From d6e506a91c0b44a932c6e6e0e2f2a1235d867fab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 3 Oct 2018 17:06:02 +0200 Subject: [PATCH 01/65] Adding Orchard Core-specific text to StartHere.txt --HG-- branch : issue/OCORE-1 --- StartHere.txt | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/StartHere.txt b/StartHere.txt index 5f282702..1b58c0e8 100644 --- a/StartHere.txt +++ b/StartHere.txt @@ -1 +1,53 @@ - \ No newline at end of file +Hi there! + + +Good to see you want to learn the ins and outs of Orchard Core module creation. Reading code is always a good way for this! + +We'll guide you on your journey to become an Orchard Core developer. Look for "NEXT STATION" comments in the code to see where +to head next, otherwise look throught the code as you like. + +Before you dive deep into this module it'd be best if you made sure that you have done the following: +* You know how ASP.NET Core works. It's important that you understand how ASP.NET Core works or + generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at + https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. +* You've read through the documentation at https://orchardcore.readthedocs.io (at least the "About Orchard Core" section, + but it would be great if you'd read the whole documentation). +* You know Orchard Core from a user's perspecive and understand the concepts underlying the system. +* If you want to be more familiar with Orchard Core fundamentals you can watch some of the following video about the + beta2 capabalities here: https://www.youtube.com/watch?v=6ZaqWmq8Pog or simply pick some of the interesting Orchard CMS + podcasts from this YouTube playlist: https://www.youtube.com/watch?v=Xu6S2XawyY4&list=PLuskKJW0FhJfOAN3dL0Y0KBMdG1pKESVn + +We've invested a lot of time creating this module. If you have ideas regarding it or have found mistakes, please let us +know on the project page: https://github.com/Lombiq/Orchard-Training-Demo-Module + +If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at Orchard +Dojo's trainings: https://orcharddojo.net/orchard-training + +Although the module has no function apart from serving as a demonstration we've written everything in a way that it really +runs and you can try it out in action. There are two ways of creating Orchard Core applications and trying out this module. +One simple way is to create an Orchard Core ASP.NET Web Application (simply follow the instructions in the Code Generation +Templates section of the documentation) and adding the Lombiq.TrainingDemo project as reference to it. The second way is +downloading the latest source of Orchard (https://github.com/OrchardCMS/OrchardCore/) and adding this module is in the +Lombiq.TrainingDemo folder under the Modules directory, opening the solution and adding the module's project to it. Don't forget +to run the solution in Debug mode and break into the code to be able to look into some specific details! + +After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules +how they solve similar tasks. If you chose to use the simpler way to add this project to Orchard Core then you should try the +other way as well to have the whole Orchard source at your hands: let it be your tutor :-). + +Later on, you may want to take a look at Map.cs (remember, "X marks the spot!") in the project root for +reminders regarding specific solutions. + +--- + +FIRST STATION: First of all, let's discuss how a .NET Standard library becomes an Orchard Module. If you look into the +Dependencies of this project you will find either a NuGet reference for the OrchardCore.Module.Targets package or if you go with +the full Orchard Core source code way you can add this particular project as a Project reference. + +On the other hand the module manifest file is also required. So... + +NEXT STATION: Head over to Manifest.cs. That file is the module's manifest; a Manifest.cs is required for Orchard modules. + + +This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session (http://www.youtube.com/watch?v=MH9mcodTX-U) +and brought to you by the Orchard Hungary team (http://english.orchardproject.hu/) and Lombiq (https://lombiq.com/). \ No newline at end of file From cefcec47dbda5bce988c5e028038bd4d3ef75d81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 3 Oct 2018 17:21:52 +0200 Subject: [PATCH 02/65] Adding documentation for Manifest.cs --HG-- branch : issue/OCORE-1 --- Manifest.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Manifest.cs b/Manifest.cs index 914a5d48..bad2af0d 100644 --- a/Manifest.cs +++ b/Manifest.cs @@ -1,10 +1,18 @@ using OrchardCore.Modules.Manifest; [assembly: Module( - Name = "Lombiq.TrainingDemo", - Author = "The Orchard Team", + // Name of the module to be displayed on the Modules page of the Dashboard. + Name = "Orchard Core Training Demo", + // Your name, company or any name that identifies the developers working on the project. + Author = "Lombiq", + // Optionally you can add a website URL (e.g. your company's website, GitHub reporitory URL). Website = "http://orchardproject.net", - Version = "0.0.1", - Description = "Lombiq.TrainingDemo", - Category = "Content Management" + // Version of the module. + Version = "2.0", + // Short description of the module. It will be displayed on the the Dashboard. + Description = "Orchard Core training demo module for teaching Orchard Core fundamentals primarily by going through its source code.", + // Modules are categorized on the Dashboard so it's a good idea to put similar modules together to a separate section. + Category = "Training" )] + +// If you're done reading throught this file go to Controllers/YourFirstOrchardCoreController. \ No newline at end of file From dd136456355974e88b42631fbc204425f4baecea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 3 Oct 2018 17:47:25 +0200 Subject: [PATCH 03/65] Adding YourFirstOrchardCoreController --HG-- branch : issue/OCORE-1 --- Controllers/HomeController.cs | 17 ---------- Controllers/YourFirstOrchardCoreController.cs | 34 +++++++++++++++++++ Views/Home/Index.cshtml | 1 - .../ActionWithRoute.cshtml | 6 ++++ Views/YourFirstOrchardCore/Index.cshtml | 10 ++++++ 5 files changed, 50 insertions(+), 18 deletions(-) delete mode 100644 Controllers/HomeController.cs create mode 100644 Controllers/YourFirstOrchardCoreController.cs delete mode 100644 Views/Home/Index.cshtml create mode 100644 Views/YourFirstOrchardCore/ActionWithRoute.cshtml create mode 100644 Views/YourFirstOrchardCore/Index.cshtml diff --git a/Controllers/HomeController.cs b/Controllers/HomeController.cs deleted file mode 100644 index 8037c496..00000000 --- a/Controllers/HomeController.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Lombiq.TrainingDemo.Controllers -{ - public class HomeController : Controller - { - public ActionResult Index() - { - return View(); - } - } -} diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs new file mode 100644 index 00000000..a8f169b8 --- /dev/null +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -0,0 +1,34 @@ +/* + * This is a controller you can find in any ASP.NET Core MVC application; Orchard is an MVC application, although much-much more + * than that. + * + * An Orchard module is basically an MVC area. You could create areas that don't interact with Orchard and you'd just + * use standard ASP.NET Core MVC skills. Of course we want more than that, so let's take a closer look. + */ + +using Microsoft.AspNetCore.Mvc; + +namespace Lombiq.TrainingDemo.Controllers +{ + public class YourFirstOrchardCoreController : Controller + { + public ActionResult Index() => + // For now we just return an empty view. This action is accessible from under + // Lombiq.TraningDemo/YourFirstOrchard/Index route (appended to your site's root path; so using defaults it + // would look something like this: + // http://localhost:44300/OrchardLocal/Lombiq.TraningDemo/YourFirstOrchard/Index) If you don't know how this + // path gets together take a second look at how ASP.NET Core MVC routing works! + View(); + + // This attribute will override the default route (see above) and use a custom one. This is also something that is an + // ASP.NET Core MVC feature but this can be used on Orchard Core controllers as well. + [Route("TrainingDemo/ActionWithRoute")] + public ActionResult ActionWithRoute() => + View(); + } +} + +/* + * If you've finished with both actions (and their .cshtml files as well), then + * NEXT STATION: Controllers/BasicOrchardCoreServicesController is what's next. + */ diff --git a/Views/Home/Index.cshtml b/Views/Home/Index.cshtml deleted file mode 100644 index abab7be9..00000000 --- a/Views/Home/Index.cshtml +++ /dev/null @@ -1 +0,0 @@ -Template \ No newline at end of file diff --git a/Views/YourFirstOrchardCore/ActionWithRoute.cshtml b/Views/YourFirstOrchardCore/ActionWithRoute.cshtml new file mode 100644 index 00000000..f43445c7 --- /dev/null +++ b/Views/YourFirstOrchardCore/ActionWithRoute.cshtml @@ -0,0 +1,6 @@ +Hello you, using custom route! + +@* + If you've finished with both actions in the YourFirstOrchardCoreController (and their .cshtml files as well), then + NEXT STATION: Controllers/BasicOrchardCoreServicesController is what's next. +*@ \ No newline at end of file diff --git a/Views/YourFirstOrchardCore/Index.cshtml b/Views/YourFirstOrchardCore/Index.cshtml new file mode 100644 index 00000000..e22e27ea --- /dev/null +++ b/Views/YourFirstOrchardCore/Index.cshtml @@ -0,0 +1,10 @@ +Hello you! + +@* + This is a view template written in the Razor language (although not much to see from Razor here). + Notice how when you open this page the above string gets injected into the layout. + This file's path and name is determined by standard ASP.NET Core MVC naming conventions. + + If you've finished with both actions in the YourFirstOrchardCoreController, then + NEXT STATION: Controllers/BasicOrchardCoreServicesController is what's next. +*@ \ No newline at end of file From 84c684388f483b010bbc4810d40f221defd3c27a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 3 Oct 2018 17:48:50 +0200 Subject: [PATCH 04/65] Removing OrchardLocal prefix --HG-- branch : issue/OCORE-1 --- Controllers/YourFirstOrchardCoreController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index a8f169b8..79d277a1 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -16,7 +16,7 @@ public ActionResult Index() => // For now we just return an empty view. This action is accessible from under // Lombiq.TraningDemo/YourFirstOrchard/Index route (appended to your site's root path; so using defaults it // would look something like this: - // http://localhost:44300/OrchardLocal/Lombiq.TraningDemo/YourFirstOrchard/Index) If you don't know how this + // http://localhost:44300/Lombiq.TraningDemo/YourFirstOrchard/Index) If you don't know how this // path gets together take a second look at how ASP.NET Core MVC routing works! View(); From 58aac889a1b7d99dbce7b79aa24e1c94e2696b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 24 Oct 2018 15:41:36 +0200 Subject: [PATCH 05/65] Updating references to use "full-source" mode --HG-- branch : issue/OCORE-1 --- Lombiq.TrainingDemo.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index 898c0c5e..99285145 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -5,15 +5,15 @@ - - - - + + - - + + + + From abf4b29e13cc4327d6e4d60a6507c3917e8b7cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 24 Oct 2018 15:45:25 +0200 Subject: [PATCH 06/65] Updating StartHere.txt --HG-- branch : issue/OCORE-1 --- StartHere.txt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/StartHere.txt b/StartHere.txt index 1b58c0e8..42a386df 100644 --- a/StartHere.txt +++ b/StartHere.txt @@ -1,4 +1,4 @@ -Hi there! +Hi there! Good to see you want to learn the ins and outs of Orchard Core module creation. Reading code is always a good way for this! @@ -25,11 +25,12 @@ Dojo's trainings: https://orcharddojo.net/orchard-training Although the module has no function apart from serving as a demonstration we've written everything in a way that it really runs and you can try it out in action. There are two ways of creating Orchard Core applications and trying out this module. -One simple way is to create an Orchard Core ASP.NET Web Application (simply follow the instructions in the Code Generation -Templates section of the documentation) and adding the Lombiq.TrainingDemo project as reference to it. The second way is -downloading the latest source of Orchard (https://github.com/OrchardCMS/OrchardCore/) and adding this module is in the -Lombiq.TrainingDemo folder under the Modules directory, opening the solution and adding the module's project to it. Don't forget -to run the solution in Debug mode and break into the code to be able to look into some specific details! +The recommended way to try this module out is to grab the full OrchardCore source and copy this module to the +src/OrchardCore.Modules folder and add it to the Solution file. The second way is to create a an Orchard Core ASP.NET Web +Application (simply follow the instructions in the Code Generation Templates section of the documentation) and adding the +Lombiq.TrainingDemo project as reference to it. If you go with the second way you need to replace project references to NuGet +package references. Don't forget to run the solution in Debug mode and break into the code to be able to look into some +specific details! After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules how they solve similar tasks. If you chose to use the simpler way to add this project to Orchard Core then you should try the From fc65ff9221992cab0a5ee8d3c64f3ae9c7284845 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Mon, 29 Oct 2018 16:50:06 +0100 Subject: [PATCH 07/65] Adding display management example --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 78 ++++++++++++++++++++++ Drivers/BookDisplayDriver.cs | 36 ++++++++++ Models/Book.cs | 22 ++++++ Startup.cs | 6 ++ Views/Book.cshtml | 14 ++++ Views/DisplayManagement/DisplayBook.cshtml | 1 + Views/Items/Book.Summary.cshtml | 5 ++ Views/Items/Book.Title.cshtml | 5 ++ Views/_ViewImports.cshtml | 10 +++ 9 files changed, 177 insertions(+) create mode 100644 Controllers/DisplayManagementController.cs create mode 100644 Drivers/BookDisplayDriver.cs create mode 100644 Models/Book.cs create mode 100644 Views/Book.cshtml create mode 100644 Views/DisplayManagement/DisplayBook.cshtml create mode 100644 Views/Items/Book.Summary.cshtml create mode 100644 Views/Items/Book.Title.cshtml create mode 100644 Views/_ViewImports.cshtml diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs new file mode 100644 index 00000000..f073e941 --- /dev/null +++ b/Controllers/DisplayManagementController.cs @@ -0,0 +1,78 @@ +/* + * In this section you will learn how Orchard Core deals with displaying different so-called shapes used for displaying various + * information to the users. This is a very huge and powerful part of Orchard Core, here you will learn the basics of Display + * Management. + * + * Firstly, to demonstrate this basic functionality, we will create a page for displaying some basic info which is part of a + * very basic object and will also add an editor for that. + * Secondly, we will see how we can split the page for multiple reusable views (i.e. shapes) using a more-or-less real-life + * example. + * + * NEXT STATION: Check the Book class to see what properties it contains. Go to Models/Book. + */ + +using Lombiq.TrainingDemo.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using OrchardCore.DisplayManagement; +using OrchardCore.DisplayManagement.ModelBinding; +using System.Threading.Tasks; + +namespace Lombiq.TrainingDemo.Controllers +{ + // Notice, that the controller implements the IUpdateModel interface. This interface encapsulates all the properties and + // methods related to ASP.NET Core MVC model binding which is already there in the Controller object so further + // implementations are not required. Orchard Core needs this model binding functionality outside the controllers (you will + // see it later). + public class DisplayManagementController : Controller, IUpdateModel + { + // For display management functionality we can use the IDisplayManager service where the T generic parameter is the + // object you want to create shapes for. + private readonly IDisplayManager _bookDisplayManager; + + + public DisplayManagementController(IHttpContextAccessor hca, IDisplayManager bookDisplayManager) + { + _bookDisplayManager = bookDisplayManager; + } + + + // First, let's see how the book summary page is generated. + public async Task DisplayBook() + { + // Since we don't store the book object in the database let's create one for demonstration purposes. + var book = CreateDemoBook(); + + // Here the shape is generated. Before going any further let's dig deeper and see what happens when this method + // is called. + // NEXT STATION: Go to Drivers/BookDisplayDriver. + var shape = await _bookDisplayManager.BuildDisplayAsync(book, this); + + return View(shape); + } + + + private Book CreateDemoBook() => + new Book + { + Title = "Harry Potter and The Sorcerer's Stone", + Author = "J.K. (Joanne) Rowling", + Summary = "Harry hasn't had a birthday party in eleven years - but all that is about to change when a mysterious " + + "letter arrives with an invitation to an incredible place.", + Excerpt = "Nearly ten years had passed since the Dursleys had woken up to find their nephew on the front step, " + + "but Privet Drive had hardly changed at all. The sun rose on the same tidy front gardens and lit up the brass " + + "number four on the Dursleys' front door; it crept into their living room, which was almost exactly the same " + + "as it had been on the night when Mr. Dursley had seen that fateful news report about the owls. Only the " + + "photographs on the mantelpiece really showed how much time had passed. Ten years ago, there had been lots of " + + "pictures of what looked like a large pink beach ball wearing different-colored bonnets - but Dudley Dursley " + + "was no longer a baby, and now the photographs showed a large blond boy riding his first bicycle, on a " + + "carousel at the fair, playing a computer game with his father, being hugged and kissed by his mother. The " + + "room held no sign at all that another boy lived in the house, too. " + }; + } +} + +/* + * If you've finished with both actions (and their .cshtml files as well), then + * NEXT STATION: Controllers/BasicOrchardCoreServicesController is what's next. + */ diff --git a/Drivers/BookDisplayDriver.cs b/Drivers/BookDisplayDriver.cs new file mode 100644 index 00000000..147cfd8a --- /dev/null +++ b/Drivers/BookDisplayDriver.cs @@ -0,0 +1,36 @@ +using Lombiq.TrainingDemo.Models; +using OrchardCore.DisplayManagement.Handlers; +using OrchardCore.DisplayManagement.Views; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; + +namespace Lombiq.TrainingDemo.Drivers +{ + // A DisplayDriver is an abstraction over all the functionality for displaying or editing a specific object that is usually + // done in the Controllers. You can create a driver for any object or contents (i.e. ContentParts or ContentFields) where + // you can implement their very specific logic for generating shapes or validating them after model binding. Furthermore, + // you can create multiple drivers for one object where all the driver methods will be executed even if the original driver + // is implemented in another (e.g. Orchard Core) module. + public class BookDisplayDriver : DisplayDriver + { + // This method gets called when building the display shape of object. If you need to call async methods here you can + // override DisplayAsync instead of this. Please note, that only one can be used since if the DisplayAsync is not + // overriden then it will be called asynchronously - either way, it will be async. + public override IDisplayResult Display(Book model) => + // For the sake of demonstration we use Combined() here. It makes it possible to return multiple shapes from + // a driver method. Use this if you'd like to return different shapes that can be used e.g. with different + // display types or you need to display specific shapes in different zones. Zones will be described really soon! + Combine( + View("Book_Title", model) + .Location("Header: 1"), + View("Book_Summary", model) + .Location("Content: 1")); + + public override IDisplayResult Edit(Book model) + { + return base.Edit(model); + } + } +} diff --git a/Models/Book.cs b/Models/Book.cs new file mode 100644 index 00000000..7d344cec --- /dev/null +++ b/Models/Book.cs @@ -0,0 +1,22 @@ +namespace Lombiq.TrainingDemo.Models +{ + public class Book + { + // Title of the book. It should be displayed on both pages. + public string Title { get; set; } + + // Author of the book. It should be displayed on both pages too. + public string Author { get; set; } + + // URL of the book cover photo. It should be displayed only on the summary page. + public string CoverPhotoUrl { get; set; } + + // Short summary of the book. It should be displayed only on the summary page. + public string Summary { get; set; } + + // A short sample from the book. It should be displayed only on the book sample page. + public string Excerpt { get; set; } + } +} + +// NEXT STATION: Now go back to Controllers/BasicDisplayManagementController. \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index fe073c6f..c4ee58ce 100644 --- a/Startup.cs +++ b/Startup.cs @@ -1,7 +1,11 @@ using System; +using Lombiq.TrainingDemo.Drivers; +using Lombiq.TrainingDemo.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; +using OrchardCore.DisplayManagement; +using OrchardCore.DisplayManagement.Handlers; using OrchardCore.Modules; namespace Lombiq.TrainingDemo @@ -10,6 +14,8 @@ public class Startup : StartupBase { public override void ConfigureServices(IServiceCollection services) { + services.AddScoped, BookDisplayDriver>(); + services.AddScoped, DisplayManager>(); } public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider) diff --git a/Views/Book.cshtml b/Views/Book.cshtml new file mode 100644 index 00000000..634c366f --- /dev/null +++ b/Views/Book.cshtml @@ -0,0 +1,14 @@ +
+ @if (Model.Header != null) + { +
+ @await DisplayAsync(Model.Header) +
+ } + @if (Model.Content != null) + { +
+ @await DisplayAsync(Model.Content) +
+ } +
\ No newline at end of file diff --git a/Views/DisplayManagement/DisplayBook.cshtml b/Views/DisplayManagement/DisplayBook.cshtml new file mode 100644 index 00000000..2df3c8df --- /dev/null +++ b/Views/DisplayManagement/DisplayBook.cshtml @@ -0,0 +1 @@ +@await DisplayAsync(Model) \ No newline at end of file diff --git a/Views/Items/Book.Summary.cshtml b/Views/Items/Book.Summary.cshtml new file mode 100644 index 00000000..8d52a5bc --- /dev/null +++ b/Views/Items/Book.Summary.cshtml @@ -0,0 +1,5 @@ +@model ShapeViewModel + +
+ @Model.Value.Summary +
\ No newline at end of file diff --git a/Views/Items/Book.Title.cshtml b/Views/Items/Book.Title.cshtml new file mode 100644 index 00000000..cc1d882f --- /dev/null +++ b/Views/Items/Book.Title.cshtml @@ -0,0 +1,5 @@ +@model ShapeViewModel + +

+ @Model.Value.Title +

\ No newline at end of file diff --git a/Views/_ViewImports.cshtml b/Views/_ViewImports.cshtml new file mode 100644 index 00000000..7583f00b --- /dev/null +++ b/Views/_ViewImports.cshtml @@ -0,0 +1,10 @@ +@inherits OrchardCore.DisplayManagement.Razor.RazorPage + +@using OrchardCore.ContentManagement.Display.ViewModels +@using OrchardCore.DisplayManagement.Views; +@using Lombiq.TrainingDemo.Models; + +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers +@addTagHelper *, OrchardCore.DisplayManagement +@addTagHelper *, OrchardCore.ResourceManagement +@addTagHelper *, OrchardCore.Contents From 625a8e08a4858bbfcffba921366275b649311f1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Tue, 13 Nov 2018 15:54:13 +0100 Subject: [PATCH 08/65] Finishing display management tutorial with documentation --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 33 ++++++++-------- Drivers/BookDisplayDriver.cs | 37 +++++++++++------- Models/Book.cs | 18 ++------- Views/Book.Description.cshtml | 22 +++++++++++ Views/Book.cshtml | 24 ++++++++---- .../DisplayBookDescription.cshtml | 1 + Views/Items/Book.Display.Author.cshtml | 5 +++ Views/Items/Book.Display.Cover.cshtml | 3 ++ ...cshtml => Book.Display.Description.cshtml} | 2 +- ...Title.cshtml => Book.Display.Title.cshtml} | 2 +- Views/_ViewImports.cshtml | 3 ++ wwwroot/HarryPotter.jpg | Bin 0 -> 40665 bytes 12 files changed, 95 insertions(+), 55 deletions(-) create mode 100644 Views/Book.Description.cshtml create mode 100644 Views/DisplayManagement/DisplayBookDescription.cshtml create mode 100644 Views/Items/Book.Display.Author.cshtml create mode 100644 Views/Items/Book.Display.Cover.cshtml rename Views/Items/{Book.Summary.cshtml => Book.Display.Description.cshtml} (63%) rename Views/Items/{Book.Title.cshtml => Book.Display.Title.cshtml} (67%) create mode 100644 wwwroot/HarryPotter.jpg diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index f073e941..2dd6889a 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -3,12 +3,7 @@ * information to the users. This is a very huge and powerful part of Orchard Core, here you will learn the basics of Display * Management. * - * Firstly, to demonstrate this basic functionality, we will create a page for displaying some basic info which is part of a - * very basic object and will also add an editor for that. - * Secondly, we will see how we can split the page for multiple reusable views (i.e. shapes) using a more-or-less real-life - * example. - * - * NEXT STATION: Check the Book class to see what properties it contains. Go to Models/Book. + * To demonstrate this basic functionality, we will create a page for displaying information about a book in two different pages. */ using Lombiq.TrainingDemo.Models; @@ -50,24 +45,30 @@ public async Task DisplayBook() return View(shape); } + + // Let's generate another Book display shape, but now with a display type. + public async Task DisplayBookDescription() + { + // Generate another book object to be used for demonstration purposes. + var book = CreateDemoBook(); + + // We can add a display type when we generate display shape. This time it will be Description. + // If display type is given then Orchard Core will search a cshtml file with a name [ObjectName].[DisplayType].cshtml. + // NEXT STATION: Go to Views/Book.Description.cshtml + var shape = await _bookDisplayManager.BuildDisplayAsync(book, this, "Description"); + + return View(shape); + } private Book CreateDemoBook() => new Book { + CoverPhotoUrl = "/Lombiq.TrainingDemo/HarryPotter.jpg", Title = "Harry Potter and The Sorcerer's Stone", Author = "J.K. (Joanne) Rowling", - Summary = "Harry hasn't had a birthday party in eleven years - but all that is about to change when a mysterious " + + Description = "Harry hasn't had a birthday party in eleven years - but all that is about to change when a mysterious " + "letter arrives with an invitation to an incredible place.", - Excerpt = "Nearly ten years had passed since the Dursleys had woken up to find their nephew on the front step, " + - "but Privet Drive had hardly changed at all. The sun rose on the same tidy front gardens and lit up the brass " + - "number four on the Dursleys' front door; it crept into their living room, which was almost exactly the same " + - "as it had been on the night when Mr. Dursley had seen that fateful news report about the owls. Only the " + - "photographs on the mantelpiece really showed how much time had passed. Ten years ago, there had been lots of " + - "pictures of what looked like a large pink beach ball wearing different-colored bonnets - but Dudley Dursley " + - "was no longer a baby, and now the photographs showed a large blond boy riding his first bicycle, on a " + - "carousel at the fair, playing a computer game with his father, being hugged and kissed by his mother. The " + - "room held no sign at all that another boy lived in the house, too. " }; } } diff --git a/Drivers/BookDisplayDriver.cs b/Drivers/BookDisplayDriver.cs index 147cfd8a..e22c0f22 100644 --- a/Drivers/BookDisplayDriver.cs +++ b/Drivers/BookDisplayDriver.cs @@ -1,18 +1,14 @@ using Lombiq.TrainingDemo.Models; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.DisplayManagement.Views; -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading.Tasks; namespace Lombiq.TrainingDemo.Drivers { // A DisplayDriver is an abstraction over all the functionality for displaying or editing a specific object that is usually // done in the Controllers. You can create a driver for any object or contents (i.e. ContentParts or ContentFields) where - // you can implement their very specific logic for generating shapes or validating them after model binding. Furthermore, - // you can create multiple drivers for one object where all the driver methods will be executed even if the original driver - // is implemented in another (e.g. Orchard Core) module. + // you can implement their very specific logic for generating reusable shapes or validating them after model binding. + // Furthermore, you can create multiple drivers for one object where all the driver methods will be executed even if the + // original driver is implemented in another (e.g. Orchard Core) module. public class BookDisplayDriver : DisplayDriver { // This method gets called when building the display shape of object. If you need to call async methods here you can @@ -21,16 +17,27 @@ public class BookDisplayDriver : DisplayDriver public override IDisplayResult Display(Book model) => // For the sake of demonstration we use Combined() here. It makes it possible to return multiple shapes from // a driver method. Use this if you'd like to return different shapes that can be used e.g. with different - // display types or you need to display specific shapes in different zones. Zones will be described really soon! + // display types or you need to display specific shapes in different zones. Zones will be described later. Combine( - View("Book_Title", model) + // Here we define a shape for the Title. The shapeType parameter will also define the default file name that + // will contain the actual markup. For this one it will be Book.Display.Title.cshtml which is located in the + // Views/Items folder. This shape will be placed in the first position of the Header zone. + View("Book_Display_Title", model) .Location("Header: 1"), - View("Book_Summary", model) - .Location("Content: 1")); + // Same applies here. This shape will be displayed in the Header zone too but in the second position. + // This way we make sure that the Title goes first. + View("Book_Display_Author", model) + .Location("Header: 2"), + // The cover photo will be in a different zone. + View("Book_Display_Cover", model) + .Location("Cover: 1"), + // The description, however, won't be displayed by default because its location targets a different display type. + // Note, that the previous shapes had no display type parameter so those will be displayed in every display type. + // This one will be displayed in the first position of the Content zone if the Book display shape will be + // generated with the Description display type. + View("Book_Display_Description", model) + .Location("Description", "Content: 1")); - public override IDisplayResult Edit(Book model) - { - return base.Edit(model); - } + // NEXT STATION: Now let's see what are those zones and how these shapes will come together! Go to Views/Book.cshtml. } } diff --git a/Models/Book.cs b/Models/Book.cs index 7d344cec..7fbfde15 100644 --- a/Models/Book.cs +++ b/Models/Book.cs @@ -1,22 +1,10 @@ -namespace Lombiq.TrainingDemo.Models +namespace Lombiq.TrainingDemo.Models { public class Book { - // Title of the book. It should be displayed on both pages. public string Title { get; set; } - - // Author of the book. It should be displayed on both pages too. public string Author { get; set; } - - // URL of the book cover photo. It should be displayed only on the summary page. public string CoverPhotoUrl { get; set; } - - // Short summary of the book. It should be displayed only on the summary page. - public string Summary { get; set; } - - // A short sample from the book. It should be displayed only on the book sample page. - public string Excerpt { get; set; } + public string Description { get; set; } } -} - -// NEXT STATION: Now go back to Controllers/BasicDisplayManagementController. \ No newline at end of file +} \ No newline at end of file diff --git a/Views/Book.Description.cshtml b/Views/Book.Description.cshtml new file mode 100644 index 00000000..11ed6a4b --- /dev/null +++ b/Views/Book.Description.cshtml @@ -0,0 +1,22 @@ +@* This is a very similar display shape for Book object, however, this one will be used only if the display type is Description. + The zone-related properties of the Model objects will be populated accordingly. *@ + +
+ @* Display Header zone if there is any shape placed in the zone. *@ + @if (Model.Header != null) + { +
+ @await DisplayAsync(Model.Header) +
+ } + + @* Display Content zone if there is any shape placed in the zone. *@ + @if (Model.Content != null) + { +
+ @await DisplayAsync(Model.Content) +
+ } +
+ +@* NEXT STATION: Go to Views/_ViewImports.cshtml *@ \ No newline at end of file diff --git a/Views/Book.cshtml b/Views/Book.cshtml index 634c366f..137d8ba0 100644 --- a/Views/Book.cshtml +++ b/Views/Book.cshtml @@ -1,14 +1,24 @@ +@* This is the display shape of any Book item if no display type given. This is generated by Orchard Core and the model + contains all the zones defined in any DisplayDrivers (remember, there can be multiple drivers for one object).*@ +
+ @* Display Cover zone if there is any shape placed in the zone. *@ + @if (Model.Cover != null) + { +
+ @await DisplayAsync(Model.Cover) +
+ } + + @* Display Header zone if there is any shape placed in the zone. *@ @if (Model.Header != null) {
@await DisplayAsync(Model.Header)
} - @if (Model.Content != null) - { -
- @await DisplayAsync(Model.Content) -
- } -
\ No newline at end of file + + @T["View Description"] + + +@* NEXT STATION: Go back to Controllers/DisplayManagementController.cs and find the DisplayBookDescription action. *@ \ No newline at end of file diff --git a/Views/DisplayManagement/DisplayBookDescription.cshtml b/Views/DisplayManagement/DisplayBookDescription.cshtml new file mode 100644 index 00000000..2df3c8df --- /dev/null +++ b/Views/DisplayManagement/DisplayBookDescription.cshtml @@ -0,0 +1 @@ +@await DisplayAsync(Model) \ No newline at end of file diff --git a/Views/Items/Book.Display.Author.cshtml b/Views/Items/Book.Display.Author.cshtml new file mode 100644 index 00000000..c724c7f3 --- /dev/null +++ b/Views/Items/Book.Display.Author.cshtml @@ -0,0 +1,5 @@ +@model ShapeViewModel + +

+ @Model.Value.Author +

\ No newline at end of file diff --git a/Views/Items/Book.Display.Cover.cshtml b/Views/Items/Book.Display.Cover.cshtml new file mode 100644 index 00000000..b8caebd5 --- /dev/null +++ b/Views/Items/Book.Display.Cover.cshtml @@ -0,0 +1,3 @@ +@model ShapeViewModel + + \ No newline at end of file diff --git a/Views/Items/Book.Summary.cshtml b/Views/Items/Book.Display.Description.cshtml similarity index 63% rename from Views/Items/Book.Summary.cshtml rename to Views/Items/Book.Display.Description.cshtml index 8d52a5bc..c67d28e6 100644 --- a/Views/Items/Book.Summary.cshtml +++ b/Views/Items/Book.Display.Description.cshtml @@ -1,5 +1,5 @@ @model ShapeViewModel
- @Model.Value.Summary + @Model.Value.Description
\ No newline at end of file diff --git a/Views/Items/Book.Title.cshtml b/Views/Items/Book.Display.Title.cshtml similarity index 67% rename from Views/Items/Book.Title.cshtml rename to Views/Items/Book.Display.Title.cshtml index cc1d882f..1d4ce857 100644 --- a/Views/Items/Book.Title.cshtml +++ b/Views/Items/Book.Display.Title.cshtml @@ -1,5 +1,5 @@ @model ShapeViewModel -

+

@Model.Value.Title

\ No newline at end of file diff --git a/Views/_ViewImports.cshtml b/Views/_ViewImports.cshtml index 7583f00b..41558a07 100644 --- a/Views/_ViewImports.cshtml +++ b/Views/_ViewImports.cshtml @@ -1,3 +1,6 @@ +@* _ViewImports.cshtml is an ASP.NET Core MVC-related feature. What is interesting to us is the Orchard Core-related usings + and tag helpers that we will possibly use in most of our shapes (.cshtml files). *@ + @inherits OrchardCore.DisplayManagement.Razor.RazorPage @using OrchardCore.ContentManagement.Display.ViewModels diff --git a/wwwroot/HarryPotter.jpg b/wwwroot/HarryPotter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..78cf684b257603a7af3563a5658d9a38ca8b8a61 GIT binary patch literal 40665 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 Y8dec_`ng)4n+%a!`wyLM%*Xlv0|n@JrvLx| literal 0 HcmV?d00001 From a2836e9418b924ca294735a4b46849d15977baae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Tue, 13 Nov 2018 16:04:05 +0100 Subject: [PATCH 09/65] Adding ViewImports station reference earlier --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 2 +- Views/DisplayManagement/DisplayBook.cshtml | 7 ++++++- Views/_ViewImports.cshtml | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index 2dd6889a..209df015 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -40,9 +40,9 @@ public async Task DisplayBook() // Here the shape is generated. Before going any further let's dig deeper and see what happens when this method // is called. - // NEXT STATION: Go to Drivers/BookDisplayDriver. var shape = await _bookDisplayManager.BuildDisplayAsync(book, this); + // NEXT STATION: Go to Views/DisplayManagement/DisplayBook.cshtml. return View(shape); } diff --git a/Views/DisplayManagement/DisplayBook.cshtml b/Views/DisplayManagement/DisplayBook.cshtml index 2df3c8df..5d26a52a 100644 --- a/Views/DisplayManagement/DisplayBook.cshtml +++ b/Views/DisplayManagement/DisplayBook.cshtml @@ -1 +1,6 @@ -@await DisplayAsync(Model) \ No newline at end of file +@* We passed the generated display shape to this view. To actually render any shapes generated in Orchard we use Display helpers. + To use these Orchard Core-related helpers in shapes we need to add a few usings and tag helpers to _ViewImports.cshtml file.*@ + +@await DisplayAsync(Model) + +@* NEXT STATION: Go to Views/_ViewImports.cshtml *@ \ No newline at end of file diff --git a/Views/_ViewImports.cshtml b/Views/_ViewImports.cshtml index 41558a07..a6c29f57 100644 --- a/Views/_ViewImports.cshtml +++ b/Views/_ViewImports.cshtml @@ -1,5 +1,5 @@ @* _ViewImports.cshtml is an ASP.NET Core MVC-related feature. What is interesting to us is the Orchard Core-related usings - and tag helpers that we will possibly use in most of our shapes (.cshtml files). *@ + and tag helpers that we will possibly use in most of our shapes (.cshtml files). *@ @inherits OrchardCore.DisplayManagement.Razor.RazorPage @@ -11,3 +11,5 @@ @addTagHelper *, OrchardCore.DisplayManagement @addTagHelper *, OrchardCore.ResourceManagement @addTagHelper *, OrchardCore.Contents + +@*NEXT STATION: Go to Drivers/BookDisplayDriver.*@ \ No newline at end of file From b20ebbb610057d10dfacdeac3260a27c3592780d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 14 Nov 2018 19:00:31 +0100 Subject: [PATCH 10/65] Adding PersonPart and its editor --HG-- branch : issue/OCORE-1 --- Drivers/PersonPartDisplayDriver.cs | 45 ++++++++++++++++++++++++++++++ Migrations.cs | 28 +++++++++++++++++++ Models/PersonPart.cs | 20 +++++++++++++ Startup.cs | 7 +++++ ViewModels/PersonPartViewModel.cs | 19 +++++++++++++ Views/PersonPart.Edit.cshtml | 23 +++++++++++++++ Views/PersonPart.cshtml | 3 ++ 7 files changed, 145 insertions(+) create mode 100644 Drivers/PersonPartDisplayDriver.cs create mode 100644 Migrations.cs create mode 100644 Models/PersonPart.cs create mode 100644 ViewModels/PersonPartViewModel.cs create mode 100644 Views/PersonPart.Edit.cshtml create mode 100644 Views/PersonPart.cshtml diff --git a/Drivers/PersonPartDisplayDriver.cs b/Drivers/PersonPartDisplayDriver.cs new file mode 100644 index 00000000..e4e87de9 --- /dev/null +++ b/Drivers/PersonPartDisplayDriver.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using Lombiq.TrainingDemo.Models; +using Lombiq.TrainingDemo.ViewModels; +using OrchardCore.ContentManagement.Display.ContentDisplay; +using OrchardCore.DisplayManagement.Handlers; +using OrchardCore.DisplayManagement.ModelBinding; +using OrchardCore.DisplayManagement.Views; + +namespace Lombiq.TrainingDemo.Drivers +{ + public class PersonPartDisplayDriver : ContentPartDisplayDriver + { + public override IDisplayResult Display(PersonPart part) + { + return View(nameof(PersonPart), part).Location("Content: 1"); + } + + public override IDisplayResult Edit(PersonPart personPart) + { + return Initialize("PersonPart_Edit", model => + { + model.PersonPart = personPart; + + model.Biography = personPart.Biography; + model.BirthDateUtc = personPart.BirthDateUtc; + model.Name = personPart.Name; + model.Sex = personPart.Sex; + }); + } + + public override async Task UpdateAsync(PersonPart model, IUpdateModel updater) + { + var viewModel = new PersonPartViewModel(); + + await updater.TryUpdateModelAsync(viewModel, Prefix); + + model.Biography = viewModel.Biography; + model.BirthDateUtc = viewModel.BirthDateUtc; + model.Name = viewModel.Name; + model.Sex = viewModel.Sex; + + return Edit(model); + } + } +} diff --git a/Migrations.cs b/Migrations.cs new file mode 100644 index 00000000..64410da4 --- /dev/null +++ b/Migrations.cs @@ -0,0 +1,28 @@ +using Lombiq.TrainingDemo.Models; +using OrchardCore.ContentManagement.Metadata; +using OrchardCore.ContentManagement.Metadata.Settings; +using OrchardCore.Data.Migration; + +namespace Lombiq.TrainingDemo +{ + public class Migrations : DataMigration + { + IContentDefinitionManager _contentDefinitionManager; + + public Migrations(IContentDefinitionManager contentDefinitionManager) + { + _contentDefinitionManager = contentDefinitionManager; + } + + public int Create() + { + _contentDefinitionManager.AlterTypeDefinition("Person", builder => builder + .Creatable() + .Listable() + .WithPart(nameof(PersonPart)) + ); + + return 1; + } + } +} \ No newline at end of file diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs new file mode 100644 index 00000000..245f3aca --- /dev/null +++ b/Models/PersonPart.cs @@ -0,0 +1,20 @@ +using System; +using OrchardCore.ContentManagement; + +namespace Lombiq.TrainingDemo.Models +{ + public class PersonPart : ContentPart + { + public string Name { get; set; } + public Sex Sex { get; set; } + public DateTime? BirthDateUtc { get; set; } + public string Biography { get; set; } + } + + + public enum Sex + { + Male, + Female + } +} \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index c4ee58ce..acc00111 100644 --- a/Startup.cs +++ b/Startup.cs @@ -4,6 +4,9 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Display.ContentDisplay; +using OrchardCore.Data.Migration; using OrchardCore.DisplayManagement; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.Modules; @@ -16,6 +19,10 @@ public override void ConfigureServices(IServiceCollection services) { services.AddScoped, BookDisplayDriver>(); services.AddScoped, DisplayManager>(); + + services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); } public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider) diff --git a/ViewModels/PersonPartViewModel.cs b/ViewModels/PersonPartViewModel.cs new file mode 100644 index 00000000..74eff33e --- /dev/null +++ b/ViewModels/PersonPartViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Lombiq.TrainingDemo.Models; +using Microsoft.AspNetCore.Mvc.ModelBinding; + +namespace Lombiq.TrainingDemo.ViewModels +{ + public class PersonPartViewModel + { + public string Name { get; set; } + public Sex Sex { get; set; } + public DateTime? BirthDateUtc { get; set; } + public string Biography { get; set; } + + [BindNever] + public PersonPart PersonPart { get; set; } + } +} diff --git a/Views/PersonPart.Edit.cshtml b/Views/PersonPart.Edit.cshtml new file mode 100644 index 00000000..5a4bfbb8 --- /dev/null +++ b/Views/PersonPart.Edit.cshtml @@ -0,0 +1,23 @@ +@model PersonPartViewModel +@using Lombiq.TrainingDemo.ViewModels; + +
+ + + @T["Person's name"] +
+ +
+ + +
+ +
+ + +
+ +
+ + +
diff --git a/Views/PersonPart.cshtml b/Views/PersonPart.cshtml new file mode 100644 index 00000000..39d53003 --- /dev/null +++ b/Views/PersonPart.cshtml @@ -0,0 +1,3 @@ +@model ShapeViewModel + +@Model.Value.Name \ No newline at end of file From be18de0ef67534c0a4ee15d6ea535bfa931c7128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 15 Nov 2018 14:45:38 +0100 Subject: [PATCH 11/65] Adding validation to PersonPartViewModel --HG-- branch : issue/OCORE-1 --- Lombiq.TrainingDemo.csproj | 1 + ViewModels/PersonPartViewModel.cs | 35 ++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index 99285145..d7761dd0 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -7,6 +7,7 @@ + diff --git a/ViewModels/PersonPartViewModel.cs b/ViewModels/PersonPartViewModel.cs index 74eff33e..f038207f 100644 --- a/ViewModels/PersonPartViewModel.cs +++ b/ViewModels/PersonPartViewModel.cs @@ -1,19 +1,48 @@ using System; using System.Collections.Generic; -using System.Text; +using System.ComponentModel.DataAnnotations; using Lombiq.TrainingDemo.Models; using Microsoft.AspNetCore.Mvc.ModelBinding; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Localization; +using OrchardCore.Modules; namespace Lombiq.TrainingDemo.ViewModels { - public class PersonPartViewModel + public class PersonPartViewModel : IValidatableObject { + [Required] public string Name { get; set; } + + [Required] public Sex Sex { get; set; } + + [Required] public DateTime? BirthDateUtc { get; set; } + public string Biography { get; set; } [BindNever] public PersonPart PersonPart { get; set; } + + + public IEnumerable Validate(ValidationContext validationContext) + { + // To use GetService overload you need to add the Microsoft.Extensions.DependencyInjection nuget package + // to your module. + var T = validationContext.GetService>(); + var clock = validationContext.GetService(); + + if (BirthDateUtc.HasValue) + { + var age = clock.UtcNow.Year - BirthDateUtc.Value.Year; + if (clock.UtcNow < BirthDateUtc.Value.AddYears(age)) age--; + + if (age < 18) + { + yield return new ValidationResult(T["The person must be 18 or older."], new[] { nameof(BirthDateUtc) }); + } + } + } } -} +} \ No newline at end of file From c86a9f2d393d3b626bade0e26b148e6c956a12b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 15 Nov 2018 18:19:16 +0100 Subject: [PATCH 12/65] Adding PersonPartIndex --HG-- branch : issue/OCORE-1 --- Controllers/PersonListAdminController.cs | 34 +++++++++++++++++++++++ Indexes/PersonPartIndex.cs | 35 ++++++++++++++++++++++++ Lombiq.TrainingDemo.csproj | 2 ++ Migrations.cs | 9 ++++++ Startup.cs | 10 +++++++ Views/PersonListAdmin/Index.cshtml | 3 ++ Views/PersonPart.Edit.cshtml | 2 +- 7 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 Controllers/PersonListAdminController.cs create mode 100644 Indexes/PersonPartIndex.cs create mode 100644 Views/PersonListAdmin/Index.cshtml diff --git a/Controllers/PersonListAdminController.cs b/Controllers/PersonListAdminController.cs new file mode 100644 index 00000000..5e7afeb3 --- /dev/null +++ b/Controllers/PersonListAdminController.cs @@ -0,0 +1,34 @@ +using Lombiq.TrainingDemo.Indexes; +using Lombiq.TrainingDemo.Models; +using Microsoft.AspNetCore.Mvc; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Records; +using OrchardCore.DisplayManagement; +using OrchardCore.DisplayManagement.ModelBinding; +using System; +using System.Threading.Tasks; +using YesSql; + +namespace Lombiq.TrainingDemo.Controllers +{ + public class PersonListAdminController : Controller, IUpdateModel + { + private readonly ISession _session; + + + public PersonListAdminController(ISession session) + { + _session = session; + } + + public async Task Index() + { + var person = await _session + .Query(index => index.BirthDateUtc < new DateTime(1990, 1, 1), true) + .With(index => index.ContentType == "Person") + .FirstOrDefaultAsync(); + + return View(person); + } + } +} \ No newline at end of file diff --git a/Indexes/PersonPartIndex.cs b/Indexes/PersonPartIndex.cs new file mode 100644 index 00000000..69fb79e0 --- /dev/null +++ b/Indexes/PersonPartIndex.cs @@ -0,0 +1,35 @@ +using System; +using Lombiq.TrainingDemo.Models; +using OrchardCore.ContentManagement; +using YesSql.Indexes; + +namespace Lombiq.TrainingDemo.Indexes +{ + public class PersonPartIndex : MapIndex + { + public string ContentItemId { get; set; } + public DateTime? BirthDateUtc { get; set; } + } + + public class PersonPartIndexProvider : IndexProvider + { + public override void Describe(DescribeContext context) + { + context.For() + .Map(contentItem => + { + var personPart = contentItem.As(); + if (personPart != null) + { + return new PersonPartIndex + { + ContentItemId = contentItem.ContentItemId, + BirthDateUtc = personPart.BirthDateUtc, + }; + } + + return null; + }); + } + } +} \ No newline at end of file diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index d7761dd0..f067d1ef 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -13,7 +13,9 @@ + + diff --git a/Migrations.cs b/Migrations.cs index 64410da4..379e23f3 100644 --- a/Migrations.cs +++ b/Migrations.cs @@ -1,3 +1,5 @@ +using System; +using Lombiq.TrainingDemo.Indexes; using Lombiq.TrainingDemo.Models; using OrchardCore.ContentManagement.Metadata; using OrchardCore.ContentManagement.Metadata.Settings; @@ -22,6 +24,13 @@ public int Create() .WithPart(nameof(PersonPart)) ); + SchemaBuilder.CreateMapIndexTable(nameof(PersonPartIndex), table => table + .Column(nameof(PersonPartIndex.BirthDateUtc)) + .Column(nameof(PersonPartIndex.ContentItemId), c => c.WithLength(26)) + ).AlterTable(nameof(PersonPartIndex), table => table + .CreateIndex($"IDX_{nameof(PersonPartIndex)}_{nameof(PersonPartIndex.BirthDateUtc)}", nameof(PersonPartIndex.BirthDateUtc)) + ); + return 1; } } diff --git a/Startup.cs b/Startup.cs index acc00111..f3d1e88a 100644 --- a/Startup.cs +++ b/Startup.cs @@ -1,5 +1,6 @@ using System; using Lombiq.TrainingDemo.Drivers; +using Lombiq.TrainingDemo.Indexes; using Lombiq.TrainingDemo.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; @@ -10,6 +11,7 @@ using OrchardCore.DisplayManagement; using OrchardCore.DisplayManagement.Handlers; using OrchardCore.Modules; +using YesSql.Indexes; namespace Lombiq.TrainingDemo { @@ -23,6 +25,7 @@ public override void ConfigureServices(IServiceCollection services) services.AddSingleton(); services.AddScoped(); services.AddScoped(); + services.AddSingleton(); } public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider) @@ -33,6 +36,13 @@ public override void Configure(IApplicationBuilder builder, IRouteBuilder routes template: "Home/Index", defaults: new { controller = "Home", action = "Index" } ); + + routes.MapAreaRoute( + name: "PersonList", + areaName: "Lombiq.TrainingDemo", + template: "Admin/PersonList", + defaults: new { controller = "PersonListAdmin", action = "Index" } + ); } } } \ No newline at end of file diff --git a/Views/PersonListAdmin/Index.cshtml b/Views/PersonListAdmin/Index.cshtml new file mode 100644 index 00000000..5fa97d88 --- /dev/null +++ b/Views/PersonListAdmin/Index.cshtml @@ -0,0 +1,3 @@ +@model OrchardCore.ContentManagement.ContentItem + +@Model \ No newline at end of file diff --git a/Views/PersonPart.Edit.cshtml b/Views/PersonPart.Edit.cshtml index 5a4bfbb8..0b5b3da7 100644 --- a/Views/PersonPart.Edit.cshtml +++ b/Views/PersonPart.Edit.cshtml @@ -13,7 +13,7 @@
- +
From a37849e8c6d90a878adff5e33e67fadb8e120d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Tue, 20 Nov 2018 15:24:37 +0100 Subject: [PATCH 13/65] Using field in PersonPart --HG-- branch : issue/OCORE-1 --- ...nController.cs => PersonListController.cs} | 12 ++++---- Drivers/PersonPartDisplayDriver.cs | 6 ++-- Lombiq.TrainingDemo.csproj | 1 + Migrations.cs | 28 +++++++++++++++++++ Models/PersonPart.cs | 3 +- Startup.cs | 12 ++++---- ViewModels/PersonPartViewModel.cs | 2 -- .../Index.cshtml | 0 Views/PersonPart.Edit.cshtml | 7 +---- Views/PersonPart.cshtml | 4 ++- 10 files changed, 50 insertions(+), 25 deletions(-) rename Controllers/{PersonListAdminController.cs => PersonListController.cs} (71%) rename Views/{PersonListAdmin => PersonList}/Index.cshtml (100%) diff --git a/Controllers/PersonListAdminController.cs b/Controllers/PersonListController.cs similarity index 71% rename from Controllers/PersonListAdminController.cs rename to Controllers/PersonListController.cs index 5e7afeb3..f6d75f77 100644 --- a/Controllers/PersonListAdminController.cs +++ b/Controllers/PersonListController.cs @@ -11,24 +11,26 @@ namespace Lombiq.TrainingDemo.Controllers { - public class PersonListAdminController : Controller, IUpdateModel + public class PersonListController : Controller, IUpdateModel { private readonly ISession _session; - public PersonListAdminController(ISession session) + public PersonListController(ISession session) { _session = session; } public async Task Index() { - var person = await _session + var persons = await _session .Query(index => index.BirthDateUtc < new DateTime(1990, 1, 1), true) .With(index => index.ContentType == "Person") - .FirstOrDefaultAsync(); + .ListAsync(); - return View(person); + //var personShapesFactory = new + + return View(persons); } } } \ No newline at end of file diff --git a/Drivers/PersonPartDisplayDriver.cs b/Drivers/PersonPartDisplayDriver.cs index e4e87de9..712e489c 100644 --- a/Drivers/PersonPartDisplayDriver.cs +++ b/Drivers/PersonPartDisplayDriver.cs @@ -20,8 +20,7 @@ public override IDisplayResult Edit(PersonPart personPart) return Initialize("PersonPart_Edit", model => { model.PersonPart = personPart; - - model.Biography = personPart.Biography; + model.BirthDateUtc = personPart.BirthDateUtc; model.Name = personPart.Name; model.Sex = personPart.Sex; @@ -33,8 +32,7 @@ public override async Task UpdateAsync(PersonPart model, IUpdate var viewModel = new PersonPartViewModel(); await updater.TryUpdateModelAsync(viewModel, Prefix); - - model.Biography = viewModel.Biography; + model.BirthDateUtc = viewModel.BirthDateUtc; model.Name = viewModel.Name; model.Sex = viewModel.Sex; diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index f067d1ef..a8806fef 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -17,6 +17,7 @@ +
diff --git a/Migrations.cs b/Migrations.cs index 379e23f3..4f357789 100644 --- a/Migrations.cs +++ b/Migrations.cs @@ -1,6 +1,8 @@ using System; using Lombiq.TrainingDemo.Indexes; using Lombiq.TrainingDemo.Models; +using OrchardCore.ContentFields.Fields; +using OrchardCore.ContentFields.Settings; using OrchardCore.ContentManagement.Metadata; using OrchardCore.ContentManagement.Metadata.Settings; using OrchardCore.Data.Migration; @@ -11,11 +13,13 @@ public class Migrations : DataMigration { IContentDefinitionManager _contentDefinitionManager; + public Migrations(IContentDefinitionManager contentDefinitionManager) { _contentDefinitionManager = contentDefinitionManager; } + public int Create() { _contentDefinitionManager.AlterTypeDefinition("Person", builder => builder @@ -24,6 +28,15 @@ public int Create() .WithPart(nameof(PersonPart)) ); + _contentDefinitionManager.AlterPartDefinition(nameof(PersonPart), part => part + .WithField(nameof(PersonPart.Biography), field => field + .OfType(nameof(TextField)) + .WithDisplayName("Biography") + .WithSettings(new TextFieldSettings + { + Required = false + }))); + SchemaBuilder.CreateMapIndexTable(nameof(PersonPartIndex), table => table .Column(nameof(PersonPartIndex.BirthDateUtc)) .Column(nameof(PersonPartIndex.ContentItemId), c => c.WithLength(26)) @@ -33,5 +46,20 @@ public int Create() return 1; } + + // For testing purposes. + public int UpdateFrom2() + { + _contentDefinitionManager.AlterPartDefinition(nameof(PersonPart), part => part + .WithField(nameof(PersonPart.Biography), field => field + .OfType(nameof(TextField)) + .WithDisplayName("Biography") + .WithSettings(new TextFieldSettings + { + Required = false + }))); + + return 3; + } } } \ No newline at end of file diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs index 245f3aca..3a384183 100644 --- a/Models/PersonPart.cs +++ b/Models/PersonPart.cs @@ -1,4 +1,5 @@ using System; +using OrchardCore.ContentFields.Fields; using OrchardCore.ContentManagement; namespace Lombiq.TrainingDemo.Models @@ -8,7 +9,7 @@ public class PersonPart : ContentPart public string Name { get; set; } public Sex Sex { get; set; } public DateTime? BirthDateUtc { get; set; } - public string Biography { get; set; } + public TextField Biography { get; set; } } diff --git a/Startup.cs b/Startup.cs index f3d1e88a..ff405a08 100644 --- a/Startup.cs +++ b/Startup.cs @@ -37,12 +37,12 @@ public override void Configure(IApplicationBuilder builder, IRouteBuilder routes defaults: new { controller = "Home", action = "Index" } ); - routes.MapAreaRoute( - name: "PersonList", - areaName: "Lombiq.TrainingDemo", - template: "Admin/PersonList", - defaults: new { controller = "PersonListAdmin", action = "Index" } - ); + //routes.MapAreaRoute( + // name: "PersonList", + // areaName: "Lombiq.TrainingDemo", + // template: "Admin/PersonList", + // defaults: new { controller = "PersonListAdmin", action = "Index" } + //); } } } \ No newline at end of file diff --git a/ViewModels/PersonPartViewModel.cs b/ViewModels/PersonPartViewModel.cs index f038207f..0127f566 100644 --- a/ViewModels/PersonPartViewModel.cs +++ b/ViewModels/PersonPartViewModel.cs @@ -20,8 +20,6 @@ public class PersonPartViewModel : IValidatableObject [Required] public DateTime? BirthDateUtc { get; set; } - public string Biography { get; set; } - [BindNever] public PersonPart PersonPart { get; set; } diff --git a/Views/PersonListAdmin/Index.cshtml b/Views/PersonList/Index.cshtml similarity index 100% rename from Views/PersonListAdmin/Index.cshtml rename to Views/PersonList/Index.cshtml diff --git a/Views/PersonPart.Edit.cshtml b/Views/PersonPart.Edit.cshtml index 0b5b3da7..b967ac21 100644 --- a/Views/PersonPart.Edit.cshtml +++ b/Views/PersonPart.Edit.cshtml @@ -15,9 +15,4 @@
-
- -
- - -
+ \ No newline at end of file diff --git a/Views/PersonPart.cshtml b/Views/PersonPart.cshtml index 39d53003..fe17a129 100644 --- a/Views/PersonPart.cshtml +++ b/Views/PersonPart.cshtml @@ -1,3 +1,5 @@ @model ShapeViewModel -@Model.Value.Name \ No newline at end of file +
@Model.Value.Name
+
@T["Birth Date: {0}", Model.Value.BirthDateUtc?.ToShortDateString()]
+
@T["Sex: {0}", Model.Value.Sex]
\ No newline at end of file From 97588a515aa8eddfdad84888ef3348953770a71a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Tue, 20 Nov 2018 21:35:33 +0100 Subject: [PATCH 14/65] Adding ColorField --HG-- branch : issue/OCORE-1 --- Drivers/ColorFieldDisplayDriver.cs | 75 ++++++++++++++++++++++++ Fields/ColorField.cs | 10 ++++ Indexing/ColorFieldIndexHandler.cs | 21 +++++++ Settings/ColorFieldSettings.cs | 9 +++ Settings/ColorFieldSettingsDriver.cs | 28 +++++++++ Startup.cs | 25 ++++++++ ViewModels/DisplayColorFieldViewModel.cs | 13 ++++ ViewModels/EditColorFieldViewModel.cs | 18 ++++++ Views/ColorField.Edit.cshtml | 21 +++++++ Views/ColorField.Option.cshtml | 4 ++ Views/ColorField.cshtml | 15 +++++ Views/ColorFieldSettings.Edit.cshtml | 24 ++++++++ 12 files changed, 263 insertions(+) create mode 100644 Drivers/ColorFieldDisplayDriver.cs create mode 100644 Fields/ColorField.cs create mode 100644 Indexing/ColorFieldIndexHandler.cs create mode 100644 Settings/ColorFieldSettings.cs create mode 100644 Settings/ColorFieldSettingsDriver.cs create mode 100644 ViewModels/DisplayColorFieldViewModel.cs create mode 100644 ViewModels/EditColorFieldViewModel.cs create mode 100644 Views/ColorField.Edit.cshtml create mode 100644 Views/ColorField.Option.cshtml create mode 100644 Views/ColorField.cshtml create mode 100644 Views/ColorFieldSettings.Edit.cshtml diff --git a/Drivers/ColorFieldDisplayDriver.cs b/Drivers/ColorFieldDisplayDriver.cs new file mode 100644 index 00000000..526e5a8f --- /dev/null +++ b/Drivers/ColorFieldDisplayDriver.cs @@ -0,0 +1,75 @@ +using System.Threading.Tasks; +using Lombiq.TrainingDemo.Fields; +using Lombiq.TrainingDemo.Settings; +using Lombiq.TrainingDemo.ViewModels; +using Microsoft.Extensions.Localization; +using OrchardCore.ContentManagement.Display.ContentDisplay; +using OrchardCore.ContentManagement.Display.Models; +using OrchardCore.ContentManagement.Metadata.Models; +using OrchardCore.DisplayManagement.ModelBinding; +using OrchardCore.DisplayManagement.Views; +using System.Text.RegularExpressions; + +namespace Lombiq.TrainingDemo.Drivers +{ + public class ColorFieldDisplayDriver : ContentFieldDisplayDriver + { + public IStringLocalizer T { get; set; } + + + public ColorFieldDisplayDriver(IStringLocalizer localizer) + { + T = localizer; + } + + + public override IDisplayResult Display(ColorField field, BuildFieldDisplayContext context) + { + return Initialize(GetDisplayShapeType(context), model => + { + model.Field = field; + model.Part = context.ContentPart; + model.PartFieldDefinition = context.PartFieldDefinition; + }) + .Location("Content") + .Location("SummaryAdmin", ""); + } + + public override IDisplayResult Edit(ColorField field, BuildFieldEditorContext context) + { + return Initialize(GetEditorShapeType(context), model => + { + model.Value = field.Value; + model.ColorName = field.ColorName; + model.Field = field; + model.Part = context.ContentPart; + model.PartFieldDefinition = context.PartFieldDefinition; + }); + } + + public override async Task UpdateAsync(ColorField field, IUpdateModel updater, UpdateFieldEditorContext context) + { + var viewModel = new EditColorFieldViewModel(); + + if (await updater.TryUpdateModelAsync(viewModel, Prefix, f => f.Value, f => f.ColorName)) + { + var settings = context.PartFieldDefinition.Settings.ToObject(); + if (settings.Required && string.IsNullOrWhiteSpace(field.Value)) + { + updater.ModelState.AddModelError(Prefix, T["A value is required for {0}.", context.PartFieldDefinition.DisplayName()]); + } + + if (!string.IsNullOrWhiteSpace(field.Value) && + !Regex.IsMatch(viewModel.Value, "^#(?:[0-9a-fA-F]{3}){1,2}$")) + { + updater.ModelState.AddModelError(Prefix, T["The given color is invalid."]); + } + + field.ColorName = viewModel.ColorName; + field.Value = viewModel.Value; + } + + return Edit(field, context); + } + } +} \ No newline at end of file diff --git a/Fields/ColorField.cs b/Fields/ColorField.cs new file mode 100644 index 00000000..c73db668 --- /dev/null +++ b/Fields/ColorField.cs @@ -0,0 +1,10 @@ +using OrchardCore.ContentManagement; + +namespace Lombiq.TrainingDemo.Fields +{ + public class ColorField : ContentField + { + public string Value { get; set; } + public string ColorName { get; set; } + } +} diff --git a/Indexing/ColorFieldIndexHandler.cs b/Indexing/ColorFieldIndexHandler.cs new file mode 100644 index 00000000..b9ed42f1 --- /dev/null +++ b/Indexing/ColorFieldIndexHandler.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; +using Lombiq.TrainingDemo.Fields; +using OrchardCore.Indexing; + +namespace Lombiq.TrainingDemo.Indexing +{ + public class ColorFieldIndexHandler : ContentFieldIndexHandler + { + public override Task BuildIndexAsync(ColorField field, BuildFieldIndexContext context) + { + var options = context.Settings.ToOptions(); + + foreach (var key in context.Keys) + { + context.DocumentIndex.Set(key, field.ColorName, options); + } + + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/Settings/ColorFieldSettings.cs b/Settings/ColorFieldSettings.cs new file mode 100644 index 00000000..06b64a79 --- /dev/null +++ b/Settings/ColorFieldSettings.cs @@ -0,0 +1,9 @@ +namespace Lombiq.TrainingDemo.Settings +{ + public class ColorFieldSettings + { + public bool Required { get; set; } + public string Hint { get; set; } + public string Label { get; set; } + } +} \ No newline at end of file diff --git a/Settings/ColorFieldSettingsDriver.cs b/Settings/ColorFieldSettingsDriver.cs new file mode 100644 index 00000000..54a4c2a3 --- /dev/null +++ b/Settings/ColorFieldSettingsDriver.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using Lombiq.TrainingDemo.Fields; +using OrchardCore.ContentManagement.Metadata.Models; +using OrchardCore.ContentTypes.Editors; +using OrchardCore.DisplayManagement.Views; + +namespace Lombiq.TrainingDemo.Settings +{ + public class ColorFieldSettingsDriver : ContentPartFieldDefinitionDisplayDriver + { + public override IDisplayResult Edit(ContentPartFieldDefinition partFieldDefinition) + { + return Initialize("ColorFieldSettings_Edit", model => partFieldDefinition.Settings.Populate(model)) + .Location("Content"); + } + + public override async Task UpdateAsync(ContentPartFieldDefinition partFieldDefinition, UpdatePartFieldEditorContext context) + { + var model = new ColorFieldSettings(); + + await context.Updater.TryUpdateModelAsync(model, Prefix); + + context.Builder.MergeSettings(model); + + return Edit(partFieldDefinition); + } + } +} \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index ff405a08..15acbc19 100644 --- a/Startup.cs +++ b/Startup.cs @@ -1,15 +1,22 @@ using System; +using Fluid; using Lombiq.TrainingDemo.Drivers; +using Lombiq.TrainingDemo.Fields; using Lombiq.TrainingDemo.Indexes; +using Lombiq.TrainingDemo.Indexing; using Lombiq.TrainingDemo.Models; +using Lombiq.TrainingDemo.Settings; +using Lombiq.TrainingDemo.ViewModels; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Display.ContentDisplay; +using OrchardCore.ContentTypes.Editors; using OrchardCore.Data.Migration; using OrchardCore.DisplayManagement; using OrchardCore.DisplayManagement.Handlers; +using OrchardCore.Indexing; using OrchardCore.Modules; using YesSql.Indexes; @@ -17,15 +24,33 @@ namespace Lombiq.TrainingDemo { public class Startup : StartupBase { + static Startup() + { + // Registering both field types and shape types are necessary as they can + // be accessed from inner properties. + + TemplateContext.GlobalMemberAccessStrategy.Register(); + TemplateContext.GlobalMemberAccessStrategy.Register(); + } + + public override void ConfigureServices(IServiceCollection services) { + // Book services.AddScoped, BookDisplayDriver>(); services.AddScoped, DisplayManager>(); + // Person Part services.AddSingleton(); services.AddScoped(); services.AddScoped(); services.AddSingleton(); + + // Color Field + services.AddSingleton(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); } public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider) diff --git a/ViewModels/DisplayColorFieldViewModel.cs b/ViewModels/DisplayColorFieldViewModel.cs new file mode 100644 index 00000000..5eb26445 --- /dev/null +++ b/ViewModels/DisplayColorFieldViewModel.cs @@ -0,0 +1,13 @@ +using Lombiq.TrainingDemo.Fields; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace Lombiq.TrainingDemo.ViewModels +{ + public class DisplayColorFieldViewModel + { + public ColorField Field { get; set; } + public ContentPart Part { get; set; } + public ContentPartFieldDefinition PartFieldDefinition { get; set; } + } +} \ No newline at end of file diff --git a/ViewModels/EditColorFieldViewModel.cs b/ViewModels/EditColorFieldViewModel.cs new file mode 100644 index 00000000..35624925 --- /dev/null +++ b/ViewModels/EditColorFieldViewModel.cs @@ -0,0 +1,18 @@ +using Lombiq.TrainingDemo.Fields; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Metadata.Models; + +namespace Lombiq.TrainingDemo.ViewModels +{ + public class EditColorFieldViewModel + { + public string ColorName { get; set; } + public string Value { get; set; } + public byte R { get; set; } + public byte G { get; set; } + public byte B { get; set; } + public ColorField Field { get; set; } + public ContentPart Part { get; set; } + public ContentPartFieldDefinition PartFieldDefinition { get; set; } + } +} \ No newline at end of file diff --git a/Views/ColorField.Edit.cshtml b/Views/ColorField.Edit.cshtml new file mode 100644 index 00000000..383f2bf5 --- /dev/null +++ b/Views/ColorField.Edit.cshtml @@ -0,0 +1,21 @@ +@model Lombiq.TrainingDemo.ViewModels.EditColorFieldViewModel +@using Lombiq.TrainingDemo.Settings; +@using OrchardCore.ContentManagement.Metadata.Models + +@{ + var settings = Model.PartFieldDefinition.Settings.ToObject(); +} + +
+ @Model.PartFieldDefinition.DisplayName() + + + + + + + @if (!String.IsNullOrEmpty(settings.Hint)) + { + @settings.Hint + } +
\ No newline at end of file diff --git a/Views/ColorField.Option.cshtml b/Views/ColorField.Option.cshtml new file mode 100644 index 00000000..039edfa0 --- /dev/null +++ b/Views/ColorField.Option.cshtml @@ -0,0 +1,4 @@ +@{ + string currentEditor = Model.Editor; +} + diff --git a/Views/ColorField.cshtml b/Views/ColorField.cshtml new file mode 100644 index 00000000..84931bd6 --- /dev/null +++ b/Views/ColorField.cshtml @@ -0,0 +1,15 @@ +@model Lombiq.TrainingDemo.ViewModels.DisplayColorFieldViewModel +@using OrchardCore.Mvc.Utilities; + +@{ + var name = (Model.PartFieldDefinition.PartDefinition.Name + "-" + Model.PartFieldDefinition.Name).HtmlClassify(); + var hex = Model.Field.Value; + if (!hex.StartsWith("#")) + { + hex = $"#{hex}"; + } +} + +
+ @Model.Field.ColorName +
\ No newline at end of file diff --git a/Views/ColorFieldSettings.Edit.cshtml b/Views/ColorFieldSettings.Edit.cshtml new file mode 100644 index 00000000..0c0bae0f --- /dev/null +++ b/Views/ColorFieldSettings.Edit.cshtml @@ -0,0 +1,24 @@ +@model Lombiq.TrainingDemo.Settings.ColorFieldSettings + +
+
+ + +
+
+ +
+
+ + + @T["The hint text to display for this field on the editor."] +
+
+ +
+
+ + + @T["The text associated to the checkbox."] +
+
\ No newline at end of file From f2f765326b44d1c402c841ac289885e58d865801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Tue, 27 Nov 2018 14:28:45 +0100 Subject: [PATCH 15/65] Adding color picker --HG-- branch : issue/OCORE-1 --- Assets/pickr/pickr.min.css | 1 + Assets/pickr/pickr.min.js | 2 + Assets/pickr/pickr.min.js.map | 1 + Controllers/PersonListController.cs | 36 ------------- Controllers/YourFirstOrchardCoreController.cs | 38 ++++++++++--- Drivers/ColorFieldDisplayDriver.cs | 2 +- Drivers/PersonPartDisplayDriver.cs | 4 +- Lombiq.TrainingDemo.csproj | 18 +++++++ Migrations.cs | 15 ------ Models/PersonPart.cs | 9 ++-- ResourceManifest.cs | 23 ++++++++ Startup.cs | 4 ++ ViewModels/EditColorFieldViewModel.cs | 3 -- ViewModels/PersonPartViewModel.cs | 2 +- Views/ColorField-ColorPicker.Edit.cshtml | 54 +++++++++++++++++++ Views/ColorField-ColorPicker.Option.cshtml | 4 ++ Views/ColorField.cshtml | 4 -- Views/PersonPart.Edit.cshtml | 6 +-- Views/PersonPart.SummaryAdmin.cshtml | 3 ++ Views/PersonPart.cshtml | 2 +- wwwroot/pickr/pickr.min.css | 1 + wwwroot/pickr/pickr.min.js | 2 + wwwroot/pickr/pickr.min.js.map | 1 + 23 files changed, 157 insertions(+), 78 deletions(-) create mode 100644 Assets/pickr/pickr.min.css create mode 100644 Assets/pickr/pickr.min.js create mode 100644 Assets/pickr/pickr.min.js.map delete mode 100644 Controllers/PersonListController.cs create mode 100644 ResourceManifest.cs create mode 100644 Views/ColorField-ColorPicker.Edit.cshtml create mode 100644 Views/ColorField-ColorPicker.Option.cshtml create mode 100644 Views/PersonPart.SummaryAdmin.cshtml create mode 100644 wwwroot/pickr/pickr.min.css create mode 100644 wwwroot/pickr/pickr.min.js create mode 100644 wwwroot/pickr/pickr.min.js.map diff --git a/Assets/pickr/pickr.min.css b/Assets/pickr/pickr.min.css new file mode 100644 index 00000000..5c8c5a6e --- /dev/null +++ b/Assets/pickr/pickr.min.css @@ -0,0 +1 @@ +.pickr{position:relative;overflow:visible;z-index:1}.pickr *{box-sizing:border-box}.pickr .pcr-button{position:relative;height:2em;width:2em;padding:.5em;border-radius:.15em;cursor:pointer;background:transparent;transition:background-color .3s;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.pickr .pcr-button:before{background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pickr .pcr-button:after,.pickr .pcr-button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%}.pickr .pcr-button:after{background:url('data:image/svg+xml;utf8, ') no-repeat 50%;background-size:70%;opacity:0}.pickr .pcr-button.clear:after{opacity:1}.pickr .pcr-button.disabled{cursor:not-allowed}.pcr-app{position:absolute;display:flex;flex-direction:column;z-index:10000;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;box-shadow:0 .2em 1.5em 0 rgba(0,0,0,.1),0 0 1em 0 rgba(0,0,0,.02);top:5px;height:15em;width:28em;max-width:95vw;padding:.8em;border-radius:.1em;background:#fff;opacity:0;visibility:hidden;transition:opacity .3s}.pcr-app.visible{visibility:visible;opacity:1}.pcr-app .pcr-interaction{display:flex;align-items:center;margin:1em -.2em 0}.pcr-app .pcr-interaction>*{margin:0 .2em}.pcr-app .pcr-interaction input{padding:.5em .6em;border:none;outline:none;letter-spacing:.07em;font-size:.75em;text-align:center;cursor:pointer;color:#c4c4c4;background:#f8f8f8;border-radius:.15em;transition:all .15s}.pcr-app .pcr-interaction input:hover{color:grey}.pcr-app .pcr-interaction .pcr-result{color:grey;text-align:left;flex-grow:1;min-width:1em;transition:all .2s;border-radius:.15em;background:#f8f8f8;cursor:text;padding-left:.8em}.pcr-app .pcr-interaction .pcr-result:focus{color:#4285f4}.pcr-app .pcr-interaction .pcr-result::selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-type.active{color:#fff;background:#4285f4}.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-save{color:#fff;width:auto}.pcr-app .pcr-interaction .pcr-save{background:#4285f4}.pcr-app .pcr-interaction .pcr-save:hover{background:#4370f4;color:#fff}.pcr-app .pcr-interaction .pcr-clear{background:#f44250}.pcr-app .pcr-interaction .pcr-clear:hover{background:#db3d49;color:#fff}.pcr-app .pcr-selection{display:flex;justify-content:space-between;flex-grow:1}.pcr-app .pcr-selection .pcr-picker{position:absolute;height:18px;width:18px;border:2px solid #fff;border-radius:100%;user-select:none;cursor:-moz-grab;cursor:-webkit-grabbing}.pcr-app .pcr-selection .pcr-color-preview{position:relative;z-index:1;width:2em;display:flex;flex-direction:column;justify-content:space-between;margin-right:.75em}.pcr-app .pcr-selection .pcr-color-preview:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{cursor:pointer;transition:background-color .3s;border-radius:.15em .15em 0 0}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color{border-radius:0 0 .15em .15em}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color,.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{background:transparent;width:100%;height:50%}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity,.pcr-app .pcr-selection .pcr-color-palette{position:relative;user-select:none;display:flex;flex-direction:column}.pcr-app .pcr-selection .pcr-color-palette{width:100%;z-index:1}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette{height:100%;border-radius:.15em}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity{margin-left:.75em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app .pcr-selection .pcr-color-opacity .pcr-picker{left:50%;transform:translateX(-50%)}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{width:8px;height:100%;border-radius:50em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider{background:linear-gradient(180deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{background:linear-gradient(180deg,transparent,#000),url('data:image/svg+xml;utf8, ');background-size:100%,50%} \ No newline at end of file diff --git a/Assets/pickr/pickr.min.js b/Assets/pickr/pickr.min.js new file mode 100644 index 00000000..0adc2483 --- /dev/null +++ b/Assets/pickr/pickr.min.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Pickr=e():t.Pickr=e()}(window,function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="dist/",n(n.s=1)}([function(t,e,n){},function(t,e,n){"use strict";n.r(e);var o={};n.r(o),n.d(o,"once",function(){return a}),n.d(o,"on",function(){return c}),n.d(o,"off",function(){return s}),n.d(o,"createElementFromString",function(){return l}),n.d(o,"removeAttribute",function(){return p}),n.d(o,"createFromTemplate",function(){return d}),n.d(o,"eventPath",function(){return h}),n.d(o,"adjustableInputNumbers",function(){return f});var r={};n.r(r),n.d(r,"hsvToRgb",function(){return b}),n.d(r,"hsvToHex",function(){return _}),n.d(r,"hsvToCmyk",function(){return w}),n.d(r,"hsvToHsl",function(){return k}),n.d(r,"parseToHSV",function(){return j});n(0);function i(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var a=function(t,e,n,o){return c(t,e,function t(){n.apply(this,arguments),this.removeEventListener(e,t)},o)},c=u.bind(null,"addEventListener"),s=u.bind(null,"removeEventListener");function u(t,e,n,o){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};return e instanceof HTMLCollection||e instanceof NodeList?e=Array.from(e):Array.isArray(e)||(e=[e]),Array.isArray(n)||(n=[n]),e.forEach(function(e){return n.forEach(function(n){return e[t](n,o,function(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{},o=p(e,"data-con"),r=p(e,"data-key");r&&(n[r]=e);for(var i=Array.from(e.children),a=o?n[o]={}:n,c=0;c1&&void 0!==arguments[1])||arguments[1],n=function(t){return t>="0"&&t<="9"||"-"===t||"."===t};function o(o){for(var r=t.value,i=t.selectionStart,a=i,c="",s=i-1;s>0&&n(r[s]);s--)c=r[s]+c,a--;for(var u=i,l=r.length;u0&&!isNaN(c)&&isFinite(c)){var p=o.deltaY<0?1:-1,d=o.ctrlKey?5*p:p,h=Number(c)+d;!e&&h<0&&(h=0);var f=r.substr(0,a)+h+r.substring(a+c.length,r.length),v=a+String(h).length;t.value=f,t.focus(),t.setSelectionRange(v,v)}o.preventDefault(),t.dispatchEvent(new Event("input"))}c(t,"focus",function(){return c(window,"wheel",o)}),c(t,"blur",function(){return s(window,"wheel",o)})}function v(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=[],o=!0,r=!1,i=void 0;try{for(var a,c=t[Symbol.iterator]();!(o=(a=c.next()).done)&&(n.push(a.value),!e||n.length!==e);o=!0);}catch(t){r=!0,i=t}finally{try{o||null==c.return||c.return()}finally{if(r)throw i}}return n}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function y(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e1&&(o-=1)}return[360*o,100*r,100*i]}function C(t,e,n,o){return e/=100,n/=100,y(A(255*(1-g(1,(t/=100)*(1-(o/=100))+o)),255*(1-g(1,e*(1-o)+o)),255*(1-g(1,n*(1-o)+o))))}function S(t,e,n){return e/=100,[t,2*(e*=(n/=100)<.5?n:1-n)/(n+e)*100,100*(n+e)]}function O(t){return A.apply(void 0,y(t.match(/.{2}/g).map(function(t){return parseInt(t,16)})))}function j(t){var e,n={cmyk:/^cmyk[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)/i,rgba:/^(rgb|rgba)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsla:/^(hsl|hsla)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsva:/^(hsv|hsva)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hex:/^#?(([\dA-Fa-f]{3,4})|([\dA-Fa-f]{6})|([\dA-Fa-f]{8}))$/i},o=function(t){return t.map(function(t){return/^(|\d+)\.\d+|\d+$/.test(t)?Number(t):void 0})};for(var r in n)if(e=n[r].exec(t))switch(r){case"cmyk":var i=v(o(e),5),a=i[1],c=i[2],s=i[3],u=i[4];if(a>100||c>100||s>100||u>100)break;return{values:y(C(a,c,s,u)).concat([1]),type:r};case"rgba":var l=v(o(e),6),p=l[2],d=l[3],h=l[4],f=l[5],g=void 0===f?1:f;if(p>255||d>255||h>255||g<0||g>1)break;return{values:y(A(p,d,h)).concat([g]),type:r};case"hex":var m=function(t,e){return[t.substring(0,e),t.substring(e,t.length)]},b=v(e,2)[1];3===b.length?b+="F":6===b.length&&(b+="FF");var _=void 0;if(4===b.length){var w=v(m(b,3).map(function(t){return t+t}),2);b=w[0],_=w[1]}else if(8===b.length){var k=v(m(b,6),2);b=k[0],_=k[1]}return _=parseInt(_,16)/255,{values:y(O(b)).concat([_]),type:r};case"hsla":var j=v(o(e),6),x=j[2],E=j[3],H=j[4],R=j[5],B=void 0===R?1:R;if(x>360||E>100||H>100||B<0||B>1)break;return{values:y(S(x,E,H)).concat([B]),type:r};case"hsva":var P=v(o(e),6),L=P[2],D=P[3],T=P[4],F=P[5],M=void 0===F?1:F;if(L>360||D>100||T>100||M<0||M>1)break;return{values:[L,D,T,M],type:r}}return{values:null,type:null}}function x(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,i=Math.ceil,a={h:t,s:e,v:n,a:o,toHSVA:function(){var t=[a.h,a.s,a.v],e=t.map(i);return t.toString=function(){return"hsva(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toHSLA:function(){var t=k(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"hsla(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toRGBA:function(){var t=b(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"rgba(".concat(e[0],", ").concat(e[1],", ").concat(e[2],", ").concat(a.a.toFixed(1),")")},t},toCMYK:function(){var t=w(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"cmyk(".concat(e[0],"%, ").concat(e[1],"%, ").concat(e[2],"%, ").concat(e[3],"%)")},t},toHEX:function(){var t=_.apply(r,[a.h,a.s,a.v]);return t.toString=function(){var e=a.a>=1?"":Number((255*a.a).toFixed(0)).toString(16).toUpperCase().padStart(2,"0");return"#".concat(t.join("").toUpperCase()+e)},t},clone:function(){return x(a.h,a.s,a.v,a.a)}};return a}function E(t){var e={options:Object.assign({lockX:!1,lockY:!1,onchange:function(){return 0}},t),_tapstart:function(t){c(document,["mouseup","touchend","touchcancel"],e._tapstop),c(document,["mousemove","touchmove"],e._tapmove),t.preventDefault(),e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove(t)},_tapmove:function(t){var n=e.options,o=e.cache,r=n.element,i=e.wrapperRect,a=0,c=0;if(t){var s=t&&t.touches&&t.touches[0];a=t?(s||t).clientX:0,c=t?(s||t).clientY:0,ai.left+i.width&&(a=i.left+i.width),ci.top+i.height&&(c=i.top+i.height),a-=i.left,c-=i.top}else o&&(a=o.x,c=o.y);n.lockX||(r.style.left=a-r.offsetWidth/2+"px"),n.lockY||(r.style.top=c-r.offsetHeight/2+"px"),e.cache={x:a,y:c},n.onchange(a,c)},_tapstop:function(){s(document,["mouseup","touchend","touchcancel"],e._tapstop),s(document,["mousemove","touchmove"],e._tapmove)},trigger:function(){e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove()},update:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove({clientX:e.wrapperRect.left+t,clientY:e.wrapperRect.top+n})},destroy:function(){var t=e.options,n=e._tapstart;s([t.wrapper,t.element],"mousedown",n),s([t.wrapper,t.element],"touchstart",n,{passive:!1})}};e.wrapperRect=e.options.wrapper.getBoundingClientRect();var n=e.options,o=e._tapstart;return c([n.wrapper,n.element],"mousedown",o),c([n.wrapper,n.element],"touchstart",o,{passive:!1}),e}function H(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e\n \n '.concat(o?"":'
','\n\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n\n
\n \n\n \n \n \n \n \n\n \n \n
\n
\n \n ")),a=i.interaction;return a.options.find(function(t){return!t.hidden&&!t.classList.add("active")}),a.type=function(){return a.options.find(function(t){return t.classList.contains("active")})},i}(t),t.useAsButton&&(t.parent||(t.parent="body"),this._root.button=t.el),document.body.appendChild(this._root.root)}},{key:"_finalBuild",value:function(){var t=this.options,e=this._root;document.body.removeChild(e.root),t.parent&&("string"==typeof t.parent&&(t.parent=document.querySelector(t.parent)),t.parent.appendChild(e.app)),t.useAsButton||t.el.parentElement.replaceChild(e.root,t.el),t.disabled&&this.disable(),t.comparison||(e.button.style.transition="none",t.useAsButton||(e.preview.lastColor.style.transition="none")),t.showAlways?e.app.classList.add("visible"):this.hide()}},{key:"_buildComponents",value:function(){var t=this,e=this.options.components,n={palette:E({element:t._root.palette.picker,wrapper:t._root.palette.palette,onchange:function(e,n){var o=t._color,r=t._root,i=t.options;o.s=e/this.wrapper.offsetWidth*100,o.v=100-n/this.wrapper.offsetHeight*100,o.v<0&&(o.v=0);var a=o.toRGBA().toString();this.element.style.background=a,this.wrapper.style.background="\n linear-gradient(to top, rgba(0, 0, 0, ".concat(o.a,"), transparent), \n linear-gradient(to left, hsla(").concat(o.h,", 100%, 50%, ").concat(o.a,"), rgba(255, 255, 255, ").concat(o.a,"))\n "),i.comparison||(r.button.style.background=a,i.useAsButton||(r.preview.lastColor.style.background=a)),r.preview.currentColor.style.background=a,t._recalc&&t._updateOutput(),r.button.classList.remove("clear")}}),hue:E({lockX:!0,element:t._root.hue.picker,wrapper:t._root.hue.slider,onchange:function(o,r){e.hue&&(t._color.h=r/this.wrapper.offsetHeight*360,this.element.style.backgroundColor="hsl(".concat(t._color.h,", 100%, 50%)"),n.palette.trigger())}}),opacity:E({lockX:!0,element:t._root.opacity.picker,wrapper:t._root.opacity.slider,onchange:function(n,o){e.opacity&&(t._color.a=Math.round(o/this.wrapper.offsetHeight*100)/100,this.element.style.background="rgba(0, 0, 0, ".concat(t._color.a,")"),t.components.palette.trigger())}}),selectable:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e={options:Object.assign({onchange:function(){return 0},className:"",elements:[]},t),_ontap:function(t){var n=e.options;n.elements.forEach(function(e){return e.classList[t.target===e?"add":"remove"](n.className)}),n.onchange(t)},destroy:function(){s(e.options.elements,"click",this._ontap)}};return c(e.options.elements,"click",e._ontap),e}({elements:t._root.interaction.options,className:"active",onchange:function(e){t._representation=e.target.getAttribute("data-type").toUpperCase(),t._updateOutput()}})};this.components=n}},{key:"_bindEvents",value:function(){var t=this,e=this._root,n=this.options,o=[c(e.interaction.clear,"click",function(){return t._clearColor()}),c(e.preview.lastColor,"click",function(){return t.setHSVA.apply(t,H(t._lastColor.toHSVA()))}),c(e.interaction.save,"click",function(){!t._saveColor()&&!n.showAlways&&t.hide()}),c(e.interaction.result,["keyup","input"],function(e){t._recalc=!1,t.setColor(e.target.value,!0)&&!t._initializingActive&&t.options.onChange(t._color,t),e.stopImmediatePropagation()}),c([e.palette.palette,e.palette.picker,e.hue.slider,e.hue.picker,e.opacity.slider,e.opacity.picker],["mousedown","touchstart"],function(){return t._recalc=!0}),c(window,"resize",function(){return t._rePositioningPicker})];if(!n.showAlways){o.push(c(e.button,"click",function(){return t.isOpen()?t.hide():t.show()}));var r=n.closeWithKey;o.push(c(document,"keyup",function(e){return t.isOpen()&&(e.key===r||e.code===r)&&t.hide()})),o.push(c(document,["touchstart","mousedown"],function(n){t.isOpen()&&!h(n).some(function(t){return t===e.app||t===e.button})&&t.hide()},{capture:!0}))}n.adjustableNumbers&&f(e.interaction.result,!1),this._eventBindings=o}},{key:"_rePositioningPicker",value:function(){var t=this._root,e=this._root.app;if(this.options.parent){var n=t.button.getBoundingClientRect();e.style.position="fixed",e.style.marginLeft="".concat(n.left,"px"),e.style.marginTop="".concat(n.top,"px")}var o=t.button.getBoundingClientRect(),r=e.getBoundingClientRect(),i=e.style;r.bottom>window.innerHeight?i.top="".concat(-r.height-5,"px"):o.bottom+r.heightwindow.innerWidth&&l-window.innerWidthwindow.innerWidth&&(s=a.left),i.left="".concat(s,"px")}},{key:"_updateOutput",value:function(){var t=this;this._root.interaction.type()&&(this._root.interaction.result.value=function(){var e="to"+t._root.interaction.type().getAttribute("data-type");return"function"==typeof t._color[e]?t._color[e]().toString():""}()),this._initializingActive||this.options.onChange(this._color,this)}},{key:"_saveColor",value:function(){var t=this._root,e=t.preview,n=t.button,o=this._color.toRGBA().toString();e.lastColor.style.background=o,this.options.useAsButton||(n.style.background=o),n.classList.remove("clear"),this._lastColor=this._color.clone(),this._initializingActive||this.options.onSave(this._color,this)}},{key:"_clearColor",value:function(){var t=this._root,e=this.options;e.useAsButton||(t.button.style.background="rgba(255, 255, 255, 0.4)"),t.button.classList.add("clear"),e.showAlways||this.hide(),e.onSave(null,this)}},{key:"destroy",value:function(){var t=this;this._eventBindings.forEach(function(t){return s.apply(o,H(t))}),Object.keys(this.components).forEach(function(e){return t.components[e].destroy()})}},{key:"destroyAndRemove",value:function(){this.destroy();var t=this._root.root;t.parentElement.removeChild(t)}},{key:"hide",value:function(){return this._root.app.classList.remove("visible"),this}},{key:"show",value:function(){if(!this.options.disabled)return this._root.app.classList.add("visible"),this._rePositioningPicker(),this}},{key:"isOpen",value:function(){return this._root.app.classList.contains("visible")}},{key:"setHSVA",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:360,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]&&arguments[4],i=this._recalc;if(this._recalc=!1,t<0||t>360||e<0||e>100||n<0||n>100||o<0||o>1)return!1;var a=this.components,c=a.hue,s=a.opacity,u=a.palette,l=c.options.wrapper.offsetHeight*(t/360);c.update(0,l);var p=s.options.wrapper.offsetHeight*o;s.update(0,p);var d=u.options.wrapper,h=d.offsetWidth*(e/100),f=d.offsetHeight*(1-n/100);return u.update(h,f),this._color=new x(t,e,n,o),this._recalc=i,this._recalc&&this._updateOutput(),r||this._saveColor(),!0}},{key:"setColor",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(null===t)return this._clearColor(),!0;var n=j(t),o=n.values,r=n.type;if(o){var i=r.toUpperCase(),a=this._root.interaction.options,c=a.find(function(t){return t.getAttribute("data-type")===i});if(!c.hidden){var s=!0,u=!1,l=void 0;try{for(var p,d=a[Symbol.iterator]();!(s=(p=d.next()).done);s=!0){var h=p.value;h.classList[h===c?"add":"remove"]("active")}}catch(t){u=!0,l=t}finally{try{s||null==d.return||d.return()}finally{if(u)throw l}}}return this.setHSVA.apply(this,H(o).concat([e]))}}},{key:"setColorRepresentation",value:function(t){return t=t.toUpperCase(),!!this._root.interaction.options.find(function(e){return e.getAttribute("data-type")===t&&!e.click()})}},{key:"getColorRepresentation",value:function(){return this._representation}},{key:"getColor",value:function(){return this._color}},{key:"getRoot",value:function(){return this._root}},{key:"disable",value:function(){return this.hide(),this.options.disabled=!0,this._root.button.classList.add("disabled"),this}},{key:"enable",value:function(){return this.options.disabled=!1,this._root.button.classList.remove("disabled"),this}}]),t}();B.utils={once:a,on:c,off:s,eventPath:h,createElementFromString:l,adjustableInputNumbers:f,removeAttribute:p,createFromTemplate:d},B.create=function(t){return new B(t)},B.version="0.3.2";e.default=B}]).default}); +//# sourceMappingURL=pickr.min.js.map \ No newline at end of file diff --git a/Assets/pickr/pickr.min.js.map b/Assets/pickr/pickr.min.js.map new file mode 100644 index 00000000..5ea5deef --- /dev/null +++ b/Assets/pickr/pickr.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap","webpack:///./src/js/lib/utils.js","webpack:///./src/js/lib/color.js","webpack:///./src/js/lib/hsvacolor.js","webpack:///./src/js/helper/moveable.js","webpack:///./src/js/pickr.js","webpack:///./src/js/helper/selectable.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","once","element","event","fn","options","on","helper","apply","this","arguments","removeEventListener","eventListener","off","method","elements","events","length","undefined","HTMLCollection","NodeList","Array","from","isArray","forEach","el","ev","_objectSpread","capture","slice","createElementFromString","html","div","document","createElement","innerHTML","trim","firstElementChild","removeAttribute","getAttribute","createFromTemplate","str","resolve","base","con","children","subtree","_i","child","arr","push","eventPath","evt","path","composedPath","target","parentElement","adjustableInputNumbers","negative","isNumChar","handleScroll","e","val","selectionStart","numStart","num","isNaN","isFinite","mul","deltaY","inc","ctrlKey","newNum","Number","newStr","substr","substring","curPos","String","focus","setSelectionRange","preventDefault","dispatchEvent","Event","min","Math","max","hsvToRgb","h","v","floor","f","q","mod","hsvToHex","map","round","toString","padStart","hsvToCmyk","k","rgb","g","b","hsvToHsl","rgbToHsv","minVal","maxVal","delta","dr","dg","db","cmykToHsv","y","_toConsumableArray","hslToHsv","hexToHsv","hex","match","parseInt","parseToHSV","regex","cmyk","rgba","hsla","hsva","numarize","array","test","type","exec","_numarize2","_slicedToArray","values","concat","_numarize4","_numarize4$","a","splitAt","alpha","_splitAt$map2","_splitAt2","_numarize6","_numarize6$","_numarize8","_numarize8$","HSVaColor","ceil","that","toHSVA","hsv","rhsv","toFixed","toHSLA","hsl","Color","rhsl","toRGBA","rrgb","toCMYK","rcmyk","toHEX","toUpperCase","join","clone","Moveable","opt","assign","lockX","lockY","onchange","_tapstart","_","_tapstop","_tapmove","wrapperRect","wrapper","getBoundingClientRect","cache","x","touch","touches","clientX","clientY","left","width","top","height","style","offsetWidth","offsetHeight","trigger","update","destroy","passive","Pickr","_classCallCheck","useAsButton","disabled","comparison","components","interaction","strings","default","defaultRepresentation","position","adjustableNumbers","showAlways","parent","closeWithKey","onChange","onSave","onClear","_initializingActive","_recalc","_color","_lastColor","_preBuild","_buildComponents","_bindEvents","setColor","_representation","setColorRepresentation","_finalBuild","_rePositioningPicker","querySelector","_root","hidden","preview","hue","opacity","keys","input","save","clear","int","find","classList","add","contains","button","body","appendChild","removeChild","app","replaceChild","disable","transition","lastColor","hide","inst","comp","palette","picker","cssRGBaString","background","currentColor","_updateOutput","remove","slider","backgroundColor","selectable","className","_ontap","Selectable","_this","eventBindings","_clearColor","setHSVA","pickr_toConsumableArray","_saveColor","result","stopImmediatePropagation","isOpen","show","ck","code","some","_eventBindings","relative","marginLeft","marginTop","bb","ab","as","bottom","innerHeight","pos","middle","right","cl","getComputedStyle","newLeft","leftClip","rightClip","innerWidth","_this2","_this$_root","_this3","args","silent","recalc","_this$components","hueY","opacityY","pickerWrapper","pickerX","pickerY","string","_Color$parseToHSV","utype","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_step","_iterator","iterator","next","done","err","return","click","utils","version"],"mappings":"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","file":"pickr.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Pickr\"] = factory();\n\telse\n\t\troot[\"Pickr\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/**\r\n * Add an eventlistener which will be fired only once.\r\n *\r\n * @param element Target element\r\n * @param event Event name\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const once = (element, event, fn, options) => on(element, event, function helper() {\r\n fn.apply(this, arguments);\r\n this.removeEventListener(event, helper);\r\n}, options);\r\n\r\n/**\r\n * Add event(s) to element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const on = eventListener.bind(null, 'addEventListener');\r\n\r\n/**\r\n * Remove event(s) from element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const off = eventListener.bind(null, 'removeEventListener');\r\n\r\nfunction eventListener(method, elements, events, fn, options = {}) {\r\n\r\n // Normalize array\r\n if (elements instanceof HTMLCollection || elements instanceof NodeList) {\r\n elements = Array.from(elements);\r\n } else if (!Array.isArray(elements)) {\r\n elements = [elements];\r\n }\r\n\r\n if (!Array.isArray(events)) {\r\n events = [events];\r\n }\r\n\r\n elements.forEach(el =>\r\n events.forEach(ev =>\r\n el[method](ev, fn, {capture: false, ...options})\r\n )\r\n );\r\n\r\n return Array.prototype.slice.call(arguments, 1);\r\n}\r\n\r\n/**\r\n * Creates an DOM-Element out of a string (Single element).\r\n * @param html HTML representing a single element\r\n * @returns {Element | null} The element.\r\n */\r\nexport function createElementFromString(html) {\r\n const div = document.createElement('div');\r\n div.innerHTML = html.trim();\r\n return div.firstElementChild;\r\n}\r\n\r\n/**\r\n * Removes an attribute from a HTMLElement and returns the value.\r\n * @param el\r\n * @param name\r\n * @return {string}\r\n */\r\nexport function removeAttribute(el, name) {\r\n const value = el.getAttribute(name);\r\n el.removeAttribute(name);\r\n return value;\r\n}\r\n\r\n/**\r\n * Creates a new html element, every element which has\r\n * a 'data-key' attribute will be saved in a object (which will be returned)\r\n * where the value of 'data-key' ist the object-key and the value the HTMLElement.\r\n *\r\n * It's possible to create a hierarchy if you add a 'data-con' attribute. Every\r\n * sibling will be added to the object which will get the name from the 'data-con' attribute.\r\n *\r\n * If you want to create an Array out of multiple elements, you can use the 'data-arr' attribute,\r\n * the value defines the key and all elements, which has the same parent and the same 'data-arr' attribute,\r\n * would be added to it.\r\n *\r\n * @param str - The HTML String.\r\n */\r\nexport function createFromTemplate(str) {\r\n\r\n // Recursive function to resolve template\r\n function resolve(element, base = {}) {\r\n\r\n // Check key and container attribute\r\n const con = removeAttribute(element, 'data-con');\r\n const key = removeAttribute(element, 'data-key');\r\n\r\n // Check and save element\r\n if (key) {\r\n base[key] = element;\r\n }\r\n\r\n // Check all children\r\n const children = Array.from(element.children);\r\n const subtree = con ? (base[con] = {}) : base;\r\n for (let child of children) {\r\n\r\n // Check if element should be saved as array\r\n const arr = removeAttribute(child, 'data-arr');\r\n if (arr) {\r\n\r\n // Check if there is already an array and add element\r\n (subtree[arr] || (subtree[arr] = [])).push(child);\r\n } else {\r\n resolve(child, subtree);\r\n }\r\n }\r\n\r\n return base;\r\n }\r\n\r\n return resolve(createElementFromString(str));\r\n}\r\n\r\n/**\r\n * Polyfill for safari & firefox for the eventPath event property.\r\n * @param evt The event object.\r\n * @return [String] event path.\r\n */\r\nexport function eventPath(evt) {\r\n let path = evt.path || (evt.composedPath && evt.composedPath());\r\n if (path) return path;\r\n\r\n let el = evt.target.parentElement;\r\n path = [evt.target, el];\r\n while (el = el.parentElement) path.push(el);\r\n\r\n path.push(document, window);\r\n return path;\r\n}\r\n\r\n/**\r\n * Creates the ability to change numbers in an input field with the scroll-wheel.\r\n * @param el\r\n * @param negative\r\n */\r\nexport function adjustableInputNumbers(el, negative = true) {\r\n\r\n // Check if a char represents a number\r\n const isNumChar = c => (c >= '0' && c <= '9') || c === '-' || c === '.';\r\n\r\n function handleScroll(e) {\r\n const val = el.value;\r\n const off = el.selectionStart;\r\n let numStart = off;\r\n let num = ''; // Will be the number as string\r\n\r\n // Look back\r\n for (let i = off - 1; i > 0 && isNumChar(val[i]); i--) {\r\n num = val[i] + num;\r\n numStart--; // Find start of number\r\n }\r\n\r\n // Look forward\r\n for (let i = off, n = val.length; i < n && isNumChar(val[i]); i++) {\r\n num += val[i];\r\n }\r\n\r\n // Check if number is valid\r\n if (num.length > 0 && !isNaN(num) && isFinite(num)) {\r\n\r\n const mul = e.deltaY < 0 ? 1 : -1;\r\n const inc = e.ctrlKey ? mul * 5 : mul;\r\n let newNum = Number(num) + inc;\r\n\r\n if (!negative && newNum < 0) {\r\n newNum = 0;\r\n }\r\n\r\n const newStr = val.substr(0, numStart) + newNum + val.substring(numStart + num.length, val.length);\r\n const curPos = numStart + String(newNum).length;\r\n\r\n // Update value and set cursor\r\n el.value = newStr;\r\n el.focus();\r\n el.setSelectionRange(curPos, curPos);\r\n }\r\n\r\n // Prevent default\r\n e.preventDefault();\r\n\r\n // Trigger input event\r\n el.dispatchEvent(new Event('input'));\r\n }\r\n\r\n // Bind events\r\n on(el, 'focus', () => on(window, 'wheel', handleScroll));\r\n on(el, 'blur', () => off(window, 'wheel', handleScroll));\r\n}","// Shorthands\r\nconst min = Math.min,\r\n max = Math.max;\r\n\r\n/**\r\n * Convert HSV spectrum to RGB.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} Array with rgb values.\r\n */\r\nexport function hsvToRgb(h, s, v) {\r\n h = (h / 360) * 6;\r\n s /= 100;\r\n v /= 100;\r\n\r\n let i = Math.floor(h);\r\n\r\n let f = h - i;\r\n let p = v * (1 - s);\r\n let q = v * (1 - f * s);\r\n let t = v * (1 - (1 - f) * s);\r\n\r\n let mod = i % 6;\r\n let r = [v, q, p, p, t, v][mod];\r\n let g = [t, v, v, q, p, p][mod];\r\n let b = [p, p, t, v, v, q][mod];\r\n\r\n return [\r\n r * 255,\r\n g * 255,\r\n b * 255\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to Hex.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {string[]} Hex values\r\n */\r\nexport function hsvToHex(h, s, v) {\r\n return hsvToRgb(h, s, v).map(v => Math.round(v).toString(16).padStart(2, '0'));\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to CMYK.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} CMYK values\r\n */\r\nexport function hsvToCmyk(h, s, v) {\r\n const rgb = hsvToRgb(h, s, v);\r\n const r = rgb[0] / 255;\r\n const g = rgb[1] / 255;\r\n const b = rgb[2] / 255;\r\n\r\n let k, c, m, y;\r\n\r\n k = min(1 - r, 1 - g, 1 - b);\r\n\r\n c = k === 1 ? 0 : (1 - r - k) / (1 - k);\r\n m = k === 1 ? 0 : (1 - g - k) / (1 - k);\r\n y = k === 1 ? 0 : (1 - b - k) / (1 - k);\r\n\r\n return [\r\n c * 100,\r\n m * 100,\r\n y * 100,\r\n k * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to HSL.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} HSL values\r\n */\r\nexport function hsvToHsl(h, s, v) {\r\n s /= 100, v /= 100;\r\n\r\n let l = (2 - s) * v / 2;\r\n\r\n if (l !== 0) {\r\n if (l === 1) {\r\n s = 0;\r\n } else if (l < 0.5) {\r\n s = s * v / (l * 2);\r\n } else {\r\n s = s * v / (2 - l * 2);\r\n }\r\n }\r\n\r\n return [\r\n h,\r\n s * 100,\r\n l * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert RGB to HSV.\r\n * @param r Red\r\n * @param g Green\r\n * @param b Blue\r\n * @return {number[]} HSV values.\r\n */\r\nfunction rgbToHsv(r, g, b) {\r\n r /= 255, g /= 255, b /= 255;\r\n\r\n let h, s, v;\r\n const minVal = min(r, g, b);\r\n const maxVal = max(r, g, b);\r\n const delta = maxVal - minVal;\r\n\r\n v = maxVal;\r\n if (delta === 0) {\r\n h = s = 0;\r\n } else {\r\n s = delta / maxVal;\r\n let dr = (((maxVal - r) / 6) + (delta / 2)) / delta;\r\n let dg = (((maxVal - g) / 6) + (delta / 2)) / delta;\r\n let db = (((maxVal - b) / 6) + (delta / 2)) / delta;\r\n\r\n if (r === maxVal) {\r\n h = db - dg;\r\n } else if (g === maxVal) {\r\n h = (1 / 3) + dr - db;\r\n } else if (b === maxVal) {\r\n h = (2 / 3) + dg - dr;\r\n }\r\n\r\n if (h < 0) {\r\n h += 1;\r\n } else if (h > 1) {\r\n h -= 1;\r\n }\r\n }\r\n\r\n return [\r\n h * 360,\r\n s * 100,\r\n v * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert CMYK to HSV.\r\n * @param c Cyan\r\n * @param m Magenta\r\n * @param y Yellow\r\n * @param k Key (Black)\r\n * @return {number[]} HSV values.\r\n */\r\nfunction cmykToHsv(c, m, y, k) {\r\n c /= 100, m /= 100, y /= 100, k /= 100;\r\n\r\n const r = (1 - min(1, c * (1 - k) + k)) * 255;\r\n const g = (1 - min(1, m * (1 - k) + k)) * 255;\r\n const b = (1 - min(1, y * (1 - k) + k)) * 255;\r\n\r\n return [...rgbToHsv(r, g, b)];\r\n}\r\n\r\n/**\r\n * Convert HSL to HSV.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param l Lightness\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hslToHsv(h, s, l) {\r\n s /= 100, l /= 100;\r\n s *= l < 0.5 ? l : 1 - l;\r\n\r\n let ns = (2 * s / (l + s)) * 100;\r\n let v = (l + s) * 100;\r\n return [h, ns, v];\r\n}\r\n\r\n/**\r\n * Convert HEX to HSV.\r\n * @param hex Hexadecimal string of rgb colors, can have length 3 or 6.\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hexToHsv(hex) {\r\n return rgbToHsv(...hex.match(/.{2}/g).map(v => parseInt(v, 16)));\r\n}\r\n\r\n/**\r\n * Try's to parse a string which represents a color to a HSV array.\r\n * Current supported types are cmyk, rgba, hsla and hexadecimal.\r\n * @param str\r\n * @return {*}\r\n */\r\nexport function parseToHSV(str) {\r\n\r\n // Regular expressions to match different types of color represention\r\n const regex = {\r\n cmyk: /^cmyk[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)/i,\r\n rgba: /^(rgb|rgba)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsla: /^(hsl|hsla)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsva: /^(hsv|hsva)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hex: /^#?(([\\dA-Fa-f]{3,4})|([\\dA-Fa-f]{6})|([\\dA-Fa-f]{8}))$/i\r\n };\r\n\r\n /**\r\n * Takes an Array of any type, convert strings which represents\r\n * a number to a number an anything else to undefined.\r\n * @param array\r\n * @return {*}\r\n */\r\n const numarize = array => array.map(v => /^(|\\d+)\\.\\d+|\\d+$/.test(v) ? Number(v) : undefined);\r\n\r\n let match;\r\n for (let type in regex) {\r\n\r\n // Check if current scheme passed\r\n if (!(match = regex[type].exec(str)))\r\n continue;\r\n\r\n // Try to convert\r\n switch (type) {\r\n case 'cmyk': {\r\n let [, c, m, y, k] = numarize(match);\r\n\r\n if (c > 100 || m > 100 || y > 100 || k > 100)\r\n break;\r\n\r\n return {values: [...cmykToHsv(c, m, y, k), 1], type};\r\n }\r\n case 'rgba': {\r\n let [, , r, g, b, a = 1] = numarize(match);\r\n\r\n if (r > 255 || g > 255 || b > 255 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...rgbToHsv(r, g, b), a], type};\r\n }\r\n case 'hex': {\r\n const splitAt = (s, i) => [s.substring(0, i), s.substring(i, s.length)];\r\n let [, hex] = match;\r\n\r\n // Fill up opacity if not declared\r\n if (hex.length === 3) {\r\n hex += 'F';\r\n } else if (hex.length === 6) {\r\n hex += 'FF';\r\n }\r\n\r\n let alpha;\r\n if (hex.length === 4) {\r\n [hex, alpha] = splitAt(hex, 3).map(v => v + v);\r\n } else if (hex.length === 8) {\r\n [hex, alpha] = splitAt(hex, 6);\r\n }\r\n\r\n // Convert 0 - 255 to 0 - 1 for opacity\r\n alpha = parseInt(alpha, 16) / 255;\r\n return {values: [...hexToHsv(hex), alpha], type};\r\n }\r\n case 'hsla': {\r\n let [, , h, s, l, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || l > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...hslToHsv(h, s, l), a], type};\r\n }\r\n case 'hsva': {\r\n let [, , h, s, v, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || v > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [h, s, v, a], type};\r\n }\r\n }\r\n }\r\n\r\n return {values: null, type: null};\r\n}","import * as Color from './color';\r\n\r\n/**\r\n * Simple class which holds the properties\r\n * of the color represention model hsla (hue saturation lightness alpha)\r\n */\r\nexport function HSVaColor(h = 0, s = 0, v = 0, a = 1) {\r\n\r\n const ceil = Math.ceil;\r\n const that = {\r\n h, s, v, a,\r\n\r\n toHSVA() {\r\n const hsv = [that.h, that.s, that.v];\r\n const rhsv = hsv.map(ceil);\r\n\r\n hsv.toString = () => `hsva(${rhsv[0]}, ${rhsv[1]}%, ${rhsv[2]}%, ${that.a.toFixed(1)})`;\r\n return hsv;\r\n },\r\n\r\n toHSLA() {\r\n const hsl = Color.hsvToHsl(that.h, that.s, that.v);\r\n const rhsl = hsl.map(ceil);\r\n\r\n hsl.toString = () => `hsla(${rhsl[0]}, ${rhsl[1]}%, ${rhsl[2]}%, ${that.a.toFixed(1)})`;\r\n return hsl;\r\n },\r\n\r\n toRGBA() {\r\n const rgb = Color.hsvToRgb(that.h, that.s, that.v);\r\n const rrgb = rgb.map(ceil);\r\n\r\n rgb.toString = () => `rgba(${rrgb[0]}, ${rrgb[1]}, ${rrgb[2]}, ${that.a.toFixed(1)})`;\r\n return rgb;\r\n },\r\n\r\n toCMYK() {\r\n const cmyk = Color.hsvToCmyk(that.h, that.s, that.v);\r\n const rcmyk = cmyk.map(ceil);\r\n\r\n cmyk.toString = () => `cmyk(${rcmyk[0]}%, ${rcmyk[1]}%, ${rcmyk[2]}%, ${rcmyk[3]}%)`;\r\n return cmyk;\r\n },\r\n\r\n toHEX() {\r\n const hex = Color.hsvToHex(...[that.h, that.s, that.v]);\r\n\r\n hex.toString = () => {\r\n\r\n // Check if alpha channel make sense, convert it to 255 number space, convert\r\n // to hex and pad it with zeros if needet.\r\n const alpha = that.a >= 1 ? '' : Number((that.a * 255).toFixed(0))\r\n .toString(16)\r\n .toUpperCase()\r\n .padStart(2, '0');\r\n\r\n return `#${hex.join('').toUpperCase() + alpha}`;\r\n };\r\n\r\n return hex;\r\n },\r\n\r\n clone() {\r\n return HSVaColor(that.h, that.s, that.v, that.a);\r\n }\r\n };\r\n\r\n return that;\r\n}","import * as _ from './../lib/utils';\r\n\r\nexport default function Moveable(opt) {\r\n\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n lockX: false,\r\n lockY: false,\r\n onchange: () => 0\r\n }, opt),\r\n\r\n _tapstart(evt) {\r\n _.on(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.on(document, ['mousemove', 'touchmove'], that._tapmove);\r\n\r\n // Prevent default touch event\r\n evt.preventDefault();\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Trigger\r\n that._tapmove(evt);\r\n },\r\n\r\n _tapmove(evt) {\r\n const {options, cache} = that;\r\n const {element} = options;\r\n const b = that.wrapperRect;\r\n\r\n let x = 0, y = 0;\r\n if (evt) {\r\n const touch = evt && evt.touches && evt.touches[0];\r\n x = evt ? (touch || evt).clientX : 0;\r\n y = evt ? (touch || evt).clientY : 0;\r\n\r\n // Reset to bounds\r\n if (x < b.left) x = b.left;\r\n else if (x > b.left + b.width) x = b.left + b.width;\r\n if (y < b.top) y = b.top;\r\n else if (y > b.top + b.height) y = b.top + b.height;\r\n\r\n // Normalize\r\n x -= b.left;\r\n y -= b.top;\r\n } else if (cache) {\r\n x = cache.x;\r\n y = cache.y;\r\n }\r\n\r\n if (!options.lockX)\r\n element.style.left = (x - element.offsetWidth / 2) + 'px';\r\n\r\n if (!options.lockY)\r\n element.style.top = (y - element.offsetHeight / 2) + 'px';\r\n\r\n that.cache = {x, y};\r\n options.onchange(x, y);\r\n },\r\n\r\n _tapstop() {\r\n _.off(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.off(document, ['mousemove', 'touchmove'], that._tapmove);\r\n },\r\n\r\n trigger() {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove();\r\n },\r\n\r\n update(x = 0, y = 0) {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove({\r\n clientX: that.wrapperRect.left + x,\r\n clientY: that.wrapperRect.top + y\r\n });\r\n },\r\n\r\n destroy() {\r\n const {options, _tapstart} = that;\r\n _.off([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.off([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n }\r\n };\r\n\r\n // Instance var\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Initilize\r\n const {options, _tapstart} = that;\r\n _.on([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.on([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n\r\n return that;\r\n}","// Import styles\r\nimport '../scss/pickr.scss';\r\n\r\n// Import utils\r\nimport * as _ from './lib/utils';\r\nimport * as Color from './lib/color';\r\n\r\n// Import classes\r\nimport {HSVaColor} from './lib/hsvacolor';\r\nimport Moveable from './helper/moveable';\r\nimport Selectable from './helper/selectable';\r\n\r\nclass Pickr {\r\n\r\n constructor(opt) {\r\n\r\n // Assign default values\r\n this.options = Object.assign({\r\n useAsButton: false,\r\n disabled: false,\r\n comparison: true,\r\n\r\n components: {interaction: {}},\r\n strings: {},\r\n\r\n default: 'fff',\r\n defaultRepresentation: 'HEX',\r\n position: 'middle',\r\n adjustableNumbers: true,\r\n showAlways: false,\r\n parent: undefined,\r\n\r\n closeWithKey: 'Escape',\r\n onChange: () => 0,\r\n onSave: () => 0,\r\n onClear: () => 0\r\n }, opt);\r\n\r\n // Check interaction section\r\n if (!this.options.components.interaction) {\r\n this.options.components.interaction = {};\r\n }\r\n\r\n // Will be used to prevent specific actions during initilization\r\n this._initializingActive = true;\r\n\r\n // Replace element with color picker\r\n this._recalc = true;\r\n\r\n // Current and last color for comparison\r\n this._color = new HSVaColor();\r\n this._lastColor = new HSVaColor();\r\n\r\n // Initialize picker\r\n this._preBuild();\r\n this._buildComponents();\r\n this._bindEvents();\r\n\r\n // Initialize color\r\n this.setColor(this.options.default);\r\n\r\n // Initialize color _epresentation\r\n this._representation = this.options.defaultRepresentation;\r\n this.setColorRepresentation(this._representation);\r\n\r\n // Initilization is finish, pickr is visible and ready to use\r\n this._initializingActive = false;\r\n\r\n // Finalize build\r\n this._finalBuild();\r\n this._rePositioningPicker();\r\n }\r\n\r\n // Does only the absolutly basic thing to initialize the components\r\n _preBuild() {\r\n const opt = this.options;\r\n\r\n // Check if element is selector\r\n if (typeof opt.el === 'string') {\r\n opt.el = document.querySelector(opt.el);\r\n }\r\n\r\n // Create element and append it to body to\r\n // prevent initialization errors\r\n this._root = create(opt);\r\n\r\n // Check if a custom button is used\r\n if (opt.useAsButton) {\r\n\r\n // Check if the user has an alternative location defined, used body as fallback\r\n if (!opt.parent) {\r\n opt.parent = 'body';\r\n }\r\n\r\n this._root.button = opt.el; // Replace button with customized button\r\n }\r\n\r\n document.body.appendChild(this._root.root);\r\n }\r\n\r\n _finalBuild() {\r\n const opt = this.options;\r\n const root = this._root;\r\n\r\n // Remove from body\r\n document.body.removeChild(root.root);\r\n\r\n // Check parent option\r\n if (opt.parent) {\r\n\r\n // Check if element is selector\r\n if (typeof opt.parent === 'string') {\r\n opt.parent = document.querySelector(opt.parent);\r\n }\r\n\r\n opt.parent.appendChild(root.app);\r\n }\r\n\r\n // Don't replace the the element if a custom button is used\r\n if (!opt.useAsButton) {\r\n\r\n // Replace element with actual color-picker\r\n opt.el.parentElement.replaceChild(root.root, opt.el);\r\n }\r\n\r\n // Call disable to also add the disabled class\r\n if (opt.disabled) {\r\n this.disable();\r\n }\r\n\r\n // Check if color comparison is disabled, if yes - remove transitions so everything keeps smoothly\r\n if (!opt.comparison) {\r\n root.button.style.transition = 'none';\r\n if (!opt.useAsButton) {\r\n root.preview.lastColor.style.transition = 'none';\r\n }\r\n }\r\n\r\n // Check showAlways option\r\n opt.showAlways ? root.app.classList.add('visible') : this.hide();\r\n }\r\n\r\n _buildComponents() {\r\n\r\n // Instance reference\r\n const inst = this;\r\n const comp = this.options.components;\r\n\r\n const components = {\r\n\r\n palette: Moveable({\r\n element: inst._root.palette.picker,\r\n wrapper: inst._root.palette.palette,\r\n\r\n onchange(x, y) {\r\n const {_color, _root, options} = inst;\r\n\r\n // Calculate saturation based on the position\r\n _color.s = (x / this.wrapper.offsetWidth) * 100;\r\n\r\n // Calculate the value\r\n _color.v = 100 - (y / this.wrapper.offsetHeight) * 100;\r\n\r\n // Prevent falling under zero\r\n _color.v < 0 ? _color.v = 0 : 0;\r\n\r\n // Set picker and gradient color\r\n const cssRGBaString = _color.toRGBA().toString();\r\n this.element.style.background = cssRGBaString;\r\n this.wrapper.style.background = `\r\n linear-gradient(to top, rgba(0, 0, 0, ${_color.a}), transparent), \r\n linear-gradient(to left, hsla(${_color.h}, 100%, 50%, ${_color.a}), rgba(255, 255, 255, ${_color.a}))\r\n `;\r\n\r\n // Check if color is locked\r\n if (!options.comparison) {\r\n _root.button.style.background = cssRGBaString;\r\n\r\n if (!options.useAsButton) {\r\n _root.preview.lastColor.style.background = cssRGBaString;\r\n }\r\n }\r\n\r\n // Change current color\r\n _root.preview.currentColor.style.background = cssRGBaString;\r\n\r\n // Update the input field only if the user is currently not typing\r\n if (inst._recalc) {\r\n inst._updateOutput();\r\n }\r\n\r\n // If the user changes the color, remove the cleared icon\r\n _root.button.classList.remove('clear');\r\n }\r\n }),\r\n\r\n hue: Moveable({\r\n lockX: true,\r\n element: inst._root.hue.picker,\r\n wrapper: inst._root.hue.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.hue) return;\r\n\r\n // Calculate hue\r\n inst._color.h = (y / this.wrapper.offsetHeight) * 360;\r\n\r\n // Update color\r\n this.element.style.backgroundColor = `hsl(${inst._color.h}, 100%, 50%)`;\r\n components.palette.trigger();\r\n }\r\n }),\r\n\r\n opacity: Moveable({\r\n lockX: true,\r\n element: inst._root.opacity.picker,\r\n wrapper: inst._root.opacity.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.opacity) return;\r\n\r\n // Calculate opacity\r\n inst._color.a = Math.round(((y / this.wrapper.offsetHeight)) * 1e2) / 100;\r\n\r\n // Update color\r\n this.element.style.background = `rgba(0, 0, 0, ${inst._color.a})`;\r\n inst.components.palette.trigger();\r\n }\r\n }),\r\n\r\n selectable: Selectable({\r\n elements: inst._root.interaction.options,\r\n className: 'active',\r\n onchange(e) {\r\n inst._representation = e.target.getAttribute('data-type').toUpperCase();\r\n inst._updateOutput();\r\n }\r\n })\r\n };\r\n\r\n this.components = components;\r\n }\r\n\r\n _bindEvents() {\r\n const {_root, options} = this;\r\n\r\n const eventBindings = [\r\n\r\n // Clear color\r\n _.on(_root.interaction.clear, 'click', () => this._clearColor()),\r\n\r\n // Select last color on click\r\n _.on(_root.preview.lastColor, 'click', () => this.setHSVA(...this._lastColor.toHSVA())),\r\n\r\n // Save color\r\n _.on(_root.interaction.save, 'click', () => {\r\n !this._saveColor() && !options.showAlways && this.hide();\r\n }),\r\n\r\n // Detect user input and disable auto-recalculation\r\n _.on(_root.interaction.result, ['keyup', 'input'], e => {\r\n this._recalc = false;\r\n\r\n // Fire listener if initialization is finish and changed color was valid\r\n if (this.setColor(e.target.value, true) && !this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n\r\n e.stopImmediatePropagation();\r\n }),\r\n\r\n // Cancel input detection on color change\r\n _.on([\r\n _root.palette.palette,\r\n _root.palette.picker,\r\n _root.hue.slider,\r\n _root.hue.picker,\r\n _root.opacity.slider,\r\n _root.opacity.picker\r\n ], ['mousedown', 'touchstart'], () => this._recalc = true),\r\n\r\n // Repositioning on resize\r\n _.on(window, 'resize', () => this._rePositioningPicker)\r\n ];\r\n\r\n // Provide hiding / showing abilities only if showAlways is false\r\n if (!options.showAlways) {\r\n\r\n // Save and hide / show picker\r\n eventBindings.push(_.on(_root.button, 'click', () => this.isOpen() ? this.hide() : this.show()));\r\n\r\n // Close with escape key\r\n const ck = options.closeWithKey;\r\n eventBindings.push(_.on(document, 'keyup', e => this.isOpen() && (e.key === ck || e.code === ck) && this.hide()));\r\n\r\n // Cancel selecting if the user taps behind the color picker\r\n eventBindings.push(_.on(document, ['touchstart', 'mousedown'], e => {\r\n if (this.isOpen() && !_.eventPath(e).some(el => el === _root.app || el === _root.button)) {\r\n this.hide();\r\n }\r\n }, {capture: true}));\r\n }\r\n\r\n // Make input adjustable if enabled\r\n if (options.adjustableNumbers) {\r\n _.adjustableInputNumbers(_root.interaction.result, false);\r\n }\r\n\r\n // Save bindings\r\n this._eventBindings = eventBindings;\r\n }\r\n\r\n _rePositioningPicker() {\r\n const root = this._root;\r\n const app = this._root.app;\r\n\r\n // Check if user has defined a parent\r\n if (this.options.parent) {\r\n const relative = root.button.getBoundingClientRect();\r\n app.style.position = 'fixed';\r\n app.style.marginLeft = `${relative.left}px`;\r\n app.style.marginTop = `${relative.top}px`;\r\n }\r\n\r\n const bb = root.button.getBoundingClientRect();\r\n const ab = app.getBoundingClientRect();\r\n const as = app.style;\r\n\r\n // Check if picker is cuttet of from the top & bottom\r\n if (ab.bottom > window.innerHeight) {\r\n as.top = `${-(ab.height) - 5}px`;\r\n } else if (bb.bottom + ab.height < window.innerHeight) {\r\n as.top = `${bb.height + 5}px`;\r\n }\r\n\r\n // Positioning picker on the x-axis\r\n const pos = {\r\n left: -(ab.width) + bb.width,\r\n middle: -(ab.width / 2) + bb.width / 2,\r\n right: 0\r\n };\r\n\r\n const cl = parseInt(getComputedStyle(app).left, 10);\r\n let newLeft = pos[this.options.position];\r\n const leftClip = (ab.left - cl) + newLeft;\r\n const rightClip = (ab.left - cl) + newLeft + ab.width;\r\n\r\n /**\r\n * First check if position is left or right but\r\n * pickr-app cannot set to left AND right because it would\r\n * be clipped by the browser width. If so, wrap it and position\r\n * pickr below button via the pos[middle] value.\r\n * The current selected posiotion should'nt be the middle.di\r\n */\r\n if (this.options.position !== 'middle' && (\r\n (leftClip < 0 && -leftClip < ab.width / 2) ||\r\n (rightClip > window.innerWidth && rightClip - window.innerWidth < ab.width / 2))) {\r\n newLeft = pos['middle'];\r\n\r\n /**\r\n * Even if set to middle pickr is getting clipped, so\r\n * set it to left / right.\r\n */\r\n } else if (leftClip < 0) {\r\n newLeft = pos['right'];\r\n } else if (rightClip > window.innerWidth) {\r\n newLeft = pos['left'];\r\n }\r\n\r\n as.left = `${newLeft}px`;\r\n }\r\n\r\n _updateOutput() {\r\n\r\n // Check if component is present\r\n if (this._root.interaction.type()) {\r\n\r\n this._root.interaction.result.value = (() => {\r\n\r\n // Construct function name and call if present\r\n const method = 'to' + this._root.interaction.type().getAttribute('data-type');\r\n return typeof this._color[method] === 'function' ? this._color[method]().toString() : '';\r\n })();\r\n }\r\n\r\n // Fire listener if initialization is finish\r\n if (!this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n }\r\n\r\n _saveColor() {\r\n const {preview, button} = this._root;\r\n\r\n // Change preview and current color\r\n const cssRGBaString = this._color.toRGBA().toString();\r\n preview.lastColor.style.background = cssRGBaString;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!this.options.useAsButton) {\r\n button.style.background = cssRGBaString;\r\n }\r\n\r\n // User changed the color so remove the clear clas\r\n button.classList.remove('clear');\r\n\r\n // Save last color\r\n this._lastColor = this._color.clone();\r\n\r\n // Fire listener\r\n if (!this._initializingActive) {\r\n this.options.onSave(this._color, this);\r\n }\r\n }\r\n\r\n _clearColor() {\r\n const {_root, options} = this;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!options.useAsButton) {\r\n _root.button.style.background = 'rgba(255, 255, 255, 0.4)';\r\n }\r\n\r\n _root.button.classList.add('clear');\r\n\r\n if (!options.showAlways) {\r\n this.hide();\r\n }\r\n\r\n // Fire listener\r\n options.onSave(null, this);\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys\r\n */\r\n destroy() {\r\n this._eventBindings.forEach(args => _.off(...args));\r\n Object.keys(this.components).forEach(key => this.components[key].destroy());\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys and removes\r\n * the pickr element.\r\n */\r\n destroyAndRemove() {\r\n this.destroy();\r\n\r\n // Remove element\r\n const root = this._root.root;\r\n root.parentElement.removeChild(root);\r\n }\r\n\r\n /**\r\n * Hides the color-picker ui.\r\n */\r\n hide() {\r\n this._root.app.classList.remove('visible');\r\n return this;\r\n }\r\n\r\n /**\r\n * Shows the color-picker ui.\r\n */\r\n show() {\r\n if (this.options.disabled) return;\r\n this._root.app.classList.add('visible');\r\n this._rePositioningPicker();\r\n return this;\r\n }\r\n\r\n /**\r\n * @return {boolean} If the color picker is currently open\r\n */\r\n isOpen() {\r\n return this._root.app.classList.contains('visible');\r\n }\r\n\r\n /**\r\n * Set a specific color.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @param a Alpha channel (0 - 1)\r\n * @param silent If the button should not change the color\r\n * @return true if the color has been accepted\r\n */\r\n setHSVA(h = 360, s = 0, v = 0, a = 1, silent = false) {\r\n\r\n // Deactivate color calculation\r\n const recalc = this._recalc; // Save state\r\n this._recalc = false;\r\n\r\n // Validate input\r\n if (h < 0 || h > 360 || s < 0 || s > 100 || v < 0 || v > 100 || a < 0 || a > 1) {\r\n return false;\r\n }\r\n\r\n // Short names\r\n const {hue, opacity, palette} = this.components;\r\n\r\n // Calculate y position of hue slider\r\n const hueWrapper = hue.options.wrapper;\r\n const hueY = hueWrapper.offsetHeight * (h / 360);\r\n hue.update(0, hueY);\r\n\r\n // Calculate y position of opacity slider\r\n const opacityWrapper = opacity.options.wrapper;\r\n const opacityY = opacityWrapper.offsetHeight * a;\r\n opacity.update(0, opacityY);\r\n\r\n // Calculate y and x position of color palette\r\n const pickerWrapper = palette.options.wrapper;\r\n const pickerX = pickerWrapper.offsetWidth * (s / 100);\r\n const pickerY = pickerWrapper.offsetHeight * (1 - (v / 100));\r\n palette.update(pickerX, pickerY);\r\n\r\n // Override current color and re-active color calculation\r\n this._color = new HSVaColor(h, s, v, a);\r\n this._recalc = recalc; // Restore old state\r\n\r\n // Update output if recalculation is enabled\r\n if (this._recalc) {\r\n this._updateOutput();\r\n }\r\n\r\n // Check if call is silent\r\n if (!silent) {\r\n this._saveColor();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Tries to parse a string which represents a color.\r\n * Examples: #fff\r\n * rgb 10 10 200\r\n * hsva 10 20 5 0.5\r\n * @param string\r\n * @param silent\r\n */\r\n setColor(string, silent = false) {\r\n\r\n // Check if null\r\n if (string === null) {\r\n this._clearColor();\r\n return true;\r\n }\r\n\r\n const {values, type} = Color.parseToHSV(string);\r\n\r\n // Check if color is ok\r\n if (values) {\r\n\r\n // Change selected color format\r\n const utype = type.toUpperCase();\r\n const {options} = this._root.interaction;\r\n const target = options.find(el => el.getAttribute('data-type') === utype);\r\n\r\n // Auto select only if not hidden\r\n if (!target.hidden) {\r\n for (const el of options) {\r\n el.classList[el === target ? 'add' : 'remove']('active');\r\n }\r\n }\r\n\r\n return this.setHSVA(...values, silent);\r\n }\r\n }\r\n\r\n /**\r\n * Changes the color _representation.\r\n * Allowed values are HEX, RGBA, HSVA, HSLA and CMYK\r\n * @param type\r\n * @returns {boolean} if the selected type was valid.\r\n */\r\n setColorRepresentation(type) {\r\n\r\n // Force uppercase to allow a case-sensitiv comparison\r\n type = type.toUpperCase();\r\n\r\n // Find button with given type and trigger click event\r\n return !!this._root.interaction.options.find(v => v.getAttribute('data-type') === type && !v.click());\r\n }\r\n\r\n /**\r\n * Returns the current color representaion. See setColorRepresentation\r\n * @returns {*}\r\n */\r\n getColorRepresentation() {\r\n return this._representation;\r\n }\r\n\r\n /**\r\n * @returns HSVaColor Current HSVaColor object.\r\n */\r\n getColor() {\r\n return this._color;\r\n }\r\n\r\n /**\r\n * @returns The root HTMLElement with all his components.\r\n */\r\n getRoot() {\r\n return this._root;\r\n }\r\n\r\n /**\r\n * Disable pickr\r\n */\r\n disable() {\r\n this.hide();\r\n this.options.disabled = true;\r\n this._root.button.classList.add('disabled');\r\n return this;\r\n }\r\n\r\n /**\r\n * Enable pickr\r\n */\r\n enable() {\r\n this.options.disabled = false;\r\n this._root.button.classList.remove('disabled');\r\n return this;\r\n }\r\n}\r\n\r\nfunction create(options) {\r\n const {components, strings, useAsButton} = options;\r\n const hidden = con => con ? '' : 'style=\"display:none\" hidden';\r\n\r\n const root = _.createFromTemplate(`\r\n
\r\n \r\n ${useAsButton ? '' : '
'}\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n
\r\n
\r\n
\r\n `);\r\n\r\n const int = root.interaction;\r\n\r\n // Select option which is not hidden\r\n int.options.find(o => !o.hidden && !o.classList.add('active'));\r\n\r\n // Create method to find currenlty active option\r\n int.type = () => int.options.find(e => e.classList.contains('active'));\r\n return root;\r\n}\r\n\r\n// Static methods\r\nPickr.utils = {\r\n once: _.once,\r\n on: _.on,\r\n off: _.off,\r\n eventPath: _.eventPath,\r\n createElementFromString: _.createElementFromString,\r\n adjustableInputNumbers: _.adjustableInputNumbers,\r\n removeAttribute: _.removeAttribute,\r\n createFromTemplate: _.createFromTemplate\r\n};\r\n\r\n// Create instance via method\r\nPickr.create = (options) => new Pickr(options);\r\n\r\n// Export\r\nPickr.version = '0.3.2';\r\nexport default Pickr;","import * as _ from './../lib/utils';\r\n\r\nexport default function Selectable(opt = {}) {\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n onchange: () => 0,\r\n className: '',\r\n elements: []\r\n }, opt),\r\n\r\n _ontap(evt) {\r\n const opt = that.options;\r\n opt.elements.forEach(e =>\r\n e.classList[evt.target === e ? 'add' : 'remove'](opt.className)\r\n );\r\n\r\n opt.onchange(evt);\r\n },\r\n\r\n destroy() {\r\n _.off(that.options.elements, 'click', this._ontap);\r\n }\r\n };\r\n\r\n _.on(that.options.elements, 'click', that._ontap);\r\n return that;\r\n}"],"sourceRoot":""} \ No newline at end of file diff --git a/Controllers/PersonListController.cs b/Controllers/PersonListController.cs deleted file mode 100644 index f6d75f77..00000000 --- a/Controllers/PersonListController.cs +++ /dev/null @@ -1,36 +0,0 @@ -using Lombiq.TrainingDemo.Indexes; -using Lombiq.TrainingDemo.Models; -using Microsoft.AspNetCore.Mvc; -using OrchardCore.ContentManagement; -using OrchardCore.ContentManagement.Records; -using OrchardCore.DisplayManagement; -using OrchardCore.DisplayManagement.ModelBinding; -using System; -using System.Threading.Tasks; -using YesSql; - -namespace Lombiq.TrainingDemo.Controllers -{ - public class PersonListController : Controller, IUpdateModel - { - private readonly ISession _session; - - - public PersonListController(ISession session) - { - _session = session; - } - - public async Task Index() - { - var persons = await _session - .Query(index => index.BirthDateUtc < new DateTime(1990, 1, 1), true) - .With(index => index.ContentType == "Person") - .ListAsync(); - - //var personShapesFactory = new - - return View(persons); - } - } -} \ No newline at end of file diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index 79d277a1..d6ed5738 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -1,30 +1,54 @@ -/* +/* * This is a controller you can find in any ASP.NET Core MVC application; Orchard is an MVC application, although much-much more * than that. * - * An Orchard module is basically an MVC area. You could create areas that don't interact with Orchard and you'd just - * use standard ASP.NET Core MVC skills. Of course we want more than that, so let's take a closer look. + * An Orchard module is basically an MVC area. You could create areas that don't interact with Orchard and you'd just use standard + * ASP.NET Core MVC skills. Of course we want more than that, so let's take a closer look. */ using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Localization; +using Microsoft.Extensions.Localization; +using OrchardCore.DisplayManagement.Notify; namespace Lombiq.TrainingDemo.Controllers { public class YourFirstOrchardCoreController : Controller { + private readonly INotifier _notifier; + private readonly IStringLocalizer T; + private readonly IHtmlLocalizer H; + + + public YourFirstOrchardCoreController( + INotifier notifier, + IStringLocalizer stringLocalizer, + IHtmlLocalizer htmlLocalizer) + { + _notifier = notifier; + + T = stringLocalizer; + H = htmlLocalizer; + } + + public ActionResult Index() => // For now we just return an empty view. This action is accessible from under // Lombiq.TraningDemo/YourFirstOrchard/Index route (appended to your site's root path; so using defaults it // would look something like this: // http://localhost:44300/Lombiq.TraningDemo/YourFirstOrchard/Index) If you don't know how this // path gets together take a second look at how ASP.NET Core MVC routing works! - View(); + View(new { Message = T["Hello you!"] }); // This attribute will override the default route (see above) and use a custom one. This is also something that is an // ASP.NET Core MVC feature but this can be used on Orchard Core controllers as well. - [Route("TrainingDemo/ActionWithRoute")] - public ActionResult ActionWithRoute() => - View(); + [Route("TrainingDemo/NotifyMe")] + public ActionResult NotifyMe() + { + _notifier.Information(H["Congratulations! You have been notified!"]); + + return View(); + } } } diff --git a/Drivers/ColorFieldDisplayDriver.cs b/Drivers/ColorFieldDisplayDriver.cs index 526e5a8f..ce2cdfb7 100644 --- a/Drivers/ColorFieldDisplayDriver.cs +++ b/Drivers/ColorFieldDisplayDriver.cs @@ -60,7 +60,7 @@ public override async Task UpdateAsync(ColorField field, IUpdate } if (!string.IsNullOrWhiteSpace(field.Value) && - !Regex.IsMatch(viewModel.Value, "^#(?:[0-9a-fA-F]{3}){1,2}$")) + !Regex.IsMatch(viewModel.Value, "^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")) { updater.ModelState.AddModelError(Prefix, T["The given color is invalid."]); } diff --git a/Drivers/PersonPartDisplayDriver.cs b/Drivers/PersonPartDisplayDriver.cs index 712e489c..88c6960d 100644 --- a/Drivers/PersonPartDisplayDriver.cs +++ b/Drivers/PersonPartDisplayDriver.cs @@ -23,7 +23,7 @@ public override IDisplayResult Edit(PersonPart personPart) model.BirthDateUtc = personPart.BirthDateUtc; model.Name = personPart.Name; - model.Sex = personPart.Sex; + model.Handedness = personPart.Handedness; }); } @@ -35,7 +35,7 @@ public override async Task UpdateAsync(PersonPart model, IUpdate model.BirthDateUtc = viewModel.BirthDateUtc; model.Name = viewModel.Name; - model.Sex = viewModel.Sex; + model.Handedness = viewModel.Handedness; return Edit(model); } diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index a8806fef..435f960e 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -4,6 +4,24 @@ netstandard2.0 + + + + + + + + + Never + + + Never + + + Never + + + diff --git a/Migrations.cs b/Migrations.cs index 4f357789..70cb0aed 100644 --- a/Migrations.cs +++ b/Migrations.cs @@ -46,20 +46,5 @@ public int Create() return 1; } - - // For testing purposes. - public int UpdateFrom2() - { - _contentDefinitionManager.AlterPartDefinition(nameof(PersonPart), part => part - .WithField(nameof(PersonPart.Biography), field => field - .OfType(nameof(TextField)) - .WithDisplayName("Biography") - .WithSettings(new TextFieldSettings - { - Required = false - }))); - - return 3; - } } } \ No newline at end of file diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs index 3a384183..a9d3ccea 100644 --- a/Models/PersonPart.cs +++ b/Models/PersonPart.cs @@ -7,15 +7,14 @@ namespace Lombiq.TrainingDemo.Models public class PersonPart : ContentPart { public string Name { get; set; } - public Sex Sex { get; set; } + public Handedness Handedness { get; set; } public DateTime? BirthDateUtc { get; set; } public TextField Biography { get; set; } } - - public enum Sex + public enum Handedness { - Male, - Female + Right, + Left } } \ No newline at end of file diff --git a/ResourceManifest.cs b/ResourceManifest.cs new file mode 100644 index 00000000..899b325b --- /dev/null +++ b/ResourceManifest.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OrchardCore.ResourceManagement; + +namespace Lombiq.TrainingDemo +{ + public class ResourceManifest : IResourceManifestProvider + { + public void BuildManifests(IResourceManifestBuilder builder) + { + var manifest = builder.Add(); + + manifest + .DefineScript("Pickr") + .SetUrl("/Lombiq.TrainingDemo/pickr/pickr.min.js"); + + manifest + .DefineStyle("Pickr") + .SetUrl("/Lombiq.TrainingDemo/pickr/pickr.min.css"); + } + } +} diff --git a/Startup.cs b/Startup.cs index 15acbc19..881aee62 100644 --- a/Startup.cs +++ b/Startup.cs @@ -18,6 +18,7 @@ using OrchardCore.DisplayManagement.Handlers; using OrchardCore.Indexing; using OrchardCore.Modules; +using OrchardCore.ResourceManagement; using YesSql.Indexes; namespace Lombiq.TrainingDemo @@ -51,6 +52,9 @@ public override void ConfigureServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddScoped(); + + // Resources + services.AddScoped(); } public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider) diff --git a/ViewModels/EditColorFieldViewModel.cs b/ViewModels/EditColorFieldViewModel.cs index 35624925..98cfea11 100644 --- a/ViewModels/EditColorFieldViewModel.cs +++ b/ViewModels/EditColorFieldViewModel.cs @@ -8,9 +8,6 @@ public class EditColorFieldViewModel { public string ColorName { get; set; } public string Value { get; set; } - public byte R { get; set; } - public byte G { get; set; } - public byte B { get; set; } public ColorField Field { get; set; } public ContentPart Part { get; set; } public ContentPartFieldDefinition PartFieldDefinition { get; set; } diff --git a/ViewModels/PersonPartViewModel.cs b/ViewModels/PersonPartViewModel.cs index 0127f566..064cb78c 100644 --- a/ViewModels/PersonPartViewModel.cs +++ b/ViewModels/PersonPartViewModel.cs @@ -15,7 +15,7 @@ public class PersonPartViewModel : IValidatableObject public string Name { get; set; } [Required] - public Sex Sex { get; set; } + public Handedness Handedness { get; set; } [Required] public DateTime? BirthDateUtc { get; set; } diff --git a/Views/ColorField-ColorPicker.Edit.cshtml b/Views/ColorField-ColorPicker.Edit.cshtml new file mode 100644 index 00000000..d80a1fa6 --- /dev/null +++ b/Views/ColorField-ColorPicker.Edit.cshtml @@ -0,0 +1,54 @@ +@model Lombiq.TrainingDemo.ViewModels.EditColorFieldViewModel +@using Lombiq.TrainingDemo.Settings; +@using OrchardCore.ContentManagement.Metadata.Models + +@{ + var settings = Model.PartFieldDefinition.Settings.ToObject(); +} + + + + +
+ @Model.PartFieldDefinition.DisplayName() + + + + + +
+ + @if (!String.IsNullOrEmpty(settings.Hint)) + { + @settings.Hint + } +
+ + \ No newline at end of file diff --git a/Views/ColorField-ColorPicker.Option.cshtml b/Views/ColorField-ColorPicker.Option.cshtml new file mode 100644 index 00000000..ed94c801 --- /dev/null +++ b/Views/ColorField-ColorPicker.Option.cshtml @@ -0,0 +1,4 @@ +@{ + string currentEditor = Model.Editor; +} + diff --git a/Views/ColorField.cshtml b/Views/ColorField.cshtml index 84931bd6..e833cbb2 100644 --- a/Views/ColorField.cshtml +++ b/Views/ColorField.cshtml @@ -4,10 +4,6 @@ @{ var name = (Model.PartFieldDefinition.PartDefinition.Name + "-" + Model.PartFieldDefinition.Name).HtmlClassify(); var hex = Model.Field.Value; - if (!hex.StartsWith("#")) - { - hex = $"#{hex}"; - } }
diff --git a/Views/PersonPart.Edit.cshtml b/Views/PersonPart.Edit.cshtml index b967ac21..ce4d30fe 100644 --- a/Views/PersonPart.Edit.cshtml +++ b/Views/PersonPart.Edit.cshtml @@ -12,7 +12,7 @@ -
- - +
+ +
\ No newline at end of file diff --git a/Views/PersonPart.SummaryAdmin.cshtml b/Views/PersonPart.SummaryAdmin.cshtml new file mode 100644 index 00000000..52bb40b9 --- /dev/null +++ b/Views/PersonPart.SummaryAdmin.cshtml @@ -0,0 +1,3 @@ +@model ShapeViewModel + +@T["Person's name: {0}", Model.Value.Name] \ No newline at end of file diff --git a/Views/PersonPart.cshtml b/Views/PersonPart.cshtml index fe17a129..e128f705 100644 --- a/Views/PersonPart.cshtml +++ b/Views/PersonPart.cshtml @@ -2,4 +2,4 @@
@Model.Value.Name
@T["Birth Date: {0}", Model.Value.BirthDateUtc?.ToShortDateString()]
-
@T["Sex: {0}", Model.Value.Sex]
\ No newline at end of file +
@T["Handedness: {0}", Model.Value.Handedness]
\ No newline at end of file diff --git a/wwwroot/pickr/pickr.min.css b/wwwroot/pickr/pickr.min.css new file mode 100644 index 00000000..5c8c5a6e --- /dev/null +++ b/wwwroot/pickr/pickr.min.css @@ -0,0 +1 @@ +.pickr{position:relative;overflow:visible;z-index:1}.pickr *{box-sizing:border-box}.pickr .pcr-button{position:relative;height:2em;width:2em;padding:.5em;border-radius:.15em;cursor:pointer;background:transparent;transition:background-color .3s;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.pickr .pcr-button:before{background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pickr .pcr-button:after,.pickr .pcr-button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%}.pickr .pcr-button:after{background:url('data:image/svg+xml;utf8, ') no-repeat 50%;background-size:70%;opacity:0}.pickr .pcr-button.clear:after{opacity:1}.pickr .pcr-button.disabled{cursor:not-allowed}.pcr-app{position:absolute;display:flex;flex-direction:column;z-index:10000;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;box-shadow:0 .2em 1.5em 0 rgba(0,0,0,.1),0 0 1em 0 rgba(0,0,0,.02);top:5px;height:15em;width:28em;max-width:95vw;padding:.8em;border-radius:.1em;background:#fff;opacity:0;visibility:hidden;transition:opacity .3s}.pcr-app.visible{visibility:visible;opacity:1}.pcr-app .pcr-interaction{display:flex;align-items:center;margin:1em -.2em 0}.pcr-app .pcr-interaction>*{margin:0 .2em}.pcr-app .pcr-interaction input{padding:.5em .6em;border:none;outline:none;letter-spacing:.07em;font-size:.75em;text-align:center;cursor:pointer;color:#c4c4c4;background:#f8f8f8;border-radius:.15em;transition:all .15s}.pcr-app .pcr-interaction input:hover{color:grey}.pcr-app .pcr-interaction .pcr-result{color:grey;text-align:left;flex-grow:1;min-width:1em;transition:all .2s;border-radius:.15em;background:#f8f8f8;cursor:text;padding-left:.8em}.pcr-app .pcr-interaction .pcr-result:focus{color:#4285f4}.pcr-app .pcr-interaction .pcr-result::selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-type.active{color:#fff;background:#4285f4}.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-save{color:#fff;width:auto}.pcr-app .pcr-interaction .pcr-save{background:#4285f4}.pcr-app .pcr-interaction .pcr-save:hover{background:#4370f4;color:#fff}.pcr-app .pcr-interaction .pcr-clear{background:#f44250}.pcr-app .pcr-interaction .pcr-clear:hover{background:#db3d49;color:#fff}.pcr-app .pcr-selection{display:flex;justify-content:space-between;flex-grow:1}.pcr-app .pcr-selection .pcr-picker{position:absolute;height:18px;width:18px;border:2px solid #fff;border-radius:100%;user-select:none;cursor:-moz-grab;cursor:-webkit-grabbing}.pcr-app .pcr-selection .pcr-color-preview{position:relative;z-index:1;width:2em;display:flex;flex-direction:column;justify-content:space-between;margin-right:.75em}.pcr-app .pcr-selection .pcr-color-preview:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{cursor:pointer;transition:background-color .3s;border-radius:.15em .15em 0 0}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color{border-radius:0 0 .15em .15em}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color,.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{background:transparent;width:100%;height:50%}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity,.pcr-app .pcr-selection .pcr-color-palette{position:relative;user-select:none;display:flex;flex-direction:column}.pcr-app .pcr-selection .pcr-color-palette{width:100%;z-index:1}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette{height:100%;border-radius:.15em}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity{margin-left:.75em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app .pcr-selection .pcr-color-opacity .pcr-picker{left:50%;transform:translateX(-50%)}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{width:8px;height:100%;border-radius:50em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider{background:linear-gradient(180deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{background:linear-gradient(180deg,transparent,#000),url('data:image/svg+xml;utf8, ');background-size:100%,50%} \ No newline at end of file diff --git a/wwwroot/pickr/pickr.min.js b/wwwroot/pickr/pickr.min.js new file mode 100644 index 00000000..0adc2483 --- /dev/null +++ b/wwwroot/pickr/pickr.min.js @@ -0,0 +1,2 @@ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Pickr=e():t.Pickr=e()}(window,function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="dist/",n(n.s=1)}([function(t,e,n){},function(t,e,n){"use strict";n.r(e);var o={};n.r(o),n.d(o,"once",function(){return a}),n.d(o,"on",function(){return c}),n.d(o,"off",function(){return s}),n.d(o,"createElementFromString",function(){return l}),n.d(o,"removeAttribute",function(){return p}),n.d(o,"createFromTemplate",function(){return d}),n.d(o,"eventPath",function(){return h}),n.d(o,"adjustableInputNumbers",function(){return f});var r={};n.r(r),n.d(r,"hsvToRgb",function(){return b}),n.d(r,"hsvToHex",function(){return _}),n.d(r,"hsvToCmyk",function(){return w}),n.d(r,"hsvToHsl",function(){return k}),n.d(r,"parseToHSV",function(){return j});n(0);function i(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var a=function(t,e,n,o){return c(t,e,function t(){n.apply(this,arguments),this.removeEventListener(e,t)},o)},c=u.bind(null,"addEventListener"),s=u.bind(null,"removeEventListener");function u(t,e,n,o){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};return e instanceof HTMLCollection||e instanceof NodeList?e=Array.from(e):Array.isArray(e)||(e=[e]),Array.isArray(n)||(n=[n]),e.forEach(function(e){return n.forEach(function(n){return e[t](n,o,function(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{},o=p(e,"data-con"),r=p(e,"data-key");r&&(n[r]=e);for(var i=Array.from(e.children),a=o?n[o]={}:n,c=0;c1&&void 0!==arguments[1])||arguments[1],n=function(t){return t>="0"&&t<="9"||"-"===t||"."===t};function o(o){for(var r=t.value,i=t.selectionStart,a=i,c="",s=i-1;s>0&&n(r[s]);s--)c=r[s]+c,a--;for(var u=i,l=r.length;u0&&!isNaN(c)&&isFinite(c)){var p=o.deltaY<0?1:-1,d=o.ctrlKey?5*p:p,h=Number(c)+d;!e&&h<0&&(h=0);var f=r.substr(0,a)+h+r.substring(a+c.length,r.length),v=a+String(h).length;t.value=f,t.focus(),t.setSelectionRange(v,v)}o.preventDefault(),t.dispatchEvent(new Event("input"))}c(t,"focus",function(){return c(window,"wheel",o)}),c(t,"blur",function(){return s(window,"wheel",o)})}function v(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=[],o=!0,r=!1,i=void 0;try{for(var a,c=t[Symbol.iterator]();!(o=(a=c.next()).done)&&(n.push(a.value),!e||n.length!==e);o=!0);}catch(t){r=!0,i=t}finally{try{o||null==c.return||c.return()}finally{if(r)throw i}}return n}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function y(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e1&&(o-=1)}return[360*o,100*r,100*i]}function C(t,e,n,o){return e/=100,n/=100,y(A(255*(1-g(1,(t/=100)*(1-(o/=100))+o)),255*(1-g(1,e*(1-o)+o)),255*(1-g(1,n*(1-o)+o))))}function S(t,e,n){return e/=100,[t,2*(e*=(n/=100)<.5?n:1-n)/(n+e)*100,100*(n+e)]}function O(t){return A.apply(void 0,y(t.match(/.{2}/g).map(function(t){return parseInt(t,16)})))}function j(t){var e,n={cmyk:/^cmyk[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)/i,rgba:/^(rgb|rgba)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsla:/^(hsl|hsla)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsva:/^(hsv|hsva)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hex:/^#?(([\dA-Fa-f]{3,4})|([\dA-Fa-f]{6})|([\dA-Fa-f]{8}))$/i},o=function(t){return t.map(function(t){return/^(|\d+)\.\d+|\d+$/.test(t)?Number(t):void 0})};for(var r in n)if(e=n[r].exec(t))switch(r){case"cmyk":var i=v(o(e),5),a=i[1],c=i[2],s=i[3],u=i[4];if(a>100||c>100||s>100||u>100)break;return{values:y(C(a,c,s,u)).concat([1]),type:r};case"rgba":var l=v(o(e),6),p=l[2],d=l[3],h=l[4],f=l[5],g=void 0===f?1:f;if(p>255||d>255||h>255||g<0||g>1)break;return{values:y(A(p,d,h)).concat([g]),type:r};case"hex":var m=function(t,e){return[t.substring(0,e),t.substring(e,t.length)]},b=v(e,2)[1];3===b.length?b+="F":6===b.length&&(b+="FF");var _=void 0;if(4===b.length){var w=v(m(b,3).map(function(t){return t+t}),2);b=w[0],_=w[1]}else if(8===b.length){var k=v(m(b,6),2);b=k[0],_=k[1]}return _=parseInt(_,16)/255,{values:y(O(b)).concat([_]),type:r};case"hsla":var j=v(o(e),6),x=j[2],E=j[3],H=j[4],R=j[5],B=void 0===R?1:R;if(x>360||E>100||H>100||B<0||B>1)break;return{values:y(S(x,E,H)).concat([B]),type:r};case"hsva":var P=v(o(e),6),L=P[2],D=P[3],T=P[4],F=P[5],M=void 0===F?1:F;if(L>360||D>100||T>100||M<0||M>1)break;return{values:[L,D,T,M],type:r}}return{values:null,type:null}}function x(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,i=Math.ceil,a={h:t,s:e,v:n,a:o,toHSVA:function(){var t=[a.h,a.s,a.v],e=t.map(i);return t.toString=function(){return"hsva(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toHSLA:function(){var t=k(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"hsla(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toRGBA:function(){var t=b(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"rgba(".concat(e[0],", ").concat(e[1],", ").concat(e[2],", ").concat(a.a.toFixed(1),")")},t},toCMYK:function(){var t=w(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"cmyk(".concat(e[0],"%, ").concat(e[1],"%, ").concat(e[2],"%, ").concat(e[3],"%)")},t},toHEX:function(){var t=_.apply(r,[a.h,a.s,a.v]);return t.toString=function(){var e=a.a>=1?"":Number((255*a.a).toFixed(0)).toString(16).toUpperCase().padStart(2,"0");return"#".concat(t.join("").toUpperCase()+e)},t},clone:function(){return x(a.h,a.s,a.v,a.a)}};return a}function E(t){var e={options:Object.assign({lockX:!1,lockY:!1,onchange:function(){return 0}},t),_tapstart:function(t){c(document,["mouseup","touchend","touchcancel"],e._tapstop),c(document,["mousemove","touchmove"],e._tapmove),t.preventDefault(),e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove(t)},_tapmove:function(t){var n=e.options,o=e.cache,r=n.element,i=e.wrapperRect,a=0,c=0;if(t){var s=t&&t.touches&&t.touches[0];a=t?(s||t).clientX:0,c=t?(s||t).clientY:0,ai.left+i.width&&(a=i.left+i.width),ci.top+i.height&&(c=i.top+i.height),a-=i.left,c-=i.top}else o&&(a=o.x,c=o.y);n.lockX||(r.style.left=a-r.offsetWidth/2+"px"),n.lockY||(r.style.top=c-r.offsetHeight/2+"px"),e.cache={x:a,y:c},n.onchange(a,c)},_tapstop:function(){s(document,["mouseup","touchend","touchcancel"],e._tapstop),s(document,["mousemove","touchmove"],e._tapmove)},trigger:function(){e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove()},update:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove({clientX:e.wrapperRect.left+t,clientY:e.wrapperRect.top+n})},destroy:function(){var t=e.options,n=e._tapstart;s([t.wrapper,t.element],"mousedown",n),s([t.wrapper,t.element],"touchstart",n,{passive:!1})}};e.wrapperRect=e.options.wrapper.getBoundingClientRect();var n=e.options,o=e._tapstart;return c([n.wrapper,n.element],"mousedown",o),c([n.wrapper,n.element],"touchstart",o,{passive:!1}),e}function H(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e\n \n '.concat(o?"":'
','\n\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n\n
\n \n\n \n \n \n \n \n\n \n \n
\n
\n
\n ")),a=i.interaction;return a.options.find(function(t){return!t.hidden&&!t.classList.add("active")}),a.type=function(){return a.options.find(function(t){return t.classList.contains("active")})},i}(t),t.useAsButton&&(t.parent||(t.parent="body"),this._root.button=t.el),document.body.appendChild(this._root.root)}},{key:"_finalBuild",value:function(){var t=this.options,e=this._root;document.body.removeChild(e.root),t.parent&&("string"==typeof t.parent&&(t.parent=document.querySelector(t.parent)),t.parent.appendChild(e.app)),t.useAsButton||t.el.parentElement.replaceChild(e.root,t.el),t.disabled&&this.disable(),t.comparison||(e.button.style.transition="none",t.useAsButton||(e.preview.lastColor.style.transition="none")),t.showAlways?e.app.classList.add("visible"):this.hide()}},{key:"_buildComponents",value:function(){var t=this,e=this.options.components,n={palette:E({element:t._root.palette.picker,wrapper:t._root.palette.palette,onchange:function(e,n){var o=t._color,r=t._root,i=t.options;o.s=e/this.wrapper.offsetWidth*100,o.v=100-n/this.wrapper.offsetHeight*100,o.v<0&&(o.v=0);var a=o.toRGBA().toString();this.element.style.background=a,this.wrapper.style.background="\n linear-gradient(to top, rgba(0, 0, 0, ".concat(o.a,"), transparent), \n linear-gradient(to left, hsla(").concat(o.h,", 100%, 50%, ").concat(o.a,"), rgba(255, 255, 255, ").concat(o.a,"))\n "),i.comparison||(r.button.style.background=a,i.useAsButton||(r.preview.lastColor.style.background=a)),r.preview.currentColor.style.background=a,t._recalc&&t._updateOutput(),r.button.classList.remove("clear")}}),hue:E({lockX:!0,element:t._root.hue.picker,wrapper:t._root.hue.slider,onchange:function(o,r){e.hue&&(t._color.h=r/this.wrapper.offsetHeight*360,this.element.style.backgroundColor="hsl(".concat(t._color.h,", 100%, 50%)"),n.palette.trigger())}}),opacity:E({lockX:!0,element:t._root.opacity.picker,wrapper:t._root.opacity.slider,onchange:function(n,o){e.opacity&&(t._color.a=Math.round(o/this.wrapper.offsetHeight*100)/100,this.element.style.background="rgba(0, 0, 0, ".concat(t._color.a,")"),t.components.palette.trigger())}}),selectable:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e={options:Object.assign({onchange:function(){return 0},className:"",elements:[]},t),_ontap:function(t){var n=e.options;n.elements.forEach(function(e){return e.classList[t.target===e?"add":"remove"](n.className)}),n.onchange(t)},destroy:function(){s(e.options.elements,"click",this._ontap)}};return c(e.options.elements,"click",e._ontap),e}({elements:t._root.interaction.options,className:"active",onchange:function(e){t._representation=e.target.getAttribute("data-type").toUpperCase(),t._updateOutput()}})};this.components=n}},{key:"_bindEvents",value:function(){var t=this,e=this._root,n=this.options,o=[c(e.interaction.clear,"click",function(){return t._clearColor()}),c(e.preview.lastColor,"click",function(){return t.setHSVA.apply(t,H(t._lastColor.toHSVA()))}),c(e.interaction.save,"click",function(){!t._saveColor()&&!n.showAlways&&t.hide()}),c(e.interaction.result,["keyup","input"],function(e){t._recalc=!1,t.setColor(e.target.value,!0)&&!t._initializingActive&&t.options.onChange(t._color,t),e.stopImmediatePropagation()}),c([e.palette.palette,e.palette.picker,e.hue.slider,e.hue.picker,e.opacity.slider,e.opacity.picker],["mousedown","touchstart"],function(){return t._recalc=!0}),c(window,"resize",function(){return t._rePositioningPicker})];if(!n.showAlways){o.push(c(e.button,"click",function(){return t.isOpen()?t.hide():t.show()}));var r=n.closeWithKey;o.push(c(document,"keyup",function(e){return t.isOpen()&&(e.key===r||e.code===r)&&t.hide()})),o.push(c(document,["touchstart","mousedown"],function(n){t.isOpen()&&!h(n).some(function(t){return t===e.app||t===e.button})&&t.hide()},{capture:!0}))}n.adjustableNumbers&&f(e.interaction.result,!1),this._eventBindings=o}},{key:"_rePositioningPicker",value:function(){var t=this._root,e=this._root.app;if(this.options.parent){var n=t.button.getBoundingClientRect();e.style.position="fixed",e.style.marginLeft="".concat(n.left,"px"),e.style.marginTop="".concat(n.top,"px")}var o=t.button.getBoundingClientRect(),r=e.getBoundingClientRect(),i=e.style;r.bottom>window.innerHeight?i.top="".concat(-r.height-5,"px"):o.bottom+r.heightwindow.innerWidth&&l-window.innerWidthwindow.innerWidth&&(s=a.left),i.left="".concat(s,"px")}},{key:"_updateOutput",value:function(){var t=this;this._root.interaction.type()&&(this._root.interaction.result.value=function(){var e="to"+t._root.interaction.type().getAttribute("data-type");return"function"==typeof t._color[e]?t._color[e]().toString():""}()),this._initializingActive||this.options.onChange(this._color,this)}},{key:"_saveColor",value:function(){var t=this._root,e=t.preview,n=t.button,o=this._color.toRGBA().toString();e.lastColor.style.background=o,this.options.useAsButton||(n.style.background=o),n.classList.remove("clear"),this._lastColor=this._color.clone(),this._initializingActive||this.options.onSave(this._color,this)}},{key:"_clearColor",value:function(){var t=this._root,e=this.options;e.useAsButton||(t.button.style.background="rgba(255, 255, 255, 0.4)"),t.button.classList.add("clear"),e.showAlways||this.hide(),e.onSave(null,this)}},{key:"destroy",value:function(){var t=this;this._eventBindings.forEach(function(t){return s.apply(o,H(t))}),Object.keys(this.components).forEach(function(e){return t.components[e].destroy()})}},{key:"destroyAndRemove",value:function(){this.destroy();var t=this._root.root;t.parentElement.removeChild(t)}},{key:"hide",value:function(){return this._root.app.classList.remove("visible"),this}},{key:"show",value:function(){if(!this.options.disabled)return this._root.app.classList.add("visible"),this._rePositioningPicker(),this}},{key:"isOpen",value:function(){return this._root.app.classList.contains("visible")}},{key:"setHSVA",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:360,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]&&arguments[4],i=this._recalc;if(this._recalc=!1,t<0||t>360||e<0||e>100||n<0||n>100||o<0||o>1)return!1;var a=this.components,c=a.hue,s=a.opacity,u=a.palette,l=c.options.wrapper.offsetHeight*(t/360);c.update(0,l);var p=s.options.wrapper.offsetHeight*o;s.update(0,p);var d=u.options.wrapper,h=d.offsetWidth*(e/100),f=d.offsetHeight*(1-n/100);return u.update(h,f),this._color=new x(t,e,n,o),this._recalc=i,this._recalc&&this._updateOutput(),r||this._saveColor(),!0}},{key:"setColor",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(null===t)return this._clearColor(),!0;var n=j(t),o=n.values,r=n.type;if(o){var i=r.toUpperCase(),a=this._root.interaction.options,c=a.find(function(t){return t.getAttribute("data-type")===i});if(!c.hidden){var s=!0,u=!1,l=void 0;try{for(var p,d=a[Symbol.iterator]();!(s=(p=d.next()).done);s=!0){var h=p.value;h.classList[h===c?"add":"remove"]("active")}}catch(t){u=!0,l=t}finally{try{s||null==d.return||d.return()}finally{if(u)throw l}}}return this.setHSVA.apply(this,H(o).concat([e]))}}},{key:"setColorRepresentation",value:function(t){return t=t.toUpperCase(),!!this._root.interaction.options.find(function(e){return e.getAttribute("data-type")===t&&!e.click()})}},{key:"getColorRepresentation",value:function(){return this._representation}},{key:"getColor",value:function(){return this._color}},{key:"getRoot",value:function(){return this._root}},{key:"disable",value:function(){return this.hide(),this.options.disabled=!0,this._root.button.classList.add("disabled"),this}},{key:"enable",value:function(){return this.options.disabled=!1,this._root.button.classList.remove("disabled"),this}}]),t}();B.utils={once:a,on:c,off:s,eventPath:h,createElementFromString:l,adjustableInputNumbers:f,removeAttribute:p,createFromTemplate:d},B.create=function(t){return new B(t)},B.version="0.3.2";e.default=B}]).default}); +//# sourceMappingURL=pickr.min.js.map \ No newline at end of file diff --git a/wwwroot/pickr/pickr.min.js.map b/wwwroot/pickr/pickr.min.js.map new file mode 100644 index 00000000..5ea5deef --- /dev/null +++ b/wwwroot/pickr/pickr.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap","webpack:///./src/js/lib/utils.js","webpack:///./src/js/lib/color.js","webpack:///./src/js/lib/hsvacolor.js","webpack:///./src/js/helper/moveable.js","webpack:///./src/js/pickr.js","webpack:///./src/js/helper/selectable.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","once","element","event","fn","options","on","helper","apply","this","arguments","removeEventListener","eventListener","off","method","elements","events","length","undefined","HTMLCollection","NodeList","Array","from","isArray","forEach","el","ev","_objectSpread","capture","slice","createElementFromString","html","div","document","createElement","innerHTML","trim","firstElementChild","removeAttribute","getAttribute","createFromTemplate","str","resolve","base","con","children","subtree","_i","child","arr","push","eventPath","evt","path","composedPath","target","parentElement","adjustableInputNumbers","negative","isNumChar","handleScroll","e","val","selectionStart","numStart","num","isNaN","isFinite","mul","deltaY","inc","ctrlKey","newNum","Number","newStr","substr","substring","curPos","String","focus","setSelectionRange","preventDefault","dispatchEvent","Event","min","Math","max","hsvToRgb","h","v","floor","f","q","mod","hsvToHex","map","round","toString","padStart","hsvToCmyk","k","rgb","g","b","hsvToHsl","rgbToHsv","minVal","maxVal","delta","dr","dg","db","cmykToHsv","y","_toConsumableArray","hslToHsv","hexToHsv","hex","match","parseInt","parseToHSV","regex","cmyk","rgba","hsla","hsva","numarize","array","test","type","exec","_numarize2","_slicedToArray","values","concat","_numarize4","_numarize4$","a","splitAt","alpha","_splitAt$map2","_splitAt2","_numarize6","_numarize6$","_numarize8","_numarize8$","HSVaColor","ceil","that","toHSVA","hsv","rhsv","toFixed","toHSLA","hsl","Color","rhsl","toRGBA","rrgb","toCMYK","rcmyk","toHEX","toUpperCase","join","clone","Moveable","opt","assign","lockX","lockY","onchange","_tapstart","_","_tapstop","_tapmove","wrapperRect","wrapper","getBoundingClientRect","cache","x","touch","touches","clientX","clientY","left","width","top","height","style","offsetWidth","offsetHeight","trigger","update","destroy","passive","Pickr","_classCallCheck","useAsButton","disabled","comparison","components","interaction","strings","default","defaultRepresentation","position","adjustableNumbers","showAlways","parent","closeWithKey","onChange","onSave","onClear","_initializingActive","_recalc","_color","_lastColor","_preBuild","_buildComponents","_bindEvents","setColor","_representation","setColorRepresentation","_finalBuild","_rePositioningPicker","querySelector","_root","hidden","preview","hue","opacity","keys","input","save","clear","int","find","classList","add","contains","button","body","appendChild","removeChild","app","replaceChild","disable","transition","lastColor","hide","inst","comp","palette","picker","cssRGBaString","background","currentColor","_updateOutput","remove","slider","backgroundColor","selectable","className","_ontap","Selectable","_this","eventBindings","_clearColor","setHSVA","pickr_toConsumableArray","_saveColor","result","stopImmediatePropagation","isOpen","show","ck","code","some","_eventBindings","relative","marginLeft","marginTop","bb","ab","as","bottom","innerHeight","pos","middle","right","cl","getComputedStyle","newLeft","leftClip","rightClip","innerWidth","_this2","_this$_root","_this3","args","silent","recalc","_this$components","hueY","opacityY","pickerWrapper","pickerX","pickerY","string","_Color$parseToHSV","utype","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_step","_iterator","iterator","next","done","err","return","click","utils","version"],"mappings":"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","file":"pickr.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Pickr\"] = factory();\n\telse\n\t\troot[\"Pickr\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/**\r\n * Add an eventlistener which will be fired only once.\r\n *\r\n * @param element Target element\r\n * @param event Event name\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const once = (element, event, fn, options) => on(element, event, function helper() {\r\n fn.apply(this, arguments);\r\n this.removeEventListener(event, helper);\r\n}, options);\r\n\r\n/**\r\n * Add event(s) to element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const on = eventListener.bind(null, 'addEventListener');\r\n\r\n/**\r\n * Remove event(s) from element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const off = eventListener.bind(null, 'removeEventListener');\r\n\r\nfunction eventListener(method, elements, events, fn, options = {}) {\r\n\r\n // Normalize array\r\n if (elements instanceof HTMLCollection || elements instanceof NodeList) {\r\n elements = Array.from(elements);\r\n } else if (!Array.isArray(elements)) {\r\n elements = [elements];\r\n }\r\n\r\n if (!Array.isArray(events)) {\r\n events = [events];\r\n }\r\n\r\n elements.forEach(el =>\r\n events.forEach(ev =>\r\n el[method](ev, fn, {capture: false, ...options})\r\n )\r\n );\r\n\r\n return Array.prototype.slice.call(arguments, 1);\r\n}\r\n\r\n/**\r\n * Creates an DOM-Element out of a string (Single element).\r\n * @param html HTML representing a single element\r\n * @returns {Element | null} The element.\r\n */\r\nexport function createElementFromString(html) {\r\n const div = document.createElement('div');\r\n div.innerHTML = html.trim();\r\n return div.firstElementChild;\r\n}\r\n\r\n/**\r\n * Removes an attribute from a HTMLElement and returns the value.\r\n * @param el\r\n * @param name\r\n * @return {string}\r\n */\r\nexport function removeAttribute(el, name) {\r\n const value = el.getAttribute(name);\r\n el.removeAttribute(name);\r\n return value;\r\n}\r\n\r\n/**\r\n * Creates a new html element, every element which has\r\n * a 'data-key' attribute will be saved in a object (which will be returned)\r\n * where the value of 'data-key' ist the object-key and the value the HTMLElement.\r\n *\r\n * It's possible to create a hierarchy if you add a 'data-con' attribute. Every\r\n * sibling will be added to the object which will get the name from the 'data-con' attribute.\r\n *\r\n * If you want to create an Array out of multiple elements, you can use the 'data-arr' attribute,\r\n * the value defines the key and all elements, which has the same parent and the same 'data-arr' attribute,\r\n * would be added to it.\r\n *\r\n * @param str - The HTML String.\r\n */\r\nexport function createFromTemplate(str) {\r\n\r\n // Recursive function to resolve template\r\n function resolve(element, base = {}) {\r\n\r\n // Check key and container attribute\r\n const con = removeAttribute(element, 'data-con');\r\n const key = removeAttribute(element, 'data-key');\r\n\r\n // Check and save element\r\n if (key) {\r\n base[key] = element;\r\n }\r\n\r\n // Check all children\r\n const children = Array.from(element.children);\r\n const subtree = con ? (base[con] = {}) : base;\r\n for (let child of children) {\r\n\r\n // Check if element should be saved as array\r\n const arr = removeAttribute(child, 'data-arr');\r\n if (arr) {\r\n\r\n // Check if there is already an array and add element\r\n (subtree[arr] || (subtree[arr] = [])).push(child);\r\n } else {\r\n resolve(child, subtree);\r\n }\r\n }\r\n\r\n return base;\r\n }\r\n\r\n return resolve(createElementFromString(str));\r\n}\r\n\r\n/**\r\n * Polyfill for safari & firefox for the eventPath event property.\r\n * @param evt The event object.\r\n * @return [String] event path.\r\n */\r\nexport function eventPath(evt) {\r\n let path = evt.path || (evt.composedPath && evt.composedPath());\r\n if (path) return path;\r\n\r\n let el = evt.target.parentElement;\r\n path = [evt.target, el];\r\n while (el = el.parentElement) path.push(el);\r\n\r\n path.push(document, window);\r\n return path;\r\n}\r\n\r\n/**\r\n * Creates the ability to change numbers in an input field with the scroll-wheel.\r\n * @param el\r\n * @param negative\r\n */\r\nexport function adjustableInputNumbers(el, negative = true) {\r\n\r\n // Check if a char represents a number\r\n const isNumChar = c => (c >= '0' && c <= '9') || c === '-' || c === '.';\r\n\r\n function handleScroll(e) {\r\n const val = el.value;\r\n const off = el.selectionStart;\r\n let numStart = off;\r\n let num = ''; // Will be the number as string\r\n\r\n // Look back\r\n for (let i = off - 1; i > 0 && isNumChar(val[i]); i--) {\r\n num = val[i] + num;\r\n numStart--; // Find start of number\r\n }\r\n\r\n // Look forward\r\n for (let i = off, n = val.length; i < n && isNumChar(val[i]); i++) {\r\n num += val[i];\r\n }\r\n\r\n // Check if number is valid\r\n if (num.length > 0 && !isNaN(num) && isFinite(num)) {\r\n\r\n const mul = e.deltaY < 0 ? 1 : -1;\r\n const inc = e.ctrlKey ? mul * 5 : mul;\r\n let newNum = Number(num) + inc;\r\n\r\n if (!negative && newNum < 0) {\r\n newNum = 0;\r\n }\r\n\r\n const newStr = val.substr(0, numStart) + newNum + val.substring(numStart + num.length, val.length);\r\n const curPos = numStart + String(newNum).length;\r\n\r\n // Update value and set cursor\r\n el.value = newStr;\r\n el.focus();\r\n el.setSelectionRange(curPos, curPos);\r\n }\r\n\r\n // Prevent default\r\n e.preventDefault();\r\n\r\n // Trigger input event\r\n el.dispatchEvent(new Event('input'));\r\n }\r\n\r\n // Bind events\r\n on(el, 'focus', () => on(window, 'wheel', handleScroll));\r\n on(el, 'blur', () => off(window, 'wheel', handleScroll));\r\n}","// Shorthands\r\nconst min = Math.min,\r\n max = Math.max;\r\n\r\n/**\r\n * Convert HSV spectrum to RGB.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} Array with rgb values.\r\n */\r\nexport function hsvToRgb(h, s, v) {\r\n h = (h / 360) * 6;\r\n s /= 100;\r\n v /= 100;\r\n\r\n let i = Math.floor(h);\r\n\r\n let f = h - i;\r\n let p = v * (1 - s);\r\n let q = v * (1 - f * s);\r\n let t = v * (1 - (1 - f) * s);\r\n\r\n let mod = i % 6;\r\n let r = [v, q, p, p, t, v][mod];\r\n let g = [t, v, v, q, p, p][mod];\r\n let b = [p, p, t, v, v, q][mod];\r\n\r\n return [\r\n r * 255,\r\n g * 255,\r\n b * 255\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to Hex.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {string[]} Hex values\r\n */\r\nexport function hsvToHex(h, s, v) {\r\n return hsvToRgb(h, s, v).map(v => Math.round(v).toString(16).padStart(2, '0'));\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to CMYK.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} CMYK values\r\n */\r\nexport function hsvToCmyk(h, s, v) {\r\n const rgb = hsvToRgb(h, s, v);\r\n const r = rgb[0] / 255;\r\n const g = rgb[1] / 255;\r\n const b = rgb[2] / 255;\r\n\r\n let k, c, m, y;\r\n\r\n k = min(1 - r, 1 - g, 1 - b);\r\n\r\n c = k === 1 ? 0 : (1 - r - k) / (1 - k);\r\n m = k === 1 ? 0 : (1 - g - k) / (1 - k);\r\n y = k === 1 ? 0 : (1 - b - k) / (1 - k);\r\n\r\n return [\r\n c * 100,\r\n m * 100,\r\n y * 100,\r\n k * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to HSL.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} HSL values\r\n */\r\nexport function hsvToHsl(h, s, v) {\r\n s /= 100, v /= 100;\r\n\r\n let l = (2 - s) * v / 2;\r\n\r\n if (l !== 0) {\r\n if (l === 1) {\r\n s = 0;\r\n } else if (l < 0.5) {\r\n s = s * v / (l * 2);\r\n } else {\r\n s = s * v / (2 - l * 2);\r\n }\r\n }\r\n\r\n return [\r\n h,\r\n s * 100,\r\n l * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert RGB to HSV.\r\n * @param r Red\r\n * @param g Green\r\n * @param b Blue\r\n * @return {number[]} HSV values.\r\n */\r\nfunction rgbToHsv(r, g, b) {\r\n r /= 255, g /= 255, b /= 255;\r\n\r\n let h, s, v;\r\n const minVal = min(r, g, b);\r\n const maxVal = max(r, g, b);\r\n const delta = maxVal - minVal;\r\n\r\n v = maxVal;\r\n if (delta === 0) {\r\n h = s = 0;\r\n } else {\r\n s = delta / maxVal;\r\n let dr = (((maxVal - r) / 6) + (delta / 2)) / delta;\r\n let dg = (((maxVal - g) / 6) + (delta / 2)) / delta;\r\n let db = (((maxVal - b) / 6) + (delta / 2)) / delta;\r\n\r\n if (r === maxVal) {\r\n h = db - dg;\r\n } else if (g === maxVal) {\r\n h = (1 / 3) + dr - db;\r\n } else if (b === maxVal) {\r\n h = (2 / 3) + dg - dr;\r\n }\r\n\r\n if (h < 0) {\r\n h += 1;\r\n } else if (h > 1) {\r\n h -= 1;\r\n }\r\n }\r\n\r\n return [\r\n h * 360,\r\n s * 100,\r\n v * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert CMYK to HSV.\r\n * @param c Cyan\r\n * @param m Magenta\r\n * @param y Yellow\r\n * @param k Key (Black)\r\n * @return {number[]} HSV values.\r\n */\r\nfunction cmykToHsv(c, m, y, k) {\r\n c /= 100, m /= 100, y /= 100, k /= 100;\r\n\r\n const r = (1 - min(1, c * (1 - k) + k)) * 255;\r\n const g = (1 - min(1, m * (1 - k) + k)) * 255;\r\n const b = (1 - min(1, y * (1 - k) + k)) * 255;\r\n\r\n return [...rgbToHsv(r, g, b)];\r\n}\r\n\r\n/**\r\n * Convert HSL to HSV.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param l Lightness\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hslToHsv(h, s, l) {\r\n s /= 100, l /= 100;\r\n s *= l < 0.5 ? l : 1 - l;\r\n\r\n let ns = (2 * s / (l + s)) * 100;\r\n let v = (l + s) * 100;\r\n return [h, ns, v];\r\n}\r\n\r\n/**\r\n * Convert HEX to HSV.\r\n * @param hex Hexadecimal string of rgb colors, can have length 3 or 6.\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hexToHsv(hex) {\r\n return rgbToHsv(...hex.match(/.{2}/g).map(v => parseInt(v, 16)));\r\n}\r\n\r\n/**\r\n * Try's to parse a string which represents a color to a HSV array.\r\n * Current supported types are cmyk, rgba, hsla and hexadecimal.\r\n * @param str\r\n * @return {*}\r\n */\r\nexport function parseToHSV(str) {\r\n\r\n // Regular expressions to match different types of color represention\r\n const regex = {\r\n cmyk: /^cmyk[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)/i,\r\n rgba: /^(rgb|rgba)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsla: /^(hsl|hsla)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsva: /^(hsv|hsva)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hex: /^#?(([\\dA-Fa-f]{3,4})|([\\dA-Fa-f]{6})|([\\dA-Fa-f]{8}))$/i\r\n };\r\n\r\n /**\r\n * Takes an Array of any type, convert strings which represents\r\n * a number to a number an anything else to undefined.\r\n * @param array\r\n * @return {*}\r\n */\r\n const numarize = array => array.map(v => /^(|\\d+)\\.\\d+|\\d+$/.test(v) ? Number(v) : undefined);\r\n\r\n let match;\r\n for (let type in regex) {\r\n\r\n // Check if current scheme passed\r\n if (!(match = regex[type].exec(str)))\r\n continue;\r\n\r\n // Try to convert\r\n switch (type) {\r\n case 'cmyk': {\r\n let [, c, m, y, k] = numarize(match);\r\n\r\n if (c > 100 || m > 100 || y > 100 || k > 100)\r\n break;\r\n\r\n return {values: [...cmykToHsv(c, m, y, k), 1], type};\r\n }\r\n case 'rgba': {\r\n let [, , r, g, b, a = 1] = numarize(match);\r\n\r\n if (r > 255 || g > 255 || b > 255 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...rgbToHsv(r, g, b), a], type};\r\n }\r\n case 'hex': {\r\n const splitAt = (s, i) => [s.substring(0, i), s.substring(i, s.length)];\r\n let [, hex] = match;\r\n\r\n // Fill up opacity if not declared\r\n if (hex.length === 3) {\r\n hex += 'F';\r\n } else if (hex.length === 6) {\r\n hex += 'FF';\r\n }\r\n\r\n let alpha;\r\n if (hex.length === 4) {\r\n [hex, alpha] = splitAt(hex, 3).map(v => v + v);\r\n } else if (hex.length === 8) {\r\n [hex, alpha] = splitAt(hex, 6);\r\n }\r\n\r\n // Convert 0 - 255 to 0 - 1 for opacity\r\n alpha = parseInt(alpha, 16) / 255;\r\n return {values: [...hexToHsv(hex), alpha], type};\r\n }\r\n case 'hsla': {\r\n let [, , h, s, l, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || l > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...hslToHsv(h, s, l), a], type};\r\n }\r\n case 'hsva': {\r\n let [, , h, s, v, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || v > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [h, s, v, a], type};\r\n }\r\n }\r\n }\r\n\r\n return {values: null, type: null};\r\n}","import * as Color from './color';\r\n\r\n/**\r\n * Simple class which holds the properties\r\n * of the color represention model hsla (hue saturation lightness alpha)\r\n */\r\nexport function HSVaColor(h = 0, s = 0, v = 0, a = 1) {\r\n\r\n const ceil = Math.ceil;\r\n const that = {\r\n h, s, v, a,\r\n\r\n toHSVA() {\r\n const hsv = [that.h, that.s, that.v];\r\n const rhsv = hsv.map(ceil);\r\n\r\n hsv.toString = () => `hsva(${rhsv[0]}, ${rhsv[1]}%, ${rhsv[2]}%, ${that.a.toFixed(1)})`;\r\n return hsv;\r\n },\r\n\r\n toHSLA() {\r\n const hsl = Color.hsvToHsl(that.h, that.s, that.v);\r\n const rhsl = hsl.map(ceil);\r\n\r\n hsl.toString = () => `hsla(${rhsl[0]}, ${rhsl[1]}%, ${rhsl[2]}%, ${that.a.toFixed(1)})`;\r\n return hsl;\r\n },\r\n\r\n toRGBA() {\r\n const rgb = Color.hsvToRgb(that.h, that.s, that.v);\r\n const rrgb = rgb.map(ceil);\r\n\r\n rgb.toString = () => `rgba(${rrgb[0]}, ${rrgb[1]}, ${rrgb[2]}, ${that.a.toFixed(1)})`;\r\n return rgb;\r\n },\r\n\r\n toCMYK() {\r\n const cmyk = Color.hsvToCmyk(that.h, that.s, that.v);\r\n const rcmyk = cmyk.map(ceil);\r\n\r\n cmyk.toString = () => `cmyk(${rcmyk[0]}%, ${rcmyk[1]}%, ${rcmyk[2]}%, ${rcmyk[3]}%)`;\r\n return cmyk;\r\n },\r\n\r\n toHEX() {\r\n const hex = Color.hsvToHex(...[that.h, that.s, that.v]);\r\n\r\n hex.toString = () => {\r\n\r\n // Check if alpha channel make sense, convert it to 255 number space, convert\r\n // to hex and pad it with zeros if needet.\r\n const alpha = that.a >= 1 ? '' : Number((that.a * 255).toFixed(0))\r\n .toString(16)\r\n .toUpperCase()\r\n .padStart(2, '0');\r\n\r\n return `#${hex.join('').toUpperCase() + alpha}`;\r\n };\r\n\r\n return hex;\r\n },\r\n\r\n clone() {\r\n return HSVaColor(that.h, that.s, that.v, that.a);\r\n }\r\n };\r\n\r\n return that;\r\n}","import * as _ from './../lib/utils';\r\n\r\nexport default function Moveable(opt) {\r\n\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n lockX: false,\r\n lockY: false,\r\n onchange: () => 0\r\n }, opt),\r\n\r\n _tapstart(evt) {\r\n _.on(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.on(document, ['mousemove', 'touchmove'], that._tapmove);\r\n\r\n // Prevent default touch event\r\n evt.preventDefault();\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Trigger\r\n that._tapmove(evt);\r\n },\r\n\r\n _tapmove(evt) {\r\n const {options, cache} = that;\r\n const {element} = options;\r\n const b = that.wrapperRect;\r\n\r\n let x = 0, y = 0;\r\n if (evt) {\r\n const touch = evt && evt.touches && evt.touches[0];\r\n x = evt ? (touch || evt).clientX : 0;\r\n y = evt ? (touch || evt).clientY : 0;\r\n\r\n // Reset to bounds\r\n if (x < b.left) x = b.left;\r\n else if (x > b.left + b.width) x = b.left + b.width;\r\n if (y < b.top) y = b.top;\r\n else if (y > b.top + b.height) y = b.top + b.height;\r\n\r\n // Normalize\r\n x -= b.left;\r\n y -= b.top;\r\n } else if (cache) {\r\n x = cache.x;\r\n y = cache.y;\r\n }\r\n\r\n if (!options.lockX)\r\n element.style.left = (x - element.offsetWidth / 2) + 'px';\r\n\r\n if (!options.lockY)\r\n element.style.top = (y - element.offsetHeight / 2) + 'px';\r\n\r\n that.cache = {x, y};\r\n options.onchange(x, y);\r\n },\r\n\r\n _tapstop() {\r\n _.off(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.off(document, ['mousemove', 'touchmove'], that._tapmove);\r\n },\r\n\r\n trigger() {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove();\r\n },\r\n\r\n update(x = 0, y = 0) {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove({\r\n clientX: that.wrapperRect.left + x,\r\n clientY: that.wrapperRect.top + y\r\n });\r\n },\r\n\r\n destroy() {\r\n const {options, _tapstart} = that;\r\n _.off([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.off([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n }\r\n };\r\n\r\n // Instance var\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Initilize\r\n const {options, _tapstart} = that;\r\n _.on([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.on([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n\r\n return that;\r\n}","// Import styles\r\nimport '../scss/pickr.scss';\r\n\r\n// Import utils\r\nimport * as _ from './lib/utils';\r\nimport * as Color from './lib/color';\r\n\r\n// Import classes\r\nimport {HSVaColor} from './lib/hsvacolor';\r\nimport Moveable from './helper/moveable';\r\nimport Selectable from './helper/selectable';\r\n\r\nclass Pickr {\r\n\r\n constructor(opt) {\r\n\r\n // Assign default values\r\n this.options = Object.assign({\r\n useAsButton: false,\r\n disabled: false,\r\n comparison: true,\r\n\r\n components: {interaction: {}},\r\n strings: {},\r\n\r\n default: 'fff',\r\n defaultRepresentation: 'HEX',\r\n position: 'middle',\r\n adjustableNumbers: true,\r\n showAlways: false,\r\n parent: undefined,\r\n\r\n closeWithKey: 'Escape',\r\n onChange: () => 0,\r\n onSave: () => 0,\r\n onClear: () => 0\r\n }, opt);\r\n\r\n // Check interaction section\r\n if (!this.options.components.interaction) {\r\n this.options.components.interaction = {};\r\n }\r\n\r\n // Will be used to prevent specific actions during initilization\r\n this._initializingActive = true;\r\n\r\n // Replace element with color picker\r\n this._recalc = true;\r\n\r\n // Current and last color for comparison\r\n this._color = new HSVaColor();\r\n this._lastColor = new HSVaColor();\r\n\r\n // Initialize picker\r\n this._preBuild();\r\n this._buildComponents();\r\n this._bindEvents();\r\n\r\n // Initialize color\r\n this.setColor(this.options.default);\r\n\r\n // Initialize color _epresentation\r\n this._representation = this.options.defaultRepresentation;\r\n this.setColorRepresentation(this._representation);\r\n\r\n // Initilization is finish, pickr is visible and ready to use\r\n this._initializingActive = false;\r\n\r\n // Finalize build\r\n this._finalBuild();\r\n this._rePositioningPicker();\r\n }\r\n\r\n // Does only the absolutly basic thing to initialize the components\r\n _preBuild() {\r\n const opt = this.options;\r\n\r\n // Check if element is selector\r\n if (typeof opt.el === 'string') {\r\n opt.el = document.querySelector(opt.el);\r\n }\r\n\r\n // Create element and append it to body to\r\n // prevent initialization errors\r\n this._root = create(opt);\r\n\r\n // Check if a custom button is used\r\n if (opt.useAsButton) {\r\n\r\n // Check if the user has an alternative location defined, used body as fallback\r\n if (!opt.parent) {\r\n opt.parent = 'body';\r\n }\r\n\r\n this._root.button = opt.el; // Replace button with customized button\r\n }\r\n\r\n document.body.appendChild(this._root.root);\r\n }\r\n\r\n _finalBuild() {\r\n const opt = this.options;\r\n const root = this._root;\r\n\r\n // Remove from body\r\n document.body.removeChild(root.root);\r\n\r\n // Check parent option\r\n if (opt.parent) {\r\n\r\n // Check if element is selector\r\n if (typeof opt.parent === 'string') {\r\n opt.parent = document.querySelector(opt.parent);\r\n }\r\n\r\n opt.parent.appendChild(root.app);\r\n }\r\n\r\n // Don't replace the the element if a custom button is used\r\n if (!opt.useAsButton) {\r\n\r\n // Replace element with actual color-picker\r\n opt.el.parentElement.replaceChild(root.root, opt.el);\r\n }\r\n\r\n // Call disable to also add the disabled class\r\n if (opt.disabled) {\r\n this.disable();\r\n }\r\n\r\n // Check if color comparison is disabled, if yes - remove transitions so everything keeps smoothly\r\n if (!opt.comparison) {\r\n root.button.style.transition = 'none';\r\n if (!opt.useAsButton) {\r\n root.preview.lastColor.style.transition = 'none';\r\n }\r\n }\r\n\r\n // Check showAlways option\r\n opt.showAlways ? root.app.classList.add('visible') : this.hide();\r\n }\r\n\r\n _buildComponents() {\r\n\r\n // Instance reference\r\n const inst = this;\r\n const comp = this.options.components;\r\n\r\n const components = {\r\n\r\n palette: Moveable({\r\n element: inst._root.palette.picker,\r\n wrapper: inst._root.palette.palette,\r\n\r\n onchange(x, y) {\r\n const {_color, _root, options} = inst;\r\n\r\n // Calculate saturation based on the position\r\n _color.s = (x / this.wrapper.offsetWidth) * 100;\r\n\r\n // Calculate the value\r\n _color.v = 100 - (y / this.wrapper.offsetHeight) * 100;\r\n\r\n // Prevent falling under zero\r\n _color.v < 0 ? _color.v = 0 : 0;\r\n\r\n // Set picker and gradient color\r\n const cssRGBaString = _color.toRGBA().toString();\r\n this.element.style.background = cssRGBaString;\r\n this.wrapper.style.background = `\r\n linear-gradient(to top, rgba(0, 0, 0, ${_color.a}), transparent), \r\n linear-gradient(to left, hsla(${_color.h}, 100%, 50%, ${_color.a}), rgba(255, 255, 255, ${_color.a}))\r\n `;\r\n\r\n // Check if color is locked\r\n if (!options.comparison) {\r\n _root.button.style.background = cssRGBaString;\r\n\r\n if (!options.useAsButton) {\r\n _root.preview.lastColor.style.background = cssRGBaString;\r\n }\r\n }\r\n\r\n // Change current color\r\n _root.preview.currentColor.style.background = cssRGBaString;\r\n\r\n // Update the input field only if the user is currently not typing\r\n if (inst._recalc) {\r\n inst._updateOutput();\r\n }\r\n\r\n // If the user changes the color, remove the cleared icon\r\n _root.button.classList.remove('clear');\r\n }\r\n }),\r\n\r\n hue: Moveable({\r\n lockX: true,\r\n element: inst._root.hue.picker,\r\n wrapper: inst._root.hue.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.hue) return;\r\n\r\n // Calculate hue\r\n inst._color.h = (y / this.wrapper.offsetHeight) * 360;\r\n\r\n // Update color\r\n this.element.style.backgroundColor = `hsl(${inst._color.h}, 100%, 50%)`;\r\n components.palette.trigger();\r\n }\r\n }),\r\n\r\n opacity: Moveable({\r\n lockX: true,\r\n element: inst._root.opacity.picker,\r\n wrapper: inst._root.opacity.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.opacity) return;\r\n\r\n // Calculate opacity\r\n inst._color.a = Math.round(((y / this.wrapper.offsetHeight)) * 1e2) / 100;\r\n\r\n // Update color\r\n this.element.style.background = `rgba(0, 0, 0, ${inst._color.a})`;\r\n inst.components.palette.trigger();\r\n }\r\n }),\r\n\r\n selectable: Selectable({\r\n elements: inst._root.interaction.options,\r\n className: 'active',\r\n onchange(e) {\r\n inst._representation = e.target.getAttribute('data-type').toUpperCase();\r\n inst._updateOutput();\r\n }\r\n })\r\n };\r\n\r\n this.components = components;\r\n }\r\n\r\n _bindEvents() {\r\n const {_root, options} = this;\r\n\r\n const eventBindings = [\r\n\r\n // Clear color\r\n _.on(_root.interaction.clear, 'click', () => this._clearColor()),\r\n\r\n // Select last color on click\r\n _.on(_root.preview.lastColor, 'click', () => this.setHSVA(...this._lastColor.toHSVA())),\r\n\r\n // Save color\r\n _.on(_root.interaction.save, 'click', () => {\r\n !this._saveColor() && !options.showAlways && this.hide();\r\n }),\r\n\r\n // Detect user input and disable auto-recalculation\r\n _.on(_root.interaction.result, ['keyup', 'input'], e => {\r\n this._recalc = false;\r\n\r\n // Fire listener if initialization is finish and changed color was valid\r\n if (this.setColor(e.target.value, true) && !this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n\r\n e.stopImmediatePropagation();\r\n }),\r\n\r\n // Cancel input detection on color change\r\n _.on([\r\n _root.palette.palette,\r\n _root.palette.picker,\r\n _root.hue.slider,\r\n _root.hue.picker,\r\n _root.opacity.slider,\r\n _root.opacity.picker\r\n ], ['mousedown', 'touchstart'], () => this._recalc = true),\r\n\r\n // Repositioning on resize\r\n _.on(window, 'resize', () => this._rePositioningPicker)\r\n ];\r\n\r\n // Provide hiding / showing abilities only if showAlways is false\r\n if (!options.showAlways) {\r\n\r\n // Save and hide / show picker\r\n eventBindings.push(_.on(_root.button, 'click', () => this.isOpen() ? this.hide() : this.show()));\r\n\r\n // Close with escape key\r\n const ck = options.closeWithKey;\r\n eventBindings.push(_.on(document, 'keyup', e => this.isOpen() && (e.key === ck || e.code === ck) && this.hide()));\r\n\r\n // Cancel selecting if the user taps behind the color picker\r\n eventBindings.push(_.on(document, ['touchstart', 'mousedown'], e => {\r\n if (this.isOpen() && !_.eventPath(e).some(el => el === _root.app || el === _root.button)) {\r\n this.hide();\r\n }\r\n }, {capture: true}));\r\n }\r\n\r\n // Make input adjustable if enabled\r\n if (options.adjustableNumbers) {\r\n _.adjustableInputNumbers(_root.interaction.result, false);\r\n }\r\n\r\n // Save bindings\r\n this._eventBindings = eventBindings;\r\n }\r\n\r\n _rePositioningPicker() {\r\n const root = this._root;\r\n const app = this._root.app;\r\n\r\n // Check if user has defined a parent\r\n if (this.options.parent) {\r\n const relative = root.button.getBoundingClientRect();\r\n app.style.position = 'fixed';\r\n app.style.marginLeft = `${relative.left}px`;\r\n app.style.marginTop = `${relative.top}px`;\r\n }\r\n\r\n const bb = root.button.getBoundingClientRect();\r\n const ab = app.getBoundingClientRect();\r\n const as = app.style;\r\n\r\n // Check if picker is cuttet of from the top & bottom\r\n if (ab.bottom > window.innerHeight) {\r\n as.top = `${-(ab.height) - 5}px`;\r\n } else if (bb.bottom + ab.height < window.innerHeight) {\r\n as.top = `${bb.height + 5}px`;\r\n }\r\n\r\n // Positioning picker on the x-axis\r\n const pos = {\r\n left: -(ab.width) + bb.width,\r\n middle: -(ab.width / 2) + bb.width / 2,\r\n right: 0\r\n };\r\n\r\n const cl = parseInt(getComputedStyle(app).left, 10);\r\n let newLeft = pos[this.options.position];\r\n const leftClip = (ab.left - cl) + newLeft;\r\n const rightClip = (ab.left - cl) + newLeft + ab.width;\r\n\r\n /**\r\n * First check if position is left or right but\r\n * pickr-app cannot set to left AND right because it would\r\n * be clipped by the browser width. If so, wrap it and position\r\n * pickr below button via the pos[middle] value.\r\n * The current selected posiotion should'nt be the middle.di\r\n */\r\n if (this.options.position !== 'middle' && (\r\n (leftClip < 0 && -leftClip < ab.width / 2) ||\r\n (rightClip > window.innerWidth && rightClip - window.innerWidth < ab.width / 2))) {\r\n newLeft = pos['middle'];\r\n\r\n /**\r\n * Even if set to middle pickr is getting clipped, so\r\n * set it to left / right.\r\n */\r\n } else if (leftClip < 0) {\r\n newLeft = pos['right'];\r\n } else if (rightClip > window.innerWidth) {\r\n newLeft = pos['left'];\r\n }\r\n\r\n as.left = `${newLeft}px`;\r\n }\r\n\r\n _updateOutput() {\r\n\r\n // Check if component is present\r\n if (this._root.interaction.type()) {\r\n\r\n this._root.interaction.result.value = (() => {\r\n\r\n // Construct function name and call if present\r\n const method = 'to' + this._root.interaction.type().getAttribute('data-type');\r\n return typeof this._color[method] === 'function' ? this._color[method]().toString() : '';\r\n })();\r\n }\r\n\r\n // Fire listener if initialization is finish\r\n if (!this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n }\r\n\r\n _saveColor() {\r\n const {preview, button} = this._root;\r\n\r\n // Change preview and current color\r\n const cssRGBaString = this._color.toRGBA().toString();\r\n preview.lastColor.style.background = cssRGBaString;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!this.options.useAsButton) {\r\n button.style.background = cssRGBaString;\r\n }\r\n\r\n // User changed the color so remove the clear clas\r\n button.classList.remove('clear');\r\n\r\n // Save last color\r\n this._lastColor = this._color.clone();\r\n\r\n // Fire listener\r\n if (!this._initializingActive) {\r\n this.options.onSave(this._color, this);\r\n }\r\n }\r\n\r\n _clearColor() {\r\n const {_root, options} = this;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!options.useAsButton) {\r\n _root.button.style.background = 'rgba(255, 255, 255, 0.4)';\r\n }\r\n\r\n _root.button.classList.add('clear');\r\n\r\n if (!options.showAlways) {\r\n this.hide();\r\n }\r\n\r\n // Fire listener\r\n options.onSave(null, this);\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys\r\n */\r\n destroy() {\r\n this._eventBindings.forEach(args => _.off(...args));\r\n Object.keys(this.components).forEach(key => this.components[key].destroy());\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys and removes\r\n * the pickr element.\r\n */\r\n destroyAndRemove() {\r\n this.destroy();\r\n\r\n // Remove element\r\n const root = this._root.root;\r\n root.parentElement.removeChild(root);\r\n }\r\n\r\n /**\r\n * Hides the color-picker ui.\r\n */\r\n hide() {\r\n this._root.app.classList.remove('visible');\r\n return this;\r\n }\r\n\r\n /**\r\n * Shows the color-picker ui.\r\n */\r\n show() {\r\n if (this.options.disabled) return;\r\n this._root.app.classList.add('visible');\r\n this._rePositioningPicker();\r\n return this;\r\n }\r\n\r\n /**\r\n * @return {boolean} If the color picker is currently open\r\n */\r\n isOpen() {\r\n return this._root.app.classList.contains('visible');\r\n }\r\n\r\n /**\r\n * Set a specific color.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @param a Alpha channel (0 - 1)\r\n * @param silent If the button should not change the color\r\n * @return true if the color has been accepted\r\n */\r\n setHSVA(h = 360, s = 0, v = 0, a = 1, silent = false) {\r\n\r\n // Deactivate color calculation\r\n const recalc = this._recalc; // Save state\r\n this._recalc = false;\r\n\r\n // Validate input\r\n if (h < 0 || h > 360 || s < 0 || s > 100 || v < 0 || v > 100 || a < 0 || a > 1) {\r\n return false;\r\n }\r\n\r\n // Short names\r\n const {hue, opacity, palette} = this.components;\r\n\r\n // Calculate y position of hue slider\r\n const hueWrapper = hue.options.wrapper;\r\n const hueY = hueWrapper.offsetHeight * (h / 360);\r\n hue.update(0, hueY);\r\n\r\n // Calculate y position of opacity slider\r\n const opacityWrapper = opacity.options.wrapper;\r\n const opacityY = opacityWrapper.offsetHeight * a;\r\n opacity.update(0, opacityY);\r\n\r\n // Calculate y and x position of color palette\r\n const pickerWrapper = palette.options.wrapper;\r\n const pickerX = pickerWrapper.offsetWidth * (s / 100);\r\n const pickerY = pickerWrapper.offsetHeight * (1 - (v / 100));\r\n palette.update(pickerX, pickerY);\r\n\r\n // Override current color and re-active color calculation\r\n this._color = new HSVaColor(h, s, v, a);\r\n this._recalc = recalc; // Restore old state\r\n\r\n // Update output if recalculation is enabled\r\n if (this._recalc) {\r\n this._updateOutput();\r\n }\r\n\r\n // Check if call is silent\r\n if (!silent) {\r\n this._saveColor();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Tries to parse a string which represents a color.\r\n * Examples: #fff\r\n * rgb 10 10 200\r\n * hsva 10 20 5 0.5\r\n * @param string\r\n * @param silent\r\n */\r\n setColor(string, silent = false) {\r\n\r\n // Check if null\r\n if (string === null) {\r\n this._clearColor();\r\n return true;\r\n }\r\n\r\n const {values, type} = Color.parseToHSV(string);\r\n\r\n // Check if color is ok\r\n if (values) {\r\n\r\n // Change selected color format\r\n const utype = type.toUpperCase();\r\n const {options} = this._root.interaction;\r\n const target = options.find(el => el.getAttribute('data-type') === utype);\r\n\r\n // Auto select only if not hidden\r\n if (!target.hidden) {\r\n for (const el of options) {\r\n el.classList[el === target ? 'add' : 'remove']('active');\r\n }\r\n }\r\n\r\n return this.setHSVA(...values, silent);\r\n }\r\n }\r\n\r\n /**\r\n * Changes the color _representation.\r\n * Allowed values are HEX, RGBA, HSVA, HSLA and CMYK\r\n * @param type\r\n * @returns {boolean} if the selected type was valid.\r\n */\r\n setColorRepresentation(type) {\r\n\r\n // Force uppercase to allow a case-sensitiv comparison\r\n type = type.toUpperCase();\r\n\r\n // Find button with given type and trigger click event\r\n return !!this._root.interaction.options.find(v => v.getAttribute('data-type') === type && !v.click());\r\n }\r\n\r\n /**\r\n * Returns the current color representaion. See setColorRepresentation\r\n * @returns {*}\r\n */\r\n getColorRepresentation() {\r\n return this._representation;\r\n }\r\n\r\n /**\r\n * @returns HSVaColor Current HSVaColor object.\r\n */\r\n getColor() {\r\n return this._color;\r\n }\r\n\r\n /**\r\n * @returns The root HTMLElement with all his components.\r\n */\r\n getRoot() {\r\n return this._root;\r\n }\r\n\r\n /**\r\n * Disable pickr\r\n */\r\n disable() {\r\n this.hide();\r\n this.options.disabled = true;\r\n this._root.button.classList.add('disabled');\r\n return this;\r\n }\r\n\r\n /**\r\n * Enable pickr\r\n */\r\n enable() {\r\n this.options.disabled = false;\r\n this._root.button.classList.remove('disabled');\r\n return this;\r\n }\r\n}\r\n\r\nfunction create(options) {\r\n const {components, strings, useAsButton} = options;\r\n const hidden = con => con ? '' : 'style=\"display:none\" hidden';\r\n\r\n const root = _.createFromTemplate(`\r\n
\r\n \r\n ${useAsButton ? '' : '
'}\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n
\r\n
\r\n
\r\n `);\r\n\r\n const int = root.interaction;\r\n\r\n // Select option which is not hidden\r\n int.options.find(o => !o.hidden && !o.classList.add('active'));\r\n\r\n // Create method to find currenlty active option\r\n int.type = () => int.options.find(e => e.classList.contains('active'));\r\n return root;\r\n}\r\n\r\n// Static methods\r\nPickr.utils = {\r\n once: _.once,\r\n on: _.on,\r\n off: _.off,\r\n eventPath: _.eventPath,\r\n createElementFromString: _.createElementFromString,\r\n adjustableInputNumbers: _.adjustableInputNumbers,\r\n removeAttribute: _.removeAttribute,\r\n createFromTemplate: _.createFromTemplate\r\n};\r\n\r\n// Create instance via method\r\nPickr.create = (options) => new Pickr(options);\r\n\r\n// Export\r\nPickr.version = '0.3.2';\r\nexport default Pickr;","import * as _ from './../lib/utils';\r\n\r\nexport default function Selectable(opt = {}) {\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n onchange: () => 0,\r\n className: '',\r\n elements: []\r\n }, opt),\r\n\r\n _ontap(evt) {\r\n const opt = that.options;\r\n opt.elements.forEach(e =>\r\n e.classList[evt.target === e ? 'add' : 'remove'](opt.className)\r\n );\r\n\r\n opt.onchange(evt);\r\n },\r\n\r\n destroy() {\r\n _.off(that.options.elements, 'click', this._ontap);\r\n }\r\n };\r\n\r\n _.on(that.options.elements, 'click', that._ontap);\r\n return that;\r\n}"],"sourceRoot":""} \ No newline at end of file From 2c1edc94dbbac4b83d11f86c8d04d8bca9cf2795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Fri, 30 Nov 2018 11:54:29 +0100 Subject: [PATCH 16/65] Demonstrating INotifier and localizers --HG-- branch : issue/OCORE-1 --- Controllers/YourFirstOrchardCoreController.cs | 2 +- Manifest.cs | 19 +++++++++++++++---- Views/YourFirstOrchardCore/Index.cshtml | 2 +- ...ActionWithRoute.cshtml => NotifyMe.cshtml} | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) rename Views/YourFirstOrchardCore/{ActionWithRoute.cshtml => NotifyMe.cshtml} (84%) diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index d6ed5738..207018cf 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -36,7 +36,7 @@ public ActionResult Index() => // For now we just return an empty view. This action is accessible from under // Lombiq.TraningDemo/YourFirstOrchard/Index route (appended to your site's root path; so using defaults it // would look something like this: - // http://localhost:44300/Lombiq.TraningDemo/YourFirstOrchard/Index) If you don't know how this + // http://localhost:44300/Lombiq.TraningDemo/YourFirstOrchardCore/Index) If you don't know how this // path gets together take a second look at how ASP.NET Core MVC routing works! View(new { Message = T["Hello you!"] }); diff --git a/Manifest.cs b/Manifest.cs index bad2af0d..22c78d7a 100644 --- a/Manifest.cs +++ b/Manifest.cs @@ -10,9 +10,20 @@ // Version of the module. Version = "2.0", // Short description of the module. It will be displayed on the the Dashboard. - Description = "Orchard Core training demo module for teaching Orchard Core fundamentals primarily by going through its source code.", - // Modules are categorized on the Dashboard so it's a good idea to put similar modules together to a separate section. - Category = "Training" + Description = "Orchard Core training demo module for teaching Orchard Core fundamentals primarily by going " + + "through its source code.", + // Modules are categorized on the Dashboard so it's a good idea to put similar modules together to a separate + // section. + Category = "Training", + // Modules can have dependencies which are other module names (name of the project) or if these modules have + // subfeatures then the name of the feature. If you use any service, taghelper etc. coming from an Orchard Core + // feature then you need to include them in this list. + Dependencies = new[] + { + "OrchardCore.Contents", + "OrchardCore.ContentTypes", + "OrchardCore.ContentFields" + } )] -// If you're done reading throught this file go to Controllers/YourFirstOrchardCoreController. \ No newline at end of file +// NEXT STATION: Controllers/YourFirstOrchardCoreController.cs \ No newline at end of file diff --git a/Views/YourFirstOrchardCore/Index.cshtml b/Views/YourFirstOrchardCore/Index.cshtml index e22e27ea..9c994c44 100644 --- a/Views/YourFirstOrchardCore/Index.cshtml +++ b/Views/YourFirstOrchardCore/Index.cshtml @@ -1,4 +1,4 @@ -Hello you! +@Model.Message @* This is a view template written in the Razor language (although not much to see from Razor here). diff --git a/Views/YourFirstOrchardCore/ActionWithRoute.cshtml b/Views/YourFirstOrchardCore/NotifyMe.cshtml similarity index 84% rename from Views/YourFirstOrchardCore/ActionWithRoute.cshtml rename to Views/YourFirstOrchardCore/NotifyMe.cshtml index f43445c7..b613d03a 100644 --- a/Views/YourFirstOrchardCore/ActionWithRoute.cshtml +++ b/Views/YourFirstOrchardCore/NotifyMe.cshtml @@ -1,4 +1,4 @@ -Hello you, using custom route! +@T["You should be notified."] @* If you've finished with both actions in the YourFirstOrchardCoreController (and their .cshtml files as well), then From 5e8264766483c90a5fd5e68ee2bb32562c26c2bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Fri, 30 Nov 2018 13:07:36 +0100 Subject: [PATCH 17/65] Demonstrating content item query --HG-- branch : issue/OCORE-1 --- Controllers/PersonListController.cs | 49 +++++++++++++++++++++++++++++ Views/PersonList/Index.cshtml | 3 -- Views/PersonList/OlderThan30.cshtml | 11 +++++++ Views/PersonPart.Summary.cshtml | 3 ++ 4 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 Controllers/PersonListController.cs delete mode 100644 Views/PersonList/Index.cshtml create mode 100644 Views/PersonList/OlderThan30.cshtml create mode 100644 Views/PersonPart.Summary.cshtml diff --git a/Controllers/PersonListController.cs b/Controllers/PersonListController.cs new file mode 100644 index 00000000..4e3db47d --- /dev/null +++ b/Controllers/PersonListController.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Lombiq.TrainingDemo.Indexes; +using Microsoft.AspNetCore.Mvc; +using OrchardCore.ContentManagement; +using OrchardCore.ContentManagement.Display; +using OrchardCore.ContentManagement.Records; +using OrchardCore.DisplayManagement.ModelBinding; +using OrchardCore.Modules; +using YesSql; + +namespace Lombiq.TrainingDemo.Controllers +{ + public class PersonListController : Controller, IUpdateModel + { + private readonly ISession _session; + private readonly IClock _clock; + private readonly IContentItemDisplayManager _contentItemDisplayManager; + + + public PersonListController( + ISession session, + IClock clock, + IContentItemDisplayManager contentItemDisplayManager) + { + _session = session; + _clock = clock; + _contentItemDisplayManager = contentItemDisplayManager; + } + + + public async Task OlderThan30() + { + var thresholdDate = _clock.UtcNow.AddYears(-30); + var people = await _session + .Query(index => index.BirthDateUtc < thresholdDate) + .ListAsync(); + + var shapes = people + .Select(async person => await _contentItemDisplayManager.BuildDisplayAsync(person, this, "Summary")) + .Select(task => task.Result); + + return View(shapes); + } + } +} diff --git a/Views/PersonList/Index.cshtml b/Views/PersonList/Index.cshtml deleted file mode 100644 index 5fa97d88..00000000 --- a/Views/PersonList/Index.cshtml +++ /dev/null @@ -1,3 +0,0 @@ -@model OrchardCore.ContentManagement.ContentItem - -@Model \ No newline at end of file diff --git a/Views/PersonList/OlderThan30.cshtml b/Views/PersonList/OlderThan30.cshtml new file mode 100644 index 00000000..ee283813 --- /dev/null +++ b/Views/PersonList/OlderThan30.cshtml @@ -0,0 +1,11 @@ +@model IEnumerable + +

@T["People older then 30 years old"]

+
    + @foreach (var shape in Model) + { +
  • + @await DisplayAsync(shape) +
  • + } +
\ No newline at end of file diff --git a/Views/PersonPart.Summary.cshtml b/Views/PersonPart.Summary.cshtml new file mode 100644 index 00000000..5af032cb --- /dev/null +++ b/Views/PersonPart.Summary.cshtml @@ -0,0 +1,3 @@ +@model ShapeViewModel + +@Model.Value.Name \ No newline at end of file From 6289cbc9185f9aed469a5020a6586da947ae15be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Sat, 1 Dec 2018 10:48:15 +0100 Subject: [PATCH 18/65] Automating copying assets from node modules and Assets folder --HG-- branch : issue/OCORE-1 --- .gitignore | 2 + .hgignore | 2 + Assets.json | 61 + {wwwroot => Assets/Images}/HarryPotter.jpg | Bin Assets/pickr/pickr.min.css | 1 - Assets/pickr/pickr.min.js | 2 - Assets/pickr/pickr.min.js.map | 1 - Controllers/DisplayManagementController.cs | 2 +- Controllers/PersonListController.cs | 28 +- Gulpfile.js | 21 + Lombiq.TrainingDemo.csproj | 25 +- package-lock.json | 2269 ++++++++++++++++++++ package.json | 9 + wwwroot/pickr/pickr.min.css | 1 - wwwroot/pickr/pickr.min.js | 2 - wwwroot/pickr/pickr.min.js.map | 1 - 16 files changed, 2390 insertions(+), 37 deletions(-) create mode 100644 Assets.json rename {wwwroot => Assets/Images}/HarryPotter.jpg (100%) delete mode 100644 Assets/pickr/pickr.min.css delete mode 100644 Assets/pickr/pickr.min.js delete mode 100644 Assets/pickr/pickr.min.js.map create mode 100644 Gulpfile.js create mode 100644 package-lock.json create mode 100644 package.json delete mode 100644 wwwroot/pickr/pickr.min.css delete mode 100644 wwwroot/pickr/pickr.min.js delete mode 100644 wwwroot/pickr/pickr.min.js.map diff --git a/.gitignore b/.gitignore index 9bce83a5..46549b9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ obj/ bin/ *.user +wwwroot +node_modules diff --git a/.hgignore b/.hgignore index 123cfa78..91812926 100644 --- a/.hgignore +++ b/.hgignore @@ -2,3 +2,5 @@ syntax: glob obj/ bin/ *.user +wwwroot +node_modules diff --git a/Assets.json b/Assets.json new file mode 100644 index 00000000..68b2d6f0 --- /dev/null +++ b/Assets.json @@ -0,0 +1,61 @@ +[ + { + "inputs": [ + "Assets/Lib/jsplumb/jsplumbtoolkit-defaults.css" + ], + "output": "wwwroot/Styles/jsplumbtoolkit-defaults.css" + }, + { + "inputs": [ + "Assets/Lib/jsplumb/jsplumb.js" + ], + "output": "wwwroot/Scripts/jsplumb.js" + }, + { + "inputs": [ + "Assets/Styles/workflow-editor.scss" + ], + "output": "wwwroot/Styles/orchard.workflows-editor.css" + }, + { + "inputs": [ + "Assets/Styles/workflow-viewer.scss" + ], + "output": "wwwroot/Styles/orchard.workflows-viewer.css" + }, + { + "inputs": [ + "Assets/Styles/admin-menu.scss" + ], + "output": "wwwroot/Styles/menu.workflows-admin.css" + }, + { + "inputs": [ + "Assets/Scripts/activity-picker.ts", + "Assets/Scripts/workflow-url-generator.ts", + "Assets/Scripts/workflow-canvas.ts", + "Assets/Scripts/workflow-editor.ts" + ], + "output": "wwwroot/Scripts/orchard.workflows-editor.js" + }, + { + "inputs": [ + "HTTP/Assets/Scripts/workflow-url-generator.ts" + ], + "output": "wwwroot/Scripts/orchard.http-request-event-editor.js" + }, + { + "inputs": [ + "./node_modules/", + "Assets/Scripts/workflow-viewer.ts" + ], + "output": "wwwroot/Scripts/orchard.workflows-viewer.js" + }, + { + "copy": true, + "inputs": [ + "Assets/Images/*" + ], + "output": "wwwroot/Images/@" + } +] diff --git a/wwwroot/HarryPotter.jpg b/Assets/Images/HarryPotter.jpg similarity index 100% rename from wwwroot/HarryPotter.jpg rename to Assets/Images/HarryPotter.jpg diff --git a/Assets/pickr/pickr.min.css b/Assets/pickr/pickr.min.css deleted file mode 100644 index 5c8c5a6e..00000000 --- a/Assets/pickr/pickr.min.css +++ /dev/null @@ -1 +0,0 @@ -.pickr{position:relative;overflow:visible;z-index:1}.pickr *{box-sizing:border-box}.pickr .pcr-button{position:relative;height:2em;width:2em;padding:.5em;border-radius:.15em;cursor:pointer;background:transparent;transition:background-color .3s;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.pickr .pcr-button:before{background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pickr .pcr-button:after,.pickr .pcr-button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%}.pickr .pcr-button:after{background:url('data:image/svg+xml;utf8, ') no-repeat 50%;background-size:70%;opacity:0}.pickr .pcr-button.clear:after{opacity:1}.pickr .pcr-button.disabled{cursor:not-allowed}.pcr-app{position:absolute;display:flex;flex-direction:column;z-index:10000;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;box-shadow:0 .2em 1.5em 0 rgba(0,0,0,.1),0 0 1em 0 rgba(0,0,0,.02);top:5px;height:15em;width:28em;max-width:95vw;padding:.8em;border-radius:.1em;background:#fff;opacity:0;visibility:hidden;transition:opacity .3s}.pcr-app.visible{visibility:visible;opacity:1}.pcr-app .pcr-interaction{display:flex;align-items:center;margin:1em -.2em 0}.pcr-app .pcr-interaction>*{margin:0 .2em}.pcr-app .pcr-interaction input{padding:.5em .6em;border:none;outline:none;letter-spacing:.07em;font-size:.75em;text-align:center;cursor:pointer;color:#c4c4c4;background:#f8f8f8;border-radius:.15em;transition:all .15s}.pcr-app .pcr-interaction input:hover{color:grey}.pcr-app .pcr-interaction .pcr-result{color:grey;text-align:left;flex-grow:1;min-width:1em;transition:all .2s;border-radius:.15em;background:#f8f8f8;cursor:text;padding-left:.8em}.pcr-app .pcr-interaction .pcr-result:focus{color:#4285f4}.pcr-app .pcr-interaction .pcr-result::selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-type.active{color:#fff;background:#4285f4}.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-save{color:#fff;width:auto}.pcr-app .pcr-interaction .pcr-save{background:#4285f4}.pcr-app .pcr-interaction .pcr-save:hover{background:#4370f4;color:#fff}.pcr-app .pcr-interaction .pcr-clear{background:#f44250}.pcr-app .pcr-interaction .pcr-clear:hover{background:#db3d49;color:#fff}.pcr-app .pcr-selection{display:flex;justify-content:space-between;flex-grow:1}.pcr-app .pcr-selection .pcr-picker{position:absolute;height:18px;width:18px;border:2px solid #fff;border-radius:100%;user-select:none;cursor:-moz-grab;cursor:-webkit-grabbing}.pcr-app .pcr-selection .pcr-color-preview{position:relative;z-index:1;width:2em;display:flex;flex-direction:column;justify-content:space-between;margin-right:.75em}.pcr-app .pcr-selection .pcr-color-preview:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{cursor:pointer;transition:background-color .3s;border-radius:.15em .15em 0 0}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color{border-radius:0 0 .15em .15em}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color,.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{background:transparent;width:100%;height:50%}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity,.pcr-app .pcr-selection .pcr-color-palette{position:relative;user-select:none;display:flex;flex-direction:column}.pcr-app .pcr-selection .pcr-color-palette{width:100%;z-index:1}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette{height:100%;border-radius:.15em}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity{margin-left:.75em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app .pcr-selection .pcr-color-opacity .pcr-picker{left:50%;transform:translateX(-50%)}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{width:8px;height:100%;border-radius:50em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider{background:linear-gradient(180deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{background:linear-gradient(180deg,transparent,#000),url('data:image/svg+xml;utf8, ');background-size:100%,50%} \ No newline at end of file diff --git a/Assets/pickr/pickr.min.js b/Assets/pickr/pickr.min.js deleted file mode 100644 index 0adc2483..00000000 --- a/Assets/pickr/pickr.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Pickr=e():t.Pickr=e()}(window,function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="dist/",n(n.s=1)}([function(t,e,n){},function(t,e,n){"use strict";n.r(e);var o={};n.r(o),n.d(o,"once",function(){return a}),n.d(o,"on",function(){return c}),n.d(o,"off",function(){return s}),n.d(o,"createElementFromString",function(){return l}),n.d(o,"removeAttribute",function(){return p}),n.d(o,"createFromTemplate",function(){return d}),n.d(o,"eventPath",function(){return h}),n.d(o,"adjustableInputNumbers",function(){return f});var r={};n.r(r),n.d(r,"hsvToRgb",function(){return b}),n.d(r,"hsvToHex",function(){return _}),n.d(r,"hsvToCmyk",function(){return w}),n.d(r,"hsvToHsl",function(){return k}),n.d(r,"parseToHSV",function(){return j});n(0);function i(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var a=function(t,e,n,o){return c(t,e,function t(){n.apply(this,arguments),this.removeEventListener(e,t)},o)},c=u.bind(null,"addEventListener"),s=u.bind(null,"removeEventListener");function u(t,e,n,o){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};return e instanceof HTMLCollection||e instanceof NodeList?e=Array.from(e):Array.isArray(e)||(e=[e]),Array.isArray(n)||(n=[n]),e.forEach(function(e){return n.forEach(function(n){return e[t](n,o,function(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{},o=p(e,"data-con"),r=p(e,"data-key");r&&(n[r]=e);for(var i=Array.from(e.children),a=o?n[o]={}:n,c=0;c1&&void 0!==arguments[1])||arguments[1],n=function(t){return t>="0"&&t<="9"||"-"===t||"."===t};function o(o){for(var r=t.value,i=t.selectionStart,a=i,c="",s=i-1;s>0&&n(r[s]);s--)c=r[s]+c,a--;for(var u=i,l=r.length;u0&&!isNaN(c)&&isFinite(c)){var p=o.deltaY<0?1:-1,d=o.ctrlKey?5*p:p,h=Number(c)+d;!e&&h<0&&(h=0);var f=r.substr(0,a)+h+r.substring(a+c.length,r.length),v=a+String(h).length;t.value=f,t.focus(),t.setSelectionRange(v,v)}o.preventDefault(),t.dispatchEvent(new Event("input"))}c(t,"focus",function(){return c(window,"wheel",o)}),c(t,"blur",function(){return s(window,"wheel",o)})}function v(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=[],o=!0,r=!1,i=void 0;try{for(var a,c=t[Symbol.iterator]();!(o=(a=c.next()).done)&&(n.push(a.value),!e||n.length!==e);o=!0);}catch(t){r=!0,i=t}finally{try{o||null==c.return||c.return()}finally{if(r)throw i}}return n}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function y(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e1&&(o-=1)}return[360*o,100*r,100*i]}function C(t,e,n,o){return e/=100,n/=100,y(A(255*(1-g(1,(t/=100)*(1-(o/=100))+o)),255*(1-g(1,e*(1-o)+o)),255*(1-g(1,n*(1-o)+o))))}function S(t,e,n){return e/=100,[t,2*(e*=(n/=100)<.5?n:1-n)/(n+e)*100,100*(n+e)]}function O(t){return A.apply(void 0,y(t.match(/.{2}/g).map(function(t){return parseInt(t,16)})))}function j(t){var e,n={cmyk:/^cmyk[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)/i,rgba:/^(rgb|rgba)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsla:/^(hsl|hsla)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsva:/^(hsv|hsva)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hex:/^#?(([\dA-Fa-f]{3,4})|([\dA-Fa-f]{6})|([\dA-Fa-f]{8}))$/i},o=function(t){return t.map(function(t){return/^(|\d+)\.\d+|\d+$/.test(t)?Number(t):void 0})};for(var r in n)if(e=n[r].exec(t))switch(r){case"cmyk":var i=v(o(e),5),a=i[1],c=i[2],s=i[3],u=i[4];if(a>100||c>100||s>100||u>100)break;return{values:y(C(a,c,s,u)).concat([1]),type:r};case"rgba":var l=v(o(e),6),p=l[2],d=l[3],h=l[4],f=l[5],g=void 0===f?1:f;if(p>255||d>255||h>255||g<0||g>1)break;return{values:y(A(p,d,h)).concat([g]),type:r};case"hex":var m=function(t,e){return[t.substring(0,e),t.substring(e,t.length)]},b=v(e,2)[1];3===b.length?b+="F":6===b.length&&(b+="FF");var _=void 0;if(4===b.length){var w=v(m(b,3).map(function(t){return t+t}),2);b=w[0],_=w[1]}else if(8===b.length){var k=v(m(b,6),2);b=k[0],_=k[1]}return _=parseInt(_,16)/255,{values:y(O(b)).concat([_]),type:r};case"hsla":var j=v(o(e),6),x=j[2],E=j[3],H=j[4],R=j[5],B=void 0===R?1:R;if(x>360||E>100||H>100||B<0||B>1)break;return{values:y(S(x,E,H)).concat([B]),type:r};case"hsva":var P=v(o(e),6),L=P[2],D=P[3],T=P[4],F=P[5],M=void 0===F?1:F;if(L>360||D>100||T>100||M<0||M>1)break;return{values:[L,D,T,M],type:r}}return{values:null,type:null}}function x(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,i=Math.ceil,a={h:t,s:e,v:n,a:o,toHSVA:function(){var t=[a.h,a.s,a.v],e=t.map(i);return t.toString=function(){return"hsva(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toHSLA:function(){var t=k(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"hsla(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toRGBA:function(){var t=b(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"rgba(".concat(e[0],", ").concat(e[1],", ").concat(e[2],", ").concat(a.a.toFixed(1),")")},t},toCMYK:function(){var t=w(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"cmyk(".concat(e[0],"%, ").concat(e[1],"%, ").concat(e[2],"%, ").concat(e[3],"%)")},t},toHEX:function(){var t=_.apply(r,[a.h,a.s,a.v]);return t.toString=function(){var e=a.a>=1?"":Number((255*a.a).toFixed(0)).toString(16).toUpperCase().padStart(2,"0");return"#".concat(t.join("").toUpperCase()+e)},t},clone:function(){return x(a.h,a.s,a.v,a.a)}};return a}function E(t){var e={options:Object.assign({lockX:!1,lockY:!1,onchange:function(){return 0}},t),_tapstart:function(t){c(document,["mouseup","touchend","touchcancel"],e._tapstop),c(document,["mousemove","touchmove"],e._tapmove),t.preventDefault(),e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove(t)},_tapmove:function(t){var n=e.options,o=e.cache,r=n.element,i=e.wrapperRect,a=0,c=0;if(t){var s=t&&t.touches&&t.touches[0];a=t?(s||t).clientX:0,c=t?(s||t).clientY:0,ai.left+i.width&&(a=i.left+i.width),ci.top+i.height&&(c=i.top+i.height),a-=i.left,c-=i.top}else o&&(a=o.x,c=o.y);n.lockX||(r.style.left=a-r.offsetWidth/2+"px"),n.lockY||(r.style.top=c-r.offsetHeight/2+"px"),e.cache={x:a,y:c},n.onchange(a,c)},_tapstop:function(){s(document,["mouseup","touchend","touchcancel"],e._tapstop),s(document,["mousemove","touchmove"],e._tapmove)},trigger:function(){e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove()},update:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove({clientX:e.wrapperRect.left+t,clientY:e.wrapperRect.top+n})},destroy:function(){var t=e.options,n=e._tapstart;s([t.wrapper,t.element],"mousedown",n),s([t.wrapper,t.element],"touchstart",n,{passive:!1})}};e.wrapperRect=e.options.wrapper.getBoundingClientRect();var n=e.options,o=e._tapstart;return c([n.wrapper,n.element],"mousedown",o),c([n.wrapper,n.element],"touchstart",o,{passive:!1}),e}function H(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e\n \n '.concat(o?"":'
','\n\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n\n
\n \n\n \n \n \n \n \n\n \n \n
\n
\n \n ")),a=i.interaction;return a.options.find(function(t){return!t.hidden&&!t.classList.add("active")}),a.type=function(){return a.options.find(function(t){return t.classList.contains("active")})},i}(t),t.useAsButton&&(t.parent||(t.parent="body"),this._root.button=t.el),document.body.appendChild(this._root.root)}},{key:"_finalBuild",value:function(){var t=this.options,e=this._root;document.body.removeChild(e.root),t.parent&&("string"==typeof t.parent&&(t.parent=document.querySelector(t.parent)),t.parent.appendChild(e.app)),t.useAsButton||t.el.parentElement.replaceChild(e.root,t.el),t.disabled&&this.disable(),t.comparison||(e.button.style.transition="none",t.useAsButton||(e.preview.lastColor.style.transition="none")),t.showAlways?e.app.classList.add("visible"):this.hide()}},{key:"_buildComponents",value:function(){var t=this,e=this.options.components,n={palette:E({element:t._root.palette.picker,wrapper:t._root.palette.palette,onchange:function(e,n){var o=t._color,r=t._root,i=t.options;o.s=e/this.wrapper.offsetWidth*100,o.v=100-n/this.wrapper.offsetHeight*100,o.v<0&&(o.v=0);var a=o.toRGBA().toString();this.element.style.background=a,this.wrapper.style.background="\n linear-gradient(to top, rgba(0, 0, 0, ".concat(o.a,"), transparent), \n linear-gradient(to left, hsla(").concat(o.h,", 100%, 50%, ").concat(o.a,"), rgba(255, 255, 255, ").concat(o.a,"))\n "),i.comparison||(r.button.style.background=a,i.useAsButton||(r.preview.lastColor.style.background=a)),r.preview.currentColor.style.background=a,t._recalc&&t._updateOutput(),r.button.classList.remove("clear")}}),hue:E({lockX:!0,element:t._root.hue.picker,wrapper:t._root.hue.slider,onchange:function(o,r){e.hue&&(t._color.h=r/this.wrapper.offsetHeight*360,this.element.style.backgroundColor="hsl(".concat(t._color.h,", 100%, 50%)"),n.palette.trigger())}}),opacity:E({lockX:!0,element:t._root.opacity.picker,wrapper:t._root.opacity.slider,onchange:function(n,o){e.opacity&&(t._color.a=Math.round(o/this.wrapper.offsetHeight*100)/100,this.element.style.background="rgba(0, 0, 0, ".concat(t._color.a,")"),t.components.palette.trigger())}}),selectable:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e={options:Object.assign({onchange:function(){return 0},className:"",elements:[]},t),_ontap:function(t){var n=e.options;n.elements.forEach(function(e){return e.classList[t.target===e?"add":"remove"](n.className)}),n.onchange(t)},destroy:function(){s(e.options.elements,"click",this._ontap)}};return c(e.options.elements,"click",e._ontap),e}({elements:t._root.interaction.options,className:"active",onchange:function(e){t._representation=e.target.getAttribute("data-type").toUpperCase(),t._updateOutput()}})};this.components=n}},{key:"_bindEvents",value:function(){var t=this,e=this._root,n=this.options,o=[c(e.interaction.clear,"click",function(){return t._clearColor()}),c(e.preview.lastColor,"click",function(){return t.setHSVA.apply(t,H(t._lastColor.toHSVA()))}),c(e.interaction.save,"click",function(){!t._saveColor()&&!n.showAlways&&t.hide()}),c(e.interaction.result,["keyup","input"],function(e){t._recalc=!1,t.setColor(e.target.value,!0)&&!t._initializingActive&&t.options.onChange(t._color,t),e.stopImmediatePropagation()}),c([e.palette.palette,e.palette.picker,e.hue.slider,e.hue.picker,e.opacity.slider,e.opacity.picker],["mousedown","touchstart"],function(){return t._recalc=!0}),c(window,"resize",function(){return t._rePositioningPicker})];if(!n.showAlways){o.push(c(e.button,"click",function(){return t.isOpen()?t.hide():t.show()}));var r=n.closeWithKey;o.push(c(document,"keyup",function(e){return t.isOpen()&&(e.key===r||e.code===r)&&t.hide()})),o.push(c(document,["touchstart","mousedown"],function(n){t.isOpen()&&!h(n).some(function(t){return t===e.app||t===e.button})&&t.hide()},{capture:!0}))}n.adjustableNumbers&&f(e.interaction.result,!1),this._eventBindings=o}},{key:"_rePositioningPicker",value:function(){var t=this._root,e=this._root.app;if(this.options.parent){var n=t.button.getBoundingClientRect();e.style.position="fixed",e.style.marginLeft="".concat(n.left,"px"),e.style.marginTop="".concat(n.top,"px")}var o=t.button.getBoundingClientRect(),r=e.getBoundingClientRect(),i=e.style;r.bottom>window.innerHeight?i.top="".concat(-r.height-5,"px"):o.bottom+r.heightwindow.innerWidth&&l-window.innerWidthwindow.innerWidth&&(s=a.left),i.left="".concat(s,"px")}},{key:"_updateOutput",value:function(){var t=this;this._root.interaction.type()&&(this._root.interaction.result.value=function(){var e="to"+t._root.interaction.type().getAttribute("data-type");return"function"==typeof t._color[e]?t._color[e]().toString():""}()),this._initializingActive||this.options.onChange(this._color,this)}},{key:"_saveColor",value:function(){var t=this._root,e=t.preview,n=t.button,o=this._color.toRGBA().toString();e.lastColor.style.background=o,this.options.useAsButton||(n.style.background=o),n.classList.remove("clear"),this._lastColor=this._color.clone(),this._initializingActive||this.options.onSave(this._color,this)}},{key:"_clearColor",value:function(){var t=this._root,e=this.options;e.useAsButton||(t.button.style.background="rgba(255, 255, 255, 0.4)"),t.button.classList.add("clear"),e.showAlways||this.hide(),e.onSave(null,this)}},{key:"destroy",value:function(){var t=this;this._eventBindings.forEach(function(t){return s.apply(o,H(t))}),Object.keys(this.components).forEach(function(e){return t.components[e].destroy()})}},{key:"destroyAndRemove",value:function(){this.destroy();var t=this._root.root;t.parentElement.removeChild(t)}},{key:"hide",value:function(){return this._root.app.classList.remove("visible"),this}},{key:"show",value:function(){if(!this.options.disabled)return this._root.app.classList.add("visible"),this._rePositioningPicker(),this}},{key:"isOpen",value:function(){return this._root.app.classList.contains("visible")}},{key:"setHSVA",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:360,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]&&arguments[4],i=this._recalc;if(this._recalc=!1,t<0||t>360||e<0||e>100||n<0||n>100||o<0||o>1)return!1;var a=this.components,c=a.hue,s=a.opacity,u=a.palette,l=c.options.wrapper.offsetHeight*(t/360);c.update(0,l);var p=s.options.wrapper.offsetHeight*o;s.update(0,p);var d=u.options.wrapper,h=d.offsetWidth*(e/100),f=d.offsetHeight*(1-n/100);return u.update(h,f),this._color=new x(t,e,n,o),this._recalc=i,this._recalc&&this._updateOutput(),r||this._saveColor(),!0}},{key:"setColor",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(null===t)return this._clearColor(),!0;var n=j(t),o=n.values,r=n.type;if(o){var i=r.toUpperCase(),a=this._root.interaction.options,c=a.find(function(t){return t.getAttribute("data-type")===i});if(!c.hidden){var s=!0,u=!1,l=void 0;try{for(var p,d=a[Symbol.iterator]();!(s=(p=d.next()).done);s=!0){var h=p.value;h.classList[h===c?"add":"remove"]("active")}}catch(t){u=!0,l=t}finally{try{s||null==d.return||d.return()}finally{if(u)throw l}}}return this.setHSVA.apply(this,H(o).concat([e]))}}},{key:"setColorRepresentation",value:function(t){return t=t.toUpperCase(),!!this._root.interaction.options.find(function(e){return e.getAttribute("data-type")===t&&!e.click()})}},{key:"getColorRepresentation",value:function(){return this._representation}},{key:"getColor",value:function(){return this._color}},{key:"getRoot",value:function(){return this._root}},{key:"disable",value:function(){return this.hide(),this.options.disabled=!0,this._root.button.classList.add("disabled"),this}},{key:"enable",value:function(){return this.options.disabled=!1,this._root.button.classList.remove("disabled"),this}}]),t}();B.utils={once:a,on:c,off:s,eventPath:h,createElementFromString:l,adjustableInputNumbers:f,removeAttribute:p,createFromTemplate:d},B.create=function(t){return new B(t)},B.version="0.3.2";e.default=B}]).default}); -//# sourceMappingURL=pickr.min.js.map \ No newline at end of file diff --git a/Assets/pickr/pickr.min.js.map b/Assets/pickr/pickr.min.js.map deleted file mode 100644 index 5ea5deef..00000000 --- a/Assets/pickr/pickr.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap","webpack:///./src/js/lib/utils.js","webpack:///./src/js/lib/color.js","webpack:///./src/js/lib/hsvacolor.js","webpack:///./src/js/helper/moveable.js","webpack:///./src/js/pickr.js","webpack:///./src/js/helper/selectable.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","once","element","event","fn","options","on","helper","apply","this","arguments","removeEventListener","eventListener","off","method","elements","events","length","undefined","HTMLCollection","NodeList","Array","from","isArray","forEach","el","ev","_objectSpread","capture","slice","createElementFromString","html","div","document","createElement","innerHTML","trim","firstElementChild","removeAttribute","getAttribute","createFromTemplate","str","resolve","base","con","children","subtree","_i","child","arr","push","eventPath","evt","path","composedPath","target","parentElement","adjustableInputNumbers","negative","isNumChar","handleScroll","e","val","selectionStart","numStart","num","isNaN","isFinite","mul","deltaY","inc","ctrlKey","newNum","Number","newStr","substr","substring","curPos","String","focus","setSelectionRange","preventDefault","dispatchEvent","Event","min","Math","max","hsvToRgb","h","v","floor","f","q","mod","hsvToHex","map","round","toString","padStart","hsvToCmyk","k","rgb","g","b","hsvToHsl","rgbToHsv","minVal","maxVal","delta","dr","dg","db","cmykToHsv","y","_toConsumableArray","hslToHsv","hexToHsv","hex","match","parseInt","parseToHSV","regex","cmyk","rgba","hsla","hsva","numarize","array","test","type","exec","_numarize2","_slicedToArray","values","concat","_numarize4","_numarize4$","a","splitAt","alpha","_splitAt$map2","_splitAt2","_numarize6","_numarize6$","_numarize8","_numarize8$","HSVaColor","ceil","that","toHSVA","hsv","rhsv","toFixed","toHSLA","hsl","Color","rhsl","toRGBA","rrgb","toCMYK","rcmyk","toHEX","toUpperCase","join","clone","Moveable","opt","assign","lockX","lockY","onchange","_tapstart","_","_tapstop","_tapmove","wrapperRect","wrapper","getBoundingClientRect","cache","x","touch","touches","clientX","clientY","left","width","top","height","style","offsetWidth","offsetHeight","trigger","update","destroy","passive","Pickr","_classCallCheck","useAsButton","disabled","comparison","components","interaction","strings","default","defaultRepresentation","position","adjustableNumbers","showAlways","parent","closeWithKey","onChange","onSave","onClear","_initializingActive","_recalc","_color","_lastColor","_preBuild","_buildComponents","_bindEvents","setColor","_representation","setColorRepresentation","_finalBuild","_rePositioningPicker","querySelector","_root","hidden","preview","hue","opacity","keys","input","save","clear","int","find","classList","add","contains","button","body","appendChild","removeChild","app","replaceChild","disable","transition","lastColor","hide","inst","comp","palette","picker","cssRGBaString","background","currentColor","_updateOutput","remove","slider","backgroundColor","selectable","className","_ontap","Selectable","_this","eventBindings","_clearColor","setHSVA","pickr_toConsumableArray","_saveColor","result","stopImmediatePropagation","isOpen","show","ck","code","some","_eventBindings","relative","marginLeft","marginTop","bb","ab","as","bottom","innerHeight","pos","middle","right","cl","getComputedStyle","newLeft","leftClip","rightClip","innerWidth","_this2","_this$_root","_this3","args","silent","recalc","_this$components","hueY","opacityY","pickerWrapper","pickerX","pickerY","string","_Color$parseToHSV","utype","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_step","_iterator","iterator","next","done","err","return","click","utils","version"],"mappings":"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","file":"pickr.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Pickr\"] = factory();\n\telse\n\t\troot[\"Pickr\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/**\r\n * Add an eventlistener which will be fired only once.\r\n *\r\n * @param element Target element\r\n * @param event Event name\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const once = (element, event, fn, options) => on(element, event, function helper() {\r\n fn.apply(this, arguments);\r\n this.removeEventListener(event, helper);\r\n}, options);\r\n\r\n/**\r\n * Add event(s) to element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const on = eventListener.bind(null, 'addEventListener');\r\n\r\n/**\r\n * Remove event(s) from element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const off = eventListener.bind(null, 'removeEventListener');\r\n\r\nfunction eventListener(method, elements, events, fn, options = {}) {\r\n\r\n // Normalize array\r\n if (elements instanceof HTMLCollection || elements instanceof NodeList) {\r\n elements = Array.from(elements);\r\n } else if (!Array.isArray(elements)) {\r\n elements = [elements];\r\n }\r\n\r\n if (!Array.isArray(events)) {\r\n events = [events];\r\n }\r\n\r\n elements.forEach(el =>\r\n events.forEach(ev =>\r\n el[method](ev, fn, {capture: false, ...options})\r\n )\r\n );\r\n\r\n return Array.prototype.slice.call(arguments, 1);\r\n}\r\n\r\n/**\r\n * Creates an DOM-Element out of a string (Single element).\r\n * @param html HTML representing a single element\r\n * @returns {Element | null} The element.\r\n */\r\nexport function createElementFromString(html) {\r\n const div = document.createElement('div');\r\n div.innerHTML = html.trim();\r\n return div.firstElementChild;\r\n}\r\n\r\n/**\r\n * Removes an attribute from a HTMLElement and returns the value.\r\n * @param el\r\n * @param name\r\n * @return {string}\r\n */\r\nexport function removeAttribute(el, name) {\r\n const value = el.getAttribute(name);\r\n el.removeAttribute(name);\r\n return value;\r\n}\r\n\r\n/**\r\n * Creates a new html element, every element which has\r\n * a 'data-key' attribute will be saved in a object (which will be returned)\r\n * where the value of 'data-key' ist the object-key and the value the HTMLElement.\r\n *\r\n * It's possible to create a hierarchy if you add a 'data-con' attribute. Every\r\n * sibling will be added to the object which will get the name from the 'data-con' attribute.\r\n *\r\n * If you want to create an Array out of multiple elements, you can use the 'data-arr' attribute,\r\n * the value defines the key and all elements, which has the same parent and the same 'data-arr' attribute,\r\n * would be added to it.\r\n *\r\n * @param str - The HTML String.\r\n */\r\nexport function createFromTemplate(str) {\r\n\r\n // Recursive function to resolve template\r\n function resolve(element, base = {}) {\r\n\r\n // Check key and container attribute\r\n const con = removeAttribute(element, 'data-con');\r\n const key = removeAttribute(element, 'data-key');\r\n\r\n // Check and save element\r\n if (key) {\r\n base[key] = element;\r\n }\r\n\r\n // Check all children\r\n const children = Array.from(element.children);\r\n const subtree = con ? (base[con] = {}) : base;\r\n for (let child of children) {\r\n\r\n // Check if element should be saved as array\r\n const arr = removeAttribute(child, 'data-arr');\r\n if (arr) {\r\n\r\n // Check if there is already an array and add element\r\n (subtree[arr] || (subtree[arr] = [])).push(child);\r\n } else {\r\n resolve(child, subtree);\r\n }\r\n }\r\n\r\n return base;\r\n }\r\n\r\n return resolve(createElementFromString(str));\r\n}\r\n\r\n/**\r\n * Polyfill for safari & firefox for the eventPath event property.\r\n * @param evt The event object.\r\n * @return [String] event path.\r\n */\r\nexport function eventPath(evt) {\r\n let path = evt.path || (evt.composedPath && evt.composedPath());\r\n if (path) return path;\r\n\r\n let el = evt.target.parentElement;\r\n path = [evt.target, el];\r\n while (el = el.parentElement) path.push(el);\r\n\r\n path.push(document, window);\r\n return path;\r\n}\r\n\r\n/**\r\n * Creates the ability to change numbers in an input field with the scroll-wheel.\r\n * @param el\r\n * @param negative\r\n */\r\nexport function adjustableInputNumbers(el, negative = true) {\r\n\r\n // Check if a char represents a number\r\n const isNumChar = c => (c >= '0' && c <= '9') || c === '-' || c === '.';\r\n\r\n function handleScroll(e) {\r\n const val = el.value;\r\n const off = el.selectionStart;\r\n let numStart = off;\r\n let num = ''; // Will be the number as string\r\n\r\n // Look back\r\n for (let i = off - 1; i > 0 && isNumChar(val[i]); i--) {\r\n num = val[i] + num;\r\n numStart--; // Find start of number\r\n }\r\n\r\n // Look forward\r\n for (let i = off, n = val.length; i < n && isNumChar(val[i]); i++) {\r\n num += val[i];\r\n }\r\n\r\n // Check if number is valid\r\n if (num.length > 0 && !isNaN(num) && isFinite(num)) {\r\n\r\n const mul = e.deltaY < 0 ? 1 : -1;\r\n const inc = e.ctrlKey ? mul * 5 : mul;\r\n let newNum = Number(num) + inc;\r\n\r\n if (!negative && newNum < 0) {\r\n newNum = 0;\r\n }\r\n\r\n const newStr = val.substr(0, numStart) + newNum + val.substring(numStart + num.length, val.length);\r\n const curPos = numStart + String(newNum).length;\r\n\r\n // Update value and set cursor\r\n el.value = newStr;\r\n el.focus();\r\n el.setSelectionRange(curPos, curPos);\r\n }\r\n\r\n // Prevent default\r\n e.preventDefault();\r\n\r\n // Trigger input event\r\n el.dispatchEvent(new Event('input'));\r\n }\r\n\r\n // Bind events\r\n on(el, 'focus', () => on(window, 'wheel', handleScroll));\r\n on(el, 'blur', () => off(window, 'wheel', handleScroll));\r\n}","// Shorthands\r\nconst min = Math.min,\r\n max = Math.max;\r\n\r\n/**\r\n * Convert HSV spectrum to RGB.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} Array with rgb values.\r\n */\r\nexport function hsvToRgb(h, s, v) {\r\n h = (h / 360) * 6;\r\n s /= 100;\r\n v /= 100;\r\n\r\n let i = Math.floor(h);\r\n\r\n let f = h - i;\r\n let p = v * (1 - s);\r\n let q = v * (1 - f * s);\r\n let t = v * (1 - (1 - f) * s);\r\n\r\n let mod = i % 6;\r\n let r = [v, q, p, p, t, v][mod];\r\n let g = [t, v, v, q, p, p][mod];\r\n let b = [p, p, t, v, v, q][mod];\r\n\r\n return [\r\n r * 255,\r\n g * 255,\r\n b * 255\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to Hex.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {string[]} Hex values\r\n */\r\nexport function hsvToHex(h, s, v) {\r\n return hsvToRgb(h, s, v).map(v => Math.round(v).toString(16).padStart(2, '0'));\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to CMYK.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} CMYK values\r\n */\r\nexport function hsvToCmyk(h, s, v) {\r\n const rgb = hsvToRgb(h, s, v);\r\n const r = rgb[0] / 255;\r\n const g = rgb[1] / 255;\r\n const b = rgb[2] / 255;\r\n\r\n let k, c, m, y;\r\n\r\n k = min(1 - r, 1 - g, 1 - b);\r\n\r\n c = k === 1 ? 0 : (1 - r - k) / (1 - k);\r\n m = k === 1 ? 0 : (1 - g - k) / (1 - k);\r\n y = k === 1 ? 0 : (1 - b - k) / (1 - k);\r\n\r\n return [\r\n c * 100,\r\n m * 100,\r\n y * 100,\r\n k * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to HSL.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} HSL values\r\n */\r\nexport function hsvToHsl(h, s, v) {\r\n s /= 100, v /= 100;\r\n\r\n let l = (2 - s) * v / 2;\r\n\r\n if (l !== 0) {\r\n if (l === 1) {\r\n s = 0;\r\n } else if (l < 0.5) {\r\n s = s * v / (l * 2);\r\n } else {\r\n s = s * v / (2 - l * 2);\r\n }\r\n }\r\n\r\n return [\r\n h,\r\n s * 100,\r\n l * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert RGB to HSV.\r\n * @param r Red\r\n * @param g Green\r\n * @param b Blue\r\n * @return {number[]} HSV values.\r\n */\r\nfunction rgbToHsv(r, g, b) {\r\n r /= 255, g /= 255, b /= 255;\r\n\r\n let h, s, v;\r\n const minVal = min(r, g, b);\r\n const maxVal = max(r, g, b);\r\n const delta = maxVal - minVal;\r\n\r\n v = maxVal;\r\n if (delta === 0) {\r\n h = s = 0;\r\n } else {\r\n s = delta / maxVal;\r\n let dr = (((maxVal - r) / 6) + (delta / 2)) / delta;\r\n let dg = (((maxVal - g) / 6) + (delta / 2)) / delta;\r\n let db = (((maxVal - b) / 6) + (delta / 2)) / delta;\r\n\r\n if (r === maxVal) {\r\n h = db - dg;\r\n } else if (g === maxVal) {\r\n h = (1 / 3) + dr - db;\r\n } else if (b === maxVal) {\r\n h = (2 / 3) + dg - dr;\r\n }\r\n\r\n if (h < 0) {\r\n h += 1;\r\n } else if (h > 1) {\r\n h -= 1;\r\n }\r\n }\r\n\r\n return [\r\n h * 360,\r\n s * 100,\r\n v * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert CMYK to HSV.\r\n * @param c Cyan\r\n * @param m Magenta\r\n * @param y Yellow\r\n * @param k Key (Black)\r\n * @return {number[]} HSV values.\r\n */\r\nfunction cmykToHsv(c, m, y, k) {\r\n c /= 100, m /= 100, y /= 100, k /= 100;\r\n\r\n const r = (1 - min(1, c * (1 - k) + k)) * 255;\r\n const g = (1 - min(1, m * (1 - k) + k)) * 255;\r\n const b = (1 - min(1, y * (1 - k) + k)) * 255;\r\n\r\n return [...rgbToHsv(r, g, b)];\r\n}\r\n\r\n/**\r\n * Convert HSL to HSV.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param l Lightness\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hslToHsv(h, s, l) {\r\n s /= 100, l /= 100;\r\n s *= l < 0.5 ? l : 1 - l;\r\n\r\n let ns = (2 * s / (l + s)) * 100;\r\n let v = (l + s) * 100;\r\n return [h, ns, v];\r\n}\r\n\r\n/**\r\n * Convert HEX to HSV.\r\n * @param hex Hexadecimal string of rgb colors, can have length 3 or 6.\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hexToHsv(hex) {\r\n return rgbToHsv(...hex.match(/.{2}/g).map(v => parseInt(v, 16)));\r\n}\r\n\r\n/**\r\n * Try's to parse a string which represents a color to a HSV array.\r\n * Current supported types are cmyk, rgba, hsla and hexadecimal.\r\n * @param str\r\n * @return {*}\r\n */\r\nexport function parseToHSV(str) {\r\n\r\n // Regular expressions to match different types of color represention\r\n const regex = {\r\n cmyk: /^cmyk[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)/i,\r\n rgba: /^(rgb|rgba)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsla: /^(hsl|hsla)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsva: /^(hsv|hsva)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hex: /^#?(([\\dA-Fa-f]{3,4})|([\\dA-Fa-f]{6})|([\\dA-Fa-f]{8}))$/i\r\n };\r\n\r\n /**\r\n * Takes an Array of any type, convert strings which represents\r\n * a number to a number an anything else to undefined.\r\n * @param array\r\n * @return {*}\r\n */\r\n const numarize = array => array.map(v => /^(|\\d+)\\.\\d+|\\d+$/.test(v) ? Number(v) : undefined);\r\n\r\n let match;\r\n for (let type in regex) {\r\n\r\n // Check if current scheme passed\r\n if (!(match = regex[type].exec(str)))\r\n continue;\r\n\r\n // Try to convert\r\n switch (type) {\r\n case 'cmyk': {\r\n let [, c, m, y, k] = numarize(match);\r\n\r\n if (c > 100 || m > 100 || y > 100 || k > 100)\r\n break;\r\n\r\n return {values: [...cmykToHsv(c, m, y, k), 1], type};\r\n }\r\n case 'rgba': {\r\n let [, , r, g, b, a = 1] = numarize(match);\r\n\r\n if (r > 255 || g > 255 || b > 255 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...rgbToHsv(r, g, b), a], type};\r\n }\r\n case 'hex': {\r\n const splitAt = (s, i) => [s.substring(0, i), s.substring(i, s.length)];\r\n let [, hex] = match;\r\n\r\n // Fill up opacity if not declared\r\n if (hex.length === 3) {\r\n hex += 'F';\r\n } else if (hex.length === 6) {\r\n hex += 'FF';\r\n }\r\n\r\n let alpha;\r\n if (hex.length === 4) {\r\n [hex, alpha] = splitAt(hex, 3).map(v => v + v);\r\n } else if (hex.length === 8) {\r\n [hex, alpha] = splitAt(hex, 6);\r\n }\r\n\r\n // Convert 0 - 255 to 0 - 1 for opacity\r\n alpha = parseInt(alpha, 16) / 255;\r\n return {values: [...hexToHsv(hex), alpha], type};\r\n }\r\n case 'hsla': {\r\n let [, , h, s, l, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || l > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...hslToHsv(h, s, l), a], type};\r\n }\r\n case 'hsva': {\r\n let [, , h, s, v, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || v > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [h, s, v, a], type};\r\n }\r\n }\r\n }\r\n\r\n return {values: null, type: null};\r\n}","import * as Color from './color';\r\n\r\n/**\r\n * Simple class which holds the properties\r\n * of the color represention model hsla (hue saturation lightness alpha)\r\n */\r\nexport function HSVaColor(h = 0, s = 0, v = 0, a = 1) {\r\n\r\n const ceil = Math.ceil;\r\n const that = {\r\n h, s, v, a,\r\n\r\n toHSVA() {\r\n const hsv = [that.h, that.s, that.v];\r\n const rhsv = hsv.map(ceil);\r\n\r\n hsv.toString = () => `hsva(${rhsv[0]}, ${rhsv[1]}%, ${rhsv[2]}%, ${that.a.toFixed(1)})`;\r\n return hsv;\r\n },\r\n\r\n toHSLA() {\r\n const hsl = Color.hsvToHsl(that.h, that.s, that.v);\r\n const rhsl = hsl.map(ceil);\r\n\r\n hsl.toString = () => `hsla(${rhsl[0]}, ${rhsl[1]}%, ${rhsl[2]}%, ${that.a.toFixed(1)})`;\r\n return hsl;\r\n },\r\n\r\n toRGBA() {\r\n const rgb = Color.hsvToRgb(that.h, that.s, that.v);\r\n const rrgb = rgb.map(ceil);\r\n\r\n rgb.toString = () => `rgba(${rrgb[0]}, ${rrgb[1]}, ${rrgb[2]}, ${that.a.toFixed(1)})`;\r\n return rgb;\r\n },\r\n\r\n toCMYK() {\r\n const cmyk = Color.hsvToCmyk(that.h, that.s, that.v);\r\n const rcmyk = cmyk.map(ceil);\r\n\r\n cmyk.toString = () => `cmyk(${rcmyk[0]}%, ${rcmyk[1]}%, ${rcmyk[2]}%, ${rcmyk[3]}%)`;\r\n return cmyk;\r\n },\r\n\r\n toHEX() {\r\n const hex = Color.hsvToHex(...[that.h, that.s, that.v]);\r\n\r\n hex.toString = () => {\r\n\r\n // Check if alpha channel make sense, convert it to 255 number space, convert\r\n // to hex and pad it with zeros if needet.\r\n const alpha = that.a >= 1 ? '' : Number((that.a * 255).toFixed(0))\r\n .toString(16)\r\n .toUpperCase()\r\n .padStart(2, '0');\r\n\r\n return `#${hex.join('').toUpperCase() + alpha}`;\r\n };\r\n\r\n return hex;\r\n },\r\n\r\n clone() {\r\n return HSVaColor(that.h, that.s, that.v, that.a);\r\n }\r\n };\r\n\r\n return that;\r\n}","import * as _ from './../lib/utils';\r\n\r\nexport default function Moveable(opt) {\r\n\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n lockX: false,\r\n lockY: false,\r\n onchange: () => 0\r\n }, opt),\r\n\r\n _tapstart(evt) {\r\n _.on(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.on(document, ['mousemove', 'touchmove'], that._tapmove);\r\n\r\n // Prevent default touch event\r\n evt.preventDefault();\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Trigger\r\n that._tapmove(evt);\r\n },\r\n\r\n _tapmove(evt) {\r\n const {options, cache} = that;\r\n const {element} = options;\r\n const b = that.wrapperRect;\r\n\r\n let x = 0, y = 0;\r\n if (evt) {\r\n const touch = evt && evt.touches && evt.touches[0];\r\n x = evt ? (touch || evt).clientX : 0;\r\n y = evt ? (touch || evt).clientY : 0;\r\n\r\n // Reset to bounds\r\n if (x < b.left) x = b.left;\r\n else if (x > b.left + b.width) x = b.left + b.width;\r\n if (y < b.top) y = b.top;\r\n else if (y > b.top + b.height) y = b.top + b.height;\r\n\r\n // Normalize\r\n x -= b.left;\r\n y -= b.top;\r\n } else if (cache) {\r\n x = cache.x;\r\n y = cache.y;\r\n }\r\n\r\n if (!options.lockX)\r\n element.style.left = (x - element.offsetWidth / 2) + 'px';\r\n\r\n if (!options.lockY)\r\n element.style.top = (y - element.offsetHeight / 2) + 'px';\r\n\r\n that.cache = {x, y};\r\n options.onchange(x, y);\r\n },\r\n\r\n _tapstop() {\r\n _.off(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.off(document, ['mousemove', 'touchmove'], that._tapmove);\r\n },\r\n\r\n trigger() {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove();\r\n },\r\n\r\n update(x = 0, y = 0) {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove({\r\n clientX: that.wrapperRect.left + x,\r\n clientY: that.wrapperRect.top + y\r\n });\r\n },\r\n\r\n destroy() {\r\n const {options, _tapstart} = that;\r\n _.off([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.off([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n }\r\n };\r\n\r\n // Instance var\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Initilize\r\n const {options, _tapstart} = that;\r\n _.on([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.on([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n\r\n return that;\r\n}","// Import styles\r\nimport '../scss/pickr.scss';\r\n\r\n// Import utils\r\nimport * as _ from './lib/utils';\r\nimport * as Color from './lib/color';\r\n\r\n// Import classes\r\nimport {HSVaColor} from './lib/hsvacolor';\r\nimport Moveable from './helper/moveable';\r\nimport Selectable from './helper/selectable';\r\n\r\nclass Pickr {\r\n\r\n constructor(opt) {\r\n\r\n // Assign default values\r\n this.options = Object.assign({\r\n useAsButton: false,\r\n disabled: false,\r\n comparison: true,\r\n\r\n components: {interaction: {}},\r\n strings: {},\r\n\r\n default: 'fff',\r\n defaultRepresentation: 'HEX',\r\n position: 'middle',\r\n adjustableNumbers: true,\r\n showAlways: false,\r\n parent: undefined,\r\n\r\n closeWithKey: 'Escape',\r\n onChange: () => 0,\r\n onSave: () => 0,\r\n onClear: () => 0\r\n }, opt);\r\n\r\n // Check interaction section\r\n if (!this.options.components.interaction) {\r\n this.options.components.interaction = {};\r\n }\r\n\r\n // Will be used to prevent specific actions during initilization\r\n this._initializingActive = true;\r\n\r\n // Replace element with color picker\r\n this._recalc = true;\r\n\r\n // Current and last color for comparison\r\n this._color = new HSVaColor();\r\n this._lastColor = new HSVaColor();\r\n\r\n // Initialize picker\r\n this._preBuild();\r\n this._buildComponents();\r\n this._bindEvents();\r\n\r\n // Initialize color\r\n this.setColor(this.options.default);\r\n\r\n // Initialize color _epresentation\r\n this._representation = this.options.defaultRepresentation;\r\n this.setColorRepresentation(this._representation);\r\n\r\n // Initilization is finish, pickr is visible and ready to use\r\n this._initializingActive = false;\r\n\r\n // Finalize build\r\n this._finalBuild();\r\n this._rePositioningPicker();\r\n }\r\n\r\n // Does only the absolutly basic thing to initialize the components\r\n _preBuild() {\r\n const opt = this.options;\r\n\r\n // Check if element is selector\r\n if (typeof opt.el === 'string') {\r\n opt.el = document.querySelector(opt.el);\r\n }\r\n\r\n // Create element and append it to body to\r\n // prevent initialization errors\r\n this._root = create(opt);\r\n\r\n // Check if a custom button is used\r\n if (opt.useAsButton) {\r\n\r\n // Check if the user has an alternative location defined, used body as fallback\r\n if (!opt.parent) {\r\n opt.parent = 'body';\r\n }\r\n\r\n this._root.button = opt.el; // Replace button with customized button\r\n }\r\n\r\n document.body.appendChild(this._root.root);\r\n }\r\n\r\n _finalBuild() {\r\n const opt = this.options;\r\n const root = this._root;\r\n\r\n // Remove from body\r\n document.body.removeChild(root.root);\r\n\r\n // Check parent option\r\n if (opt.parent) {\r\n\r\n // Check if element is selector\r\n if (typeof opt.parent === 'string') {\r\n opt.parent = document.querySelector(opt.parent);\r\n }\r\n\r\n opt.parent.appendChild(root.app);\r\n }\r\n\r\n // Don't replace the the element if a custom button is used\r\n if (!opt.useAsButton) {\r\n\r\n // Replace element with actual color-picker\r\n opt.el.parentElement.replaceChild(root.root, opt.el);\r\n }\r\n\r\n // Call disable to also add the disabled class\r\n if (opt.disabled) {\r\n this.disable();\r\n }\r\n\r\n // Check if color comparison is disabled, if yes - remove transitions so everything keeps smoothly\r\n if (!opt.comparison) {\r\n root.button.style.transition = 'none';\r\n if (!opt.useAsButton) {\r\n root.preview.lastColor.style.transition = 'none';\r\n }\r\n }\r\n\r\n // Check showAlways option\r\n opt.showAlways ? root.app.classList.add('visible') : this.hide();\r\n }\r\n\r\n _buildComponents() {\r\n\r\n // Instance reference\r\n const inst = this;\r\n const comp = this.options.components;\r\n\r\n const components = {\r\n\r\n palette: Moveable({\r\n element: inst._root.palette.picker,\r\n wrapper: inst._root.palette.palette,\r\n\r\n onchange(x, y) {\r\n const {_color, _root, options} = inst;\r\n\r\n // Calculate saturation based on the position\r\n _color.s = (x / this.wrapper.offsetWidth) * 100;\r\n\r\n // Calculate the value\r\n _color.v = 100 - (y / this.wrapper.offsetHeight) * 100;\r\n\r\n // Prevent falling under zero\r\n _color.v < 0 ? _color.v = 0 : 0;\r\n\r\n // Set picker and gradient color\r\n const cssRGBaString = _color.toRGBA().toString();\r\n this.element.style.background = cssRGBaString;\r\n this.wrapper.style.background = `\r\n linear-gradient(to top, rgba(0, 0, 0, ${_color.a}), transparent), \r\n linear-gradient(to left, hsla(${_color.h}, 100%, 50%, ${_color.a}), rgba(255, 255, 255, ${_color.a}))\r\n `;\r\n\r\n // Check if color is locked\r\n if (!options.comparison) {\r\n _root.button.style.background = cssRGBaString;\r\n\r\n if (!options.useAsButton) {\r\n _root.preview.lastColor.style.background = cssRGBaString;\r\n }\r\n }\r\n\r\n // Change current color\r\n _root.preview.currentColor.style.background = cssRGBaString;\r\n\r\n // Update the input field only if the user is currently not typing\r\n if (inst._recalc) {\r\n inst._updateOutput();\r\n }\r\n\r\n // If the user changes the color, remove the cleared icon\r\n _root.button.classList.remove('clear');\r\n }\r\n }),\r\n\r\n hue: Moveable({\r\n lockX: true,\r\n element: inst._root.hue.picker,\r\n wrapper: inst._root.hue.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.hue) return;\r\n\r\n // Calculate hue\r\n inst._color.h = (y / this.wrapper.offsetHeight) * 360;\r\n\r\n // Update color\r\n this.element.style.backgroundColor = `hsl(${inst._color.h}, 100%, 50%)`;\r\n components.palette.trigger();\r\n }\r\n }),\r\n\r\n opacity: Moveable({\r\n lockX: true,\r\n element: inst._root.opacity.picker,\r\n wrapper: inst._root.opacity.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.opacity) return;\r\n\r\n // Calculate opacity\r\n inst._color.a = Math.round(((y / this.wrapper.offsetHeight)) * 1e2) / 100;\r\n\r\n // Update color\r\n this.element.style.background = `rgba(0, 0, 0, ${inst._color.a})`;\r\n inst.components.palette.trigger();\r\n }\r\n }),\r\n\r\n selectable: Selectable({\r\n elements: inst._root.interaction.options,\r\n className: 'active',\r\n onchange(e) {\r\n inst._representation = e.target.getAttribute('data-type').toUpperCase();\r\n inst._updateOutput();\r\n }\r\n })\r\n };\r\n\r\n this.components = components;\r\n }\r\n\r\n _bindEvents() {\r\n const {_root, options} = this;\r\n\r\n const eventBindings = [\r\n\r\n // Clear color\r\n _.on(_root.interaction.clear, 'click', () => this._clearColor()),\r\n\r\n // Select last color on click\r\n _.on(_root.preview.lastColor, 'click', () => this.setHSVA(...this._lastColor.toHSVA())),\r\n\r\n // Save color\r\n _.on(_root.interaction.save, 'click', () => {\r\n !this._saveColor() && !options.showAlways && this.hide();\r\n }),\r\n\r\n // Detect user input and disable auto-recalculation\r\n _.on(_root.interaction.result, ['keyup', 'input'], e => {\r\n this._recalc = false;\r\n\r\n // Fire listener if initialization is finish and changed color was valid\r\n if (this.setColor(e.target.value, true) && !this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n\r\n e.stopImmediatePropagation();\r\n }),\r\n\r\n // Cancel input detection on color change\r\n _.on([\r\n _root.palette.palette,\r\n _root.palette.picker,\r\n _root.hue.slider,\r\n _root.hue.picker,\r\n _root.opacity.slider,\r\n _root.opacity.picker\r\n ], ['mousedown', 'touchstart'], () => this._recalc = true),\r\n\r\n // Repositioning on resize\r\n _.on(window, 'resize', () => this._rePositioningPicker)\r\n ];\r\n\r\n // Provide hiding / showing abilities only if showAlways is false\r\n if (!options.showAlways) {\r\n\r\n // Save and hide / show picker\r\n eventBindings.push(_.on(_root.button, 'click', () => this.isOpen() ? this.hide() : this.show()));\r\n\r\n // Close with escape key\r\n const ck = options.closeWithKey;\r\n eventBindings.push(_.on(document, 'keyup', e => this.isOpen() && (e.key === ck || e.code === ck) && this.hide()));\r\n\r\n // Cancel selecting if the user taps behind the color picker\r\n eventBindings.push(_.on(document, ['touchstart', 'mousedown'], e => {\r\n if (this.isOpen() && !_.eventPath(e).some(el => el === _root.app || el === _root.button)) {\r\n this.hide();\r\n }\r\n }, {capture: true}));\r\n }\r\n\r\n // Make input adjustable if enabled\r\n if (options.adjustableNumbers) {\r\n _.adjustableInputNumbers(_root.interaction.result, false);\r\n }\r\n\r\n // Save bindings\r\n this._eventBindings = eventBindings;\r\n }\r\n\r\n _rePositioningPicker() {\r\n const root = this._root;\r\n const app = this._root.app;\r\n\r\n // Check if user has defined a parent\r\n if (this.options.parent) {\r\n const relative = root.button.getBoundingClientRect();\r\n app.style.position = 'fixed';\r\n app.style.marginLeft = `${relative.left}px`;\r\n app.style.marginTop = `${relative.top}px`;\r\n }\r\n\r\n const bb = root.button.getBoundingClientRect();\r\n const ab = app.getBoundingClientRect();\r\n const as = app.style;\r\n\r\n // Check if picker is cuttet of from the top & bottom\r\n if (ab.bottom > window.innerHeight) {\r\n as.top = `${-(ab.height) - 5}px`;\r\n } else if (bb.bottom + ab.height < window.innerHeight) {\r\n as.top = `${bb.height + 5}px`;\r\n }\r\n\r\n // Positioning picker on the x-axis\r\n const pos = {\r\n left: -(ab.width) + bb.width,\r\n middle: -(ab.width / 2) + bb.width / 2,\r\n right: 0\r\n };\r\n\r\n const cl = parseInt(getComputedStyle(app).left, 10);\r\n let newLeft = pos[this.options.position];\r\n const leftClip = (ab.left - cl) + newLeft;\r\n const rightClip = (ab.left - cl) + newLeft + ab.width;\r\n\r\n /**\r\n * First check if position is left or right but\r\n * pickr-app cannot set to left AND right because it would\r\n * be clipped by the browser width. If so, wrap it and position\r\n * pickr below button via the pos[middle] value.\r\n * The current selected posiotion should'nt be the middle.di\r\n */\r\n if (this.options.position !== 'middle' && (\r\n (leftClip < 0 && -leftClip < ab.width / 2) ||\r\n (rightClip > window.innerWidth && rightClip - window.innerWidth < ab.width / 2))) {\r\n newLeft = pos['middle'];\r\n\r\n /**\r\n * Even if set to middle pickr is getting clipped, so\r\n * set it to left / right.\r\n */\r\n } else if (leftClip < 0) {\r\n newLeft = pos['right'];\r\n } else if (rightClip > window.innerWidth) {\r\n newLeft = pos['left'];\r\n }\r\n\r\n as.left = `${newLeft}px`;\r\n }\r\n\r\n _updateOutput() {\r\n\r\n // Check if component is present\r\n if (this._root.interaction.type()) {\r\n\r\n this._root.interaction.result.value = (() => {\r\n\r\n // Construct function name and call if present\r\n const method = 'to' + this._root.interaction.type().getAttribute('data-type');\r\n return typeof this._color[method] === 'function' ? this._color[method]().toString() : '';\r\n })();\r\n }\r\n\r\n // Fire listener if initialization is finish\r\n if (!this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n }\r\n\r\n _saveColor() {\r\n const {preview, button} = this._root;\r\n\r\n // Change preview and current color\r\n const cssRGBaString = this._color.toRGBA().toString();\r\n preview.lastColor.style.background = cssRGBaString;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!this.options.useAsButton) {\r\n button.style.background = cssRGBaString;\r\n }\r\n\r\n // User changed the color so remove the clear clas\r\n button.classList.remove('clear');\r\n\r\n // Save last color\r\n this._lastColor = this._color.clone();\r\n\r\n // Fire listener\r\n if (!this._initializingActive) {\r\n this.options.onSave(this._color, this);\r\n }\r\n }\r\n\r\n _clearColor() {\r\n const {_root, options} = this;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!options.useAsButton) {\r\n _root.button.style.background = 'rgba(255, 255, 255, 0.4)';\r\n }\r\n\r\n _root.button.classList.add('clear');\r\n\r\n if (!options.showAlways) {\r\n this.hide();\r\n }\r\n\r\n // Fire listener\r\n options.onSave(null, this);\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys\r\n */\r\n destroy() {\r\n this._eventBindings.forEach(args => _.off(...args));\r\n Object.keys(this.components).forEach(key => this.components[key].destroy());\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys and removes\r\n * the pickr element.\r\n */\r\n destroyAndRemove() {\r\n this.destroy();\r\n\r\n // Remove element\r\n const root = this._root.root;\r\n root.parentElement.removeChild(root);\r\n }\r\n\r\n /**\r\n * Hides the color-picker ui.\r\n */\r\n hide() {\r\n this._root.app.classList.remove('visible');\r\n return this;\r\n }\r\n\r\n /**\r\n * Shows the color-picker ui.\r\n */\r\n show() {\r\n if (this.options.disabled) return;\r\n this._root.app.classList.add('visible');\r\n this._rePositioningPicker();\r\n return this;\r\n }\r\n\r\n /**\r\n * @return {boolean} If the color picker is currently open\r\n */\r\n isOpen() {\r\n return this._root.app.classList.contains('visible');\r\n }\r\n\r\n /**\r\n * Set a specific color.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @param a Alpha channel (0 - 1)\r\n * @param silent If the button should not change the color\r\n * @return true if the color has been accepted\r\n */\r\n setHSVA(h = 360, s = 0, v = 0, a = 1, silent = false) {\r\n\r\n // Deactivate color calculation\r\n const recalc = this._recalc; // Save state\r\n this._recalc = false;\r\n\r\n // Validate input\r\n if (h < 0 || h > 360 || s < 0 || s > 100 || v < 0 || v > 100 || a < 0 || a > 1) {\r\n return false;\r\n }\r\n\r\n // Short names\r\n const {hue, opacity, palette} = this.components;\r\n\r\n // Calculate y position of hue slider\r\n const hueWrapper = hue.options.wrapper;\r\n const hueY = hueWrapper.offsetHeight * (h / 360);\r\n hue.update(0, hueY);\r\n\r\n // Calculate y position of opacity slider\r\n const opacityWrapper = opacity.options.wrapper;\r\n const opacityY = opacityWrapper.offsetHeight * a;\r\n opacity.update(0, opacityY);\r\n\r\n // Calculate y and x position of color palette\r\n const pickerWrapper = palette.options.wrapper;\r\n const pickerX = pickerWrapper.offsetWidth * (s / 100);\r\n const pickerY = pickerWrapper.offsetHeight * (1 - (v / 100));\r\n palette.update(pickerX, pickerY);\r\n\r\n // Override current color and re-active color calculation\r\n this._color = new HSVaColor(h, s, v, a);\r\n this._recalc = recalc; // Restore old state\r\n\r\n // Update output if recalculation is enabled\r\n if (this._recalc) {\r\n this._updateOutput();\r\n }\r\n\r\n // Check if call is silent\r\n if (!silent) {\r\n this._saveColor();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Tries to parse a string which represents a color.\r\n * Examples: #fff\r\n * rgb 10 10 200\r\n * hsva 10 20 5 0.5\r\n * @param string\r\n * @param silent\r\n */\r\n setColor(string, silent = false) {\r\n\r\n // Check if null\r\n if (string === null) {\r\n this._clearColor();\r\n return true;\r\n }\r\n\r\n const {values, type} = Color.parseToHSV(string);\r\n\r\n // Check if color is ok\r\n if (values) {\r\n\r\n // Change selected color format\r\n const utype = type.toUpperCase();\r\n const {options} = this._root.interaction;\r\n const target = options.find(el => el.getAttribute('data-type') === utype);\r\n\r\n // Auto select only if not hidden\r\n if (!target.hidden) {\r\n for (const el of options) {\r\n el.classList[el === target ? 'add' : 'remove']('active');\r\n }\r\n }\r\n\r\n return this.setHSVA(...values, silent);\r\n }\r\n }\r\n\r\n /**\r\n * Changes the color _representation.\r\n * Allowed values are HEX, RGBA, HSVA, HSLA and CMYK\r\n * @param type\r\n * @returns {boolean} if the selected type was valid.\r\n */\r\n setColorRepresentation(type) {\r\n\r\n // Force uppercase to allow a case-sensitiv comparison\r\n type = type.toUpperCase();\r\n\r\n // Find button with given type and trigger click event\r\n return !!this._root.interaction.options.find(v => v.getAttribute('data-type') === type && !v.click());\r\n }\r\n\r\n /**\r\n * Returns the current color representaion. See setColorRepresentation\r\n * @returns {*}\r\n */\r\n getColorRepresentation() {\r\n return this._representation;\r\n }\r\n\r\n /**\r\n * @returns HSVaColor Current HSVaColor object.\r\n */\r\n getColor() {\r\n return this._color;\r\n }\r\n\r\n /**\r\n * @returns The root HTMLElement with all his components.\r\n */\r\n getRoot() {\r\n return this._root;\r\n }\r\n\r\n /**\r\n * Disable pickr\r\n */\r\n disable() {\r\n this.hide();\r\n this.options.disabled = true;\r\n this._root.button.classList.add('disabled');\r\n return this;\r\n }\r\n\r\n /**\r\n * Enable pickr\r\n */\r\n enable() {\r\n this.options.disabled = false;\r\n this._root.button.classList.remove('disabled');\r\n return this;\r\n }\r\n}\r\n\r\nfunction create(options) {\r\n const {components, strings, useAsButton} = options;\r\n const hidden = con => con ? '' : 'style=\"display:none\" hidden';\r\n\r\n const root = _.createFromTemplate(`\r\n
\r\n \r\n ${useAsButton ? '' : '
'}\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n
\r\n
\r\n
\r\n `);\r\n\r\n const int = root.interaction;\r\n\r\n // Select option which is not hidden\r\n int.options.find(o => !o.hidden && !o.classList.add('active'));\r\n\r\n // Create method to find currenlty active option\r\n int.type = () => int.options.find(e => e.classList.contains('active'));\r\n return root;\r\n}\r\n\r\n// Static methods\r\nPickr.utils = {\r\n once: _.once,\r\n on: _.on,\r\n off: _.off,\r\n eventPath: _.eventPath,\r\n createElementFromString: _.createElementFromString,\r\n adjustableInputNumbers: _.adjustableInputNumbers,\r\n removeAttribute: _.removeAttribute,\r\n createFromTemplate: _.createFromTemplate\r\n};\r\n\r\n// Create instance via method\r\nPickr.create = (options) => new Pickr(options);\r\n\r\n// Export\r\nPickr.version = '0.3.2';\r\nexport default Pickr;","import * as _ from './../lib/utils';\r\n\r\nexport default function Selectable(opt = {}) {\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n onchange: () => 0,\r\n className: '',\r\n elements: []\r\n }, opt),\r\n\r\n _ontap(evt) {\r\n const opt = that.options;\r\n opt.elements.forEach(e =>\r\n e.classList[evt.target === e ? 'add' : 'remove'](opt.className)\r\n );\r\n\r\n opt.onchange(evt);\r\n },\r\n\r\n destroy() {\r\n _.off(that.options.elements, 'click', this._ontap);\r\n }\r\n };\r\n\r\n _.on(that.options.elements, 'click', that._ontap);\r\n return that;\r\n}"],"sourceRoot":""} \ No newline at end of file diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index 209df015..e76e1b59 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -64,7 +64,7 @@ public async Task DisplayBookDescription() private Book CreateDemoBook() => new Book { - CoverPhotoUrl = "/Lombiq.TrainingDemo/HarryPotter.jpg", + CoverPhotoUrl = "/Lombiq.TrainingDemo/Images/HarryPotter.jpg", Title = "Harry Potter and The Sorcerer's Stone", Author = "J.K. (Joanne) Rowling", Description = "Harry hasn't had a birthday party in eleven years - but all that is about to change when a mysterious " + diff --git a/Controllers/PersonListController.cs b/Controllers/PersonListController.cs index 4e3db47d..75b761e0 100644 --- a/Controllers/PersonListController.cs +++ b/Controllers/PersonListController.cs @@ -1,13 +1,10 @@ -using System; -using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading.Tasks; using Lombiq.TrainingDemo.Indexes; +using Lombiq.TrainingDemo.Models; using Microsoft.AspNetCore.Mvc; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Display; -using OrchardCore.ContentManagement.Records; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.Modules; using YesSql; @@ -19,16 +16,19 @@ public class PersonListController : Controller, IUpdateModel private readonly ISession _session; private readonly IClock _clock; private readonly IContentItemDisplayManager _contentItemDisplayManager; + private readonly IContentManager _contentManager; public PersonListController( ISession session, IClock clock, - IContentItemDisplayManager contentItemDisplayManager) + IContentItemDisplayManager contentItemDisplayManager, + IContentManager contentManager) { _session = session; _clock = clock; _contentItemDisplayManager = contentItemDisplayManager; + _contentManager = contentManager; } @@ -39,11 +39,21 @@ public async Task OlderThan30() .Query(index => index.BirthDateUtc < thresholdDate) .ListAsync(); - var shapes = people - .Select(async person => await _contentItemDisplayManager.BuildDisplayAsync(person, this, "Summary")) - .Select(task => task.Result); + var shapes = await Task.WhenAll(people.Select(async person => + await _contentItemDisplayManager.BuildDisplayAsync(person, this, "Summary"))); + + // Testing 1..2..3... + + var person1 = await _contentManager.NewAsync("Person"); + var personPart1 = person1.As(); + personPart1.Name = "Person 1"; + + var person2 = await _contentManager.NewAsync("Person"); + var personPart2 = person2.As(); + personPart2.Name = "Person 2"; + return View(shapes); } } -} +} \ No newline at end of file diff --git a/Gulpfile.js b/Gulpfile.js new file mode 100644 index 00000000..4c61fb39 --- /dev/null +++ b/Gulpfile.js @@ -0,0 +1,21 @@ +const gulp = require("gulp"); + +const imageFiles = "Assets/Images/**/*"; +const imageFilesDestination = "wwwroot/Images"; + +const pickrFiles = "node_modules/pickr-widget/dist/*"; +const pickrFilesDestination = "wwwroot/pickr"; + +gulp.task("images", function () { + return gulp + .src(imageFiles) + .pipe(gulp.dest(imageFilesDestination)); +}); + +gulp.task("pickr", function () { + return gulp + .src(pickrFiles) + .pipe(gulp.dest(pickrFilesDestination)); +}); + +gulp.task("default", ["images", "pickr"]); \ No newline at end of file diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index 435f960e..ba4b59f7 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -1,27 +1,9 @@ - + netstandard2.0 - - - - - - - - - Never - - - Never - - - Never - - - @@ -38,4 +20,9 @@ + + + + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..901fb54f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2269 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "dev": true + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.3", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + } + }, + "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.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.4" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "parse-node-version": "1.0.0", + "time-stamp": "1.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.3.3" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "http://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.1" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "http://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "1.0.1" + } + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "http://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.6" + } + }, + "gulp": { + "version": "3.9.1", + "resolved": "http://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.3", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.5", + "vinyl": "0.5.3" + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.1" + } + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.3.3", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "1.0.0", + "is-windows": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "dev": true, + "requires": { + "is-unc-path": "1.0.0" + } + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "3.0.2", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.8.1" + } + }, + "lodash": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.13", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" + } + }, + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "make-iterator": "1.0.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + } + }, + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.1" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-node-version": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", + "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "pickr-widget": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/pickr-widget/-/pickr-widget-0.3.2.tgz", + "integrity": "sha512-ysOy+fJFOFuU+/vYQfkDqBRY9s4msUtGS3nDFFycPMHd3BEqG6TP0IyuiMfGbMqWcK78xR5CBYmX0Gs6IRE4bg==" + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.8.1" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, + "semver": { + "version": "4.3.6", + "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.2", + "use": "3.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "2.1.2", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "stream-consume": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "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 + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "2.3.6", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + } + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..00f52f94 --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "private": true, + "dependencies": { + "pickr-widget": "^0.3.2" + }, + "devDependencies": { + "gulp": "^3.9.1" + } +} diff --git a/wwwroot/pickr/pickr.min.css b/wwwroot/pickr/pickr.min.css deleted file mode 100644 index 5c8c5a6e..00000000 --- a/wwwroot/pickr/pickr.min.css +++ /dev/null @@ -1 +0,0 @@ -.pickr{position:relative;overflow:visible;z-index:1}.pickr *{box-sizing:border-box}.pickr .pcr-button{position:relative;height:2em;width:2em;padding:.5em;border-radius:.15em;cursor:pointer;background:transparent;transition:background-color .3s;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.pickr .pcr-button:before{background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pickr .pcr-button:after,.pickr .pcr-button:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%}.pickr .pcr-button:after{background:url('data:image/svg+xml;utf8, ') no-repeat 50%;background-size:70%;opacity:0}.pickr .pcr-button.clear:after{opacity:1}.pickr .pcr-button.disabled{cursor:not-allowed}.pcr-app{position:absolute;display:flex;flex-direction:column;z-index:10000;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;box-shadow:0 .2em 1.5em 0 rgba(0,0,0,.1),0 0 1em 0 rgba(0,0,0,.02);top:5px;height:15em;width:28em;max-width:95vw;padding:.8em;border-radius:.1em;background:#fff;opacity:0;visibility:hidden;transition:opacity .3s}.pcr-app.visible{visibility:visible;opacity:1}.pcr-app .pcr-interaction{display:flex;align-items:center;margin:1em -.2em 0}.pcr-app .pcr-interaction>*{margin:0 .2em}.pcr-app .pcr-interaction input{padding:.5em .6em;border:none;outline:none;letter-spacing:.07em;font-size:.75em;text-align:center;cursor:pointer;color:#c4c4c4;background:#f8f8f8;border-radius:.15em;transition:all .15s}.pcr-app .pcr-interaction input:hover{color:grey}.pcr-app .pcr-interaction .pcr-result{color:grey;text-align:left;flex-grow:1;min-width:1em;transition:all .2s;border-radius:.15em;background:#f8f8f8;cursor:text;padding-left:.8em}.pcr-app .pcr-interaction .pcr-result:focus{color:#4285f4}.pcr-app .pcr-interaction .pcr-result::selection{background:#4285f4;color:#fff}.pcr-app .pcr-interaction .pcr-type.active{color:#fff;background:#4285f4}.pcr-app .pcr-interaction .pcr-clear,.pcr-app .pcr-interaction .pcr-save{color:#fff;width:auto}.pcr-app .pcr-interaction .pcr-save{background:#4285f4}.pcr-app .pcr-interaction .pcr-save:hover{background:#4370f4;color:#fff}.pcr-app .pcr-interaction .pcr-clear{background:#f44250}.pcr-app .pcr-interaction .pcr-clear:hover{background:#db3d49;color:#fff}.pcr-app .pcr-selection{display:flex;justify-content:space-between;flex-grow:1}.pcr-app .pcr-selection .pcr-picker{position:absolute;height:18px;width:18px;border:2px solid #fff;border-radius:100%;user-select:none;cursor:-moz-grab;cursor:-webkit-grabbing}.pcr-app .pcr-selection .pcr-color-preview{position:relative;z-index:1;width:2em;display:flex;flex-direction:column;justify-content:space-between;margin-right:.75em}.pcr-app .pcr-selection .pcr-color-preview:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{cursor:pointer;transition:background-color .3s;border-radius:.15em .15em 0 0}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color{border-radius:0 0 .15em .15em}.pcr-app .pcr-selection .pcr-color-preview .pcr-current-color,.pcr-app .pcr-selection .pcr-color-preview .pcr-last-color{background:transparent;width:100%;height:50%}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity,.pcr-app .pcr-selection .pcr-color-palette{position:relative;user-select:none;display:flex;flex-direction:column}.pcr-app .pcr-selection .pcr-color-palette{width:100%;z-index:1}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette{height:100%;border-radius:.15em}.pcr-app .pcr-selection .pcr-color-palette .pcr-palette:before{position:absolute;content:"";top:0;left:0;width:100%;height:100%;background:url('data:image/svg+xml;utf8, ');background-size:.5em;border-radius:.15em;z-index:-1}.pcr-app .pcr-selection .pcr-color-chooser,.pcr-app .pcr-selection .pcr-color-opacity{margin-left:.75em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-picker,.pcr-app .pcr-selection .pcr-color-opacity .pcr-picker{left:50%;transform:translateX(-50%)}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider,.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{width:8px;height:100%;border-radius:50em}.pcr-app .pcr-selection .pcr-color-chooser .pcr-slider{background:linear-gradient(180deg,red,#ff0,#0f0,#0ff,#00f,#f0f,red)}.pcr-app .pcr-selection .pcr-color-opacity .pcr-slider{background:linear-gradient(180deg,transparent,#000),url('data:image/svg+xml;utf8, ');background-size:100%,50%} \ No newline at end of file diff --git a/wwwroot/pickr/pickr.min.js b/wwwroot/pickr/pickr.min.js deleted file mode 100644 index 0adc2483..00000000 --- a/wwwroot/pickr/pickr.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Pickr=e():t.Pickr=e()}(window,function(){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var r=e[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(o,r,function(e){return t[e]}.bind(null,r));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="dist/",n(n.s=1)}([function(t,e,n){},function(t,e,n){"use strict";n.r(e);var o={};n.r(o),n.d(o,"once",function(){return a}),n.d(o,"on",function(){return c}),n.d(o,"off",function(){return s}),n.d(o,"createElementFromString",function(){return l}),n.d(o,"removeAttribute",function(){return p}),n.d(o,"createFromTemplate",function(){return d}),n.d(o,"eventPath",function(){return h}),n.d(o,"adjustableInputNumbers",function(){return f});var r={};n.r(r),n.d(r,"hsvToRgb",function(){return b}),n.d(r,"hsvToHex",function(){return _}),n.d(r,"hsvToCmyk",function(){return w}),n.d(r,"hsvToHsl",function(){return k}),n.d(r,"parseToHSV",function(){return j});n(0);function i(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}var a=function(t,e,n,o){return c(t,e,function t(){n.apply(this,arguments),this.removeEventListener(e,t)},o)},c=u.bind(null,"addEventListener"),s=u.bind(null,"removeEventListener");function u(t,e,n,o){var r=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{};return e instanceof HTMLCollection||e instanceof NodeList?e=Array.from(e):Array.isArray(e)||(e=[e]),Array.isArray(n)||(n=[n]),e.forEach(function(e){return n.forEach(function(n){return e[t](n,o,function(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{},o=p(e,"data-con"),r=p(e,"data-key");r&&(n[r]=e);for(var i=Array.from(e.children),a=o?n[o]={}:n,c=0;c1&&void 0!==arguments[1])||arguments[1],n=function(t){return t>="0"&&t<="9"||"-"===t||"."===t};function o(o){for(var r=t.value,i=t.selectionStart,a=i,c="",s=i-1;s>0&&n(r[s]);s--)c=r[s]+c,a--;for(var u=i,l=r.length;u0&&!isNaN(c)&&isFinite(c)){var p=o.deltaY<0?1:-1,d=o.ctrlKey?5*p:p,h=Number(c)+d;!e&&h<0&&(h=0);var f=r.substr(0,a)+h+r.substring(a+c.length,r.length),v=a+String(h).length;t.value=f,t.focus(),t.setSelectionRange(v,v)}o.preventDefault(),t.dispatchEvent(new Event("input"))}c(t,"focus",function(){return c(window,"wheel",o)}),c(t,"blur",function(){return s(window,"wheel",o)})}function v(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var n=[],o=!0,r=!1,i=void 0;try{for(var a,c=t[Symbol.iterator]();!(o=(a=c.next()).done)&&(n.push(a.value),!e||n.length!==e);o=!0);}catch(t){r=!0,i=t}finally{try{o||null==c.return||c.return()}finally{if(r)throw i}}return n}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function y(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e1&&(o-=1)}return[360*o,100*r,100*i]}function C(t,e,n,o){return e/=100,n/=100,y(A(255*(1-g(1,(t/=100)*(1-(o/=100))+o)),255*(1-g(1,e*(1-o)+o)),255*(1-g(1,n*(1-o)+o))))}function S(t,e,n){return e/=100,[t,2*(e*=(n/=100)<.5?n:1-n)/(n+e)*100,100*(n+e)]}function O(t){return A.apply(void 0,y(t.match(/.{2}/g).map(function(t){return parseInt(t,16)})))}function j(t){var e,n={cmyk:/^cmyk[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)/i,rgba:/^(rgb|rgba)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsla:/^(hsl|hsla)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hsva:/^(hsv|hsva)[\D]+(\d+)[\D]+(\d+)[\D]+(\d+)[\D]*?([\d.]+|$)/i,hex:/^#?(([\dA-Fa-f]{3,4})|([\dA-Fa-f]{6})|([\dA-Fa-f]{8}))$/i},o=function(t){return t.map(function(t){return/^(|\d+)\.\d+|\d+$/.test(t)?Number(t):void 0})};for(var r in n)if(e=n[r].exec(t))switch(r){case"cmyk":var i=v(o(e),5),a=i[1],c=i[2],s=i[3],u=i[4];if(a>100||c>100||s>100||u>100)break;return{values:y(C(a,c,s,u)).concat([1]),type:r};case"rgba":var l=v(o(e),6),p=l[2],d=l[3],h=l[4],f=l[5],g=void 0===f?1:f;if(p>255||d>255||h>255||g<0||g>1)break;return{values:y(A(p,d,h)).concat([g]),type:r};case"hex":var m=function(t,e){return[t.substring(0,e),t.substring(e,t.length)]},b=v(e,2)[1];3===b.length?b+="F":6===b.length&&(b+="FF");var _=void 0;if(4===b.length){var w=v(m(b,3).map(function(t){return t+t}),2);b=w[0],_=w[1]}else if(8===b.length){var k=v(m(b,6),2);b=k[0],_=k[1]}return _=parseInt(_,16)/255,{values:y(O(b)).concat([_]),type:r};case"hsla":var j=v(o(e),6),x=j[2],E=j[3],H=j[4],R=j[5],B=void 0===R?1:R;if(x>360||E>100||H>100||B<0||B>1)break;return{values:y(S(x,E,H)).concat([B]),type:r};case"hsva":var P=v(o(e),6),L=P[2],D=P[3],T=P[4],F=P[5],M=void 0===F?1:F;if(L>360||D>100||T>100||M<0||M>1)break;return{values:[L,D,T,M],type:r}}return{values:null,type:null}}function x(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,i=Math.ceil,a={h:t,s:e,v:n,a:o,toHSVA:function(){var t=[a.h,a.s,a.v],e=t.map(i);return t.toString=function(){return"hsva(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toHSLA:function(){var t=k(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"hsla(".concat(e[0],", ").concat(e[1],"%, ").concat(e[2],"%, ").concat(a.a.toFixed(1),")")},t},toRGBA:function(){var t=b(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"rgba(".concat(e[0],", ").concat(e[1],", ").concat(e[2],", ").concat(a.a.toFixed(1),")")},t},toCMYK:function(){var t=w(a.h,a.s,a.v),e=t.map(i);return t.toString=function(){return"cmyk(".concat(e[0],"%, ").concat(e[1],"%, ").concat(e[2],"%, ").concat(e[3],"%)")},t},toHEX:function(){var t=_.apply(r,[a.h,a.s,a.v]);return t.toString=function(){var e=a.a>=1?"":Number((255*a.a).toFixed(0)).toString(16).toUpperCase().padStart(2,"0");return"#".concat(t.join("").toUpperCase()+e)},t},clone:function(){return x(a.h,a.s,a.v,a.a)}};return a}function E(t){var e={options:Object.assign({lockX:!1,lockY:!1,onchange:function(){return 0}},t),_tapstart:function(t){c(document,["mouseup","touchend","touchcancel"],e._tapstop),c(document,["mousemove","touchmove"],e._tapmove),t.preventDefault(),e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove(t)},_tapmove:function(t){var n=e.options,o=e.cache,r=n.element,i=e.wrapperRect,a=0,c=0;if(t){var s=t&&t.touches&&t.touches[0];a=t?(s||t).clientX:0,c=t?(s||t).clientY:0,ai.left+i.width&&(a=i.left+i.width),ci.top+i.height&&(c=i.top+i.height),a-=i.left,c-=i.top}else o&&(a=o.x,c=o.y);n.lockX||(r.style.left=a-r.offsetWidth/2+"px"),n.lockY||(r.style.top=c-r.offsetHeight/2+"px"),e.cache={x:a,y:c},n.onchange(a,c)},_tapstop:function(){s(document,["mouseup","touchend","touchcancel"],e._tapstop),s(document,["mousemove","touchmove"],e._tapmove)},trigger:function(){e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove()},update:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;e.wrapperRect=e.options.wrapper.getBoundingClientRect(),e._tapmove({clientX:e.wrapperRect.left+t,clientY:e.wrapperRect.top+n})},destroy:function(){var t=e.options,n=e._tapstart;s([t.wrapper,t.element],"mousedown",n),s([t.wrapper,t.element],"touchstart",n,{passive:!1})}};e.wrapperRect=e.options.wrapper.getBoundingClientRect();var n=e.options,o=e._tapstart;return c([n.wrapper,n.element],"mousedown",o),c([n.wrapper,n.element],"touchstart",o,{passive:!1}),e}function H(t){return function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e\n \n '.concat(o?"":'
','\n\n
\n
\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n\n
\n
\n
\n
\n
\n\n
\n \n\n \n \n \n \n \n\n \n \n
\n
\n \n ")),a=i.interaction;return a.options.find(function(t){return!t.hidden&&!t.classList.add("active")}),a.type=function(){return a.options.find(function(t){return t.classList.contains("active")})},i}(t),t.useAsButton&&(t.parent||(t.parent="body"),this._root.button=t.el),document.body.appendChild(this._root.root)}},{key:"_finalBuild",value:function(){var t=this.options,e=this._root;document.body.removeChild(e.root),t.parent&&("string"==typeof t.parent&&(t.parent=document.querySelector(t.parent)),t.parent.appendChild(e.app)),t.useAsButton||t.el.parentElement.replaceChild(e.root,t.el),t.disabled&&this.disable(),t.comparison||(e.button.style.transition="none",t.useAsButton||(e.preview.lastColor.style.transition="none")),t.showAlways?e.app.classList.add("visible"):this.hide()}},{key:"_buildComponents",value:function(){var t=this,e=this.options.components,n={palette:E({element:t._root.palette.picker,wrapper:t._root.palette.palette,onchange:function(e,n){var o=t._color,r=t._root,i=t.options;o.s=e/this.wrapper.offsetWidth*100,o.v=100-n/this.wrapper.offsetHeight*100,o.v<0&&(o.v=0);var a=o.toRGBA().toString();this.element.style.background=a,this.wrapper.style.background="\n linear-gradient(to top, rgba(0, 0, 0, ".concat(o.a,"), transparent), \n linear-gradient(to left, hsla(").concat(o.h,", 100%, 50%, ").concat(o.a,"), rgba(255, 255, 255, ").concat(o.a,"))\n "),i.comparison||(r.button.style.background=a,i.useAsButton||(r.preview.lastColor.style.background=a)),r.preview.currentColor.style.background=a,t._recalc&&t._updateOutput(),r.button.classList.remove("clear")}}),hue:E({lockX:!0,element:t._root.hue.picker,wrapper:t._root.hue.slider,onchange:function(o,r){e.hue&&(t._color.h=r/this.wrapper.offsetHeight*360,this.element.style.backgroundColor="hsl(".concat(t._color.h,", 100%, 50%)"),n.palette.trigger())}}),opacity:E({lockX:!0,element:t._root.opacity.picker,wrapper:t._root.opacity.slider,onchange:function(n,o){e.opacity&&(t._color.a=Math.round(o/this.wrapper.offsetHeight*100)/100,this.element.style.background="rgba(0, 0, 0, ".concat(t._color.a,")"),t.components.palette.trigger())}}),selectable:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e={options:Object.assign({onchange:function(){return 0},className:"",elements:[]},t),_ontap:function(t){var n=e.options;n.elements.forEach(function(e){return e.classList[t.target===e?"add":"remove"](n.className)}),n.onchange(t)},destroy:function(){s(e.options.elements,"click",this._ontap)}};return c(e.options.elements,"click",e._ontap),e}({elements:t._root.interaction.options,className:"active",onchange:function(e){t._representation=e.target.getAttribute("data-type").toUpperCase(),t._updateOutput()}})};this.components=n}},{key:"_bindEvents",value:function(){var t=this,e=this._root,n=this.options,o=[c(e.interaction.clear,"click",function(){return t._clearColor()}),c(e.preview.lastColor,"click",function(){return t.setHSVA.apply(t,H(t._lastColor.toHSVA()))}),c(e.interaction.save,"click",function(){!t._saveColor()&&!n.showAlways&&t.hide()}),c(e.interaction.result,["keyup","input"],function(e){t._recalc=!1,t.setColor(e.target.value,!0)&&!t._initializingActive&&t.options.onChange(t._color,t),e.stopImmediatePropagation()}),c([e.palette.palette,e.palette.picker,e.hue.slider,e.hue.picker,e.opacity.slider,e.opacity.picker],["mousedown","touchstart"],function(){return t._recalc=!0}),c(window,"resize",function(){return t._rePositioningPicker})];if(!n.showAlways){o.push(c(e.button,"click",function(){return t.isOpen()?t.hide():t.show()}));var r=n.closeWithKey;o.push(c(document,"keyup",function(e){return t.isOpen()&&(e.key===r||e.code===r)&&t.hide()})),o.push(c(document,["touchstart","mousedown"],function(n){t.isOpen()&&!h(n).some(function(t){return t===e.app||t===e.button})&&t.hide()},{capture:!0}))}n.adjustableNumbers&&f(e.interaction.result,!1),this._eventBindings=o}},{key:"_rePositioningPicker",value:function(){var t=this._root,e=this._root.app;if(this.options.parent){var n=t.button.getBoundingClientRect();e.style.position="fixed",e.style.marginLeft="".concat(n.left,"px"),e.style.marginTop="".concat(n.top,"px")}var o=t.button.getBoundingClientRect(),r=e.getBoundingClientRect(),i=e.style;r.bottom>window.innerHeight?i.top="".concat(-r.height-5,"px"):o.bottom+r.heightwindow.innerWidth&&l-window.innerWidthwindow.innerWidth&&(s=a.left),i.left="".concat(s,"px")}},{key:"_updateOutput",value:function(){var t=this;this._root.interaction.type()&&(this._root.interaction.result.value=function(){var e="to"+t._root.interaction.type().getAttribute("data-type");return"function"==typeof t._color[e]?t._color[e]().toString():""}()),this._initializingActive||this.options.onChange(this._color,this)}},{key:"_saveColor",value:function(){var t=this._root,e=t.preview,n=t.button,o=this._color.toRGBA().toString();e.lastColor.style.background=o,this.options.useAsButton||(n.style.background=o),n.classList.remove("clear"),this._lastColor=this._color.clone(),this._initializingActive||this.options.onSave(this._color,this)}},{key:"_clearColor",value:function(){var t=this._root,e=this.options;e.useAsButton||(t.button.style.background="rgba(255, 255, 255, 0.4)"),t.button.classList.add("clear"),e.showAlways||this.hide(),e.onSave(null,this)}},{key:"destroy",value:function(){var t=this;this._eventBindings.forEach(function(t){return s.apply(o,H(t))}),Object.keys(this.components).forEach(function(e){return t.components[e].destroy()})}},{key:"destroyAndRemove",value:function(){this.destroy();var t=this._root.root;t.parentElement.removeChild(t)}},{key:"hide",value:function(){return this._root.app.classList.remove("visible"),this}},{key:"show",value:function(){if(!this.options.disabled)return this._root.app.classList.add("visible"),this._rePositioningPicker(),this}},{key:"isOpen",value:function(){return this._root.app.classList.contains("visible")}},{key:"setHSVA",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:360,e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:1,r=arguments.length>4&&void 0!==arguments[4]&&arguments[4],i=this._recalc;if(this._recalc=!1,t<0||t>360||e<0||e>100||n<0||n>100||o<0||o>1)return!1;var a=this.components,c=a.hue,s=a.opacity,u=a.palette,l=c.options.wrapper.offsetHeight*(t/360);c.update(0,l);var p=s.options.wrapper.offsetHeight*o;s.update(0,p);var d=u.options.wrapper,h=d.offsetWidth*(e/100),f=d.offsetHeight*(1-n/100);return u.update(h,f),this._color=new x(t,e,n,o),this._recalc=i,this._recalc&&this._updateOutput(),r||this._saveColor(),!0}},{key:"setColor",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1];if(null===t)return this._clearColor(),!0;var n=j(t),o=n.values,r=n.type;if(o){var i=r.toUpperCase(),a=this._root.interaction.options,c=a.find(function(t){return t.getAttribute("data-type")===i});if(!c.hidden){var s=!0,u=!1,l=void 0;try{for(var p,d=a[Symbol.iterator]();!(s=(p=d.next()).done);s=!0){var h=p.value;h.classList[h===c?"add":"remove"]("active")}}catch(t){u=!0,l=t}finally{try{s||null==d.return||d.return()}finally{if(u)throw l}}}return this.setHSVA.apply(this,H(o).concat([e]))}}},{key:"setColorRepresentation",value:function(t){return t=t.toUpperCase(),!!this._root.interaction.options.find(function(e){return e.getAttribute("data-type")===t&&!e.click()})}},{key:"getColorRepresentation",value:function(){return this._representation}},{key:"getColor",value:function(){return this._color}},{key:"getRoot",value:function(){return this._root}},{key:"disable",value:function(){return this.hide(),this.options.disabled=!0,this._root.button.classList.add("disabled"),this}},{key:"enable",value:function(){return this.options.disabled=!1,this._root.button.classList.remove("disabled"),this}}]),t}();B.utils={once:a,on:c,off:s,eventPath:h,createElementFromString:l,adjustableInputNumbers:f,removeAttribute:p,createFromTemplate:d},B.create=function(t){return new B(t)},B.version="0.3.2";e.default=B}]).default}); -//# sourceMappingURL=pickr.min.js.map \ No newline at end of file diff --git a/wwwroot/pickr/pickr.min.js.map b/wwwroot/pickr/pickr.min.js.map deleted file mode 100644 index 5ea5deef..00000000 --- a/wwwroot/pickr/pickr.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap","webpack:///./src/js/lib/utils.js","webpack:///./src/js/lib/color.js","webpack:///./src/js/lib/hsvacolor.js","webpack:///./src/js/helper/moveable.js","webpack:///./src/js/pickr.js","webpack:///./src/js/helper/selectable.js"],"names":["root","factory","exports","module","define","amd","window","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","once","element","event","fn","options","on","helper","apply","this","arguments","removeEventListener","eventListener","off","method","elements","events","length","undefined","HTMLCollection","NodeList","Array","from","isArray","forEach","el","ev","_objectSpread","capture","slice","createElementFromString","html","div","document","createElement","innerHTML","trim","firstElementChild","removeAttribute","getAttribute","createFromTemplate","str","resolve","base","con","children","subtree","_i","child","arr","push","eventPath","evt","path","composedPath","target","parentElement","adjustableInputNumbers","negative","isNumChar","handleScroll","e","val","selectionStart","numStart","num","isNaN","isFinite","mul","deltaY","inc","ctrlKey","newNum","Number","newStr","substr","substring","curPos","String","focus","setSelectionRange","preventDefault","dispatchEvent","Event","min","Math","max","hsvToRgb","h","v","floor","f","q","mod","hsvToHex","map","round","toString","padStart","hsvToCmyk","k","rgb","g","b","hsvToHsl","rgbToHsv","minVal","maxVal","delta","dr","dg","db","cmykToHsv","y","_toConsumableArray","hslToHsv","hexToHsv","hex","match","parseInt","parseToHSV","regex","cmyk","rgba","hsla","hsva","numarize","array","test","type","exec","_numarize2","_slicedToArray","values","concat","_numarize4","_numarize4$","a","splitAt","alpha","_splitAt$map2","_splitAt2","_numarize6","_numarize6$","_numarize8","_numarize8$","HSVaColor","ceil","that","toHSVA","hsv","rhsv","toFixed","toHSLA","hsl","Color","rhsl","toRGBA","rrgb","toCMYK","rcmyk","toHEX","toUpperCase","join","clone","Moveable","opt","assign","lockX","lockY","onchange","_tapstart","_","_tapstop","_tapmove","wrapperRect","wrapper","getBoundingClientRect","cache","x","touch","touches","clientX","clientY","left","width","top","height","style","offsetWidth","offsetHeight","trigger","update","destroy","passive","Pickr","_classCallCheck","useAsButton","disabled","comparison","components","interaction","strings","default","defaultRepresentation","position","adjustableNumbers","showAlways","parent","closeWithKey","onChange","onSave","onClear","_initializingActive","_recalc","_color","_lastColor","_preBuild","_buildComponents","_bindEvents","setColor","_representation","setColorRepresentation","_finalBuild","_rePositioningPicker","querySelector","_root","hidden","preview","hue","opacity","keys","input","save","clear","int","find","classList","add","contains","button","body","appendChild","removeChild","app","replaceChild","disable","transition","lastColor","hide","inst","comp","palette","picker","cssRGBaString","background","currentColor","_updateOutput","remove","slider","backgroundColor","selectable","className","_ontap","Selectable","_this","eventBindings","_clearColor","setHSVA","pickr_toConsumableArray","_saveColor","result","stopImmediatePropagation","isOpen","show","ck","code","some","_eventBindings","relative","marginLeft","marginTop","bb","ab","as","bottom","innerHeight","pos","middle","right","cl","getComputedStyle","newLeft","leftClip","rightClip","innerWidth","_this2","_this$_root","_this3","args","silent","recalc","_this$components","hueY","opacityY","pickerWrapper","pickerX","pickerY","string","_Color$parseToHSV","utype","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_step","_iterator","iterator","next","done","err","return","click","utils","version"],"mappings":"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","file":"pickr.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"Pickr\"] = factory();\n\telse\n\t\troot[\"Pickr\"] = factory();\n})(window, function() {\nreturn "," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"dist/\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n","/**\r\n * Add an eventlistener which will be fired only once.\r\n *\r\n * @param element Target element\r\n * @param event Event name\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const once = (element, event, fn, options) => on(element, event, function helper() {\r\n fn.apply(this, arguments);\r\n this.removeEventListener(event, helper);\r\n}, options);\r\n\r\n/**\r\n * Add event(s) to element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const on = eventListener.bind(null, 'addEventListener');\r\n\r\n/**\r\n * Remove event(s) from element(s).\r\n * @param elements DOM-Elements\r\n * @param events Event names\r\n * @param fn Callback\r\n * @param options Optional options\r\n * @return Array passed arguments\r\n */\r\nexport const off = eventListener.bind(null, 'removeEventListener');\r\n\r\nfunction eventListener(method, elements, events, fn, options = {}) {\r\n\r\n // Normalize array\r\n if (elements instanceof HTMLCollection || elements instanceof NodeList) {\r\n elements = Array.from(elements);\r\n } else if (!Array.isArray(elements)) {\r\n elements = [elements];\r\n }\r\n\r\n if (!Array.isArray(events)) {\r\n events = [events];\r\n }\r\n\r\n elements.forEach(el =>\r\n events.forEach(ev =>\r\n el[method](ev, fn, {capture: false, ...options})\r\n )\r\n );\r\n\r\n return Array.prototype.slice.call(arguments, 1);\r\n}\r\n\r\n/**\r\n * Creates an DOM-Element out of a string (Single element).\r\n * @param html HTML representing a single element\r\n * @returns {Element | null} The element.\r\n */\r\nexport function createElementFromString(html) {\r\n const div = document.createElement('div');\r\n div.innerHTML = html.trim();\r\n return div.firstElementChild;\r\n}\r\n\r\n/**\r\n * Removes an attribute from a HTMLElement and returns the value.\r\n * @param el\r\n * @param name\r\n * @return {string}\r\n */\r\nexport function removeAttribute(el, name) {\r\n const value = el.getAttribute(name);\r\n el.removeAttribute(name);\r\n return value;\r\n}\r\n\r\n/**\r\n * Creates a new html element, every element which has\r\n * a 'data-key' attribute will be saved in a object (which will be returned)\r\n * where the value of 'data-key' ist the object-key and the value the HTMLElement.\r\n *\r\n * It's possible to create a hierarchy if you add a 'data-con' attribute. Every\r\n * sibling will be added to the object which will get the name from the 'data-con' attribute.\r\n *\r\n * If you want to create an Array out of multiple elements, you can use the 'data-arr' attribute,\r\n * the value defines the key and all elements, which has the same parent and the same 'data-arr' attribute,\r\n * would be added to it.\r\n *\r\n * @param str - The HTML String.\r\n */\r\nexport function createFromTemplate(str) {\r\n\r\n // Recursive function to resolve template\r\n function resolve(element, base = {}) {\r\n\r\n // Check key and container attribute\r\n const con = removeAttribute(element, 'data-con');\r\n const key = removeAttribute(element, 'data-key');\r\n\r\n // Check and save element\r\n if (key) {\r\n base[key] = element;\r\n }\r\n\r\n // Check all children\r\n const children = Array.from(element.children);\r\n const subtree = con ? (base[con] = {}) : base;\r\n for (let child of children) {\r\n\r\n // Check if element should be saved as array\r\n const arr = removeAttribute(child, 'data-arr');\r\n if (arr) {\r\n\r\n // Check if there is already an array and add element\r\n (subtree[arr] || (subtree[arr] = [])).push(child);\r\n } else {\r\n resolve(child, subtree);\r\n }\r\n }\r\n\r\n return base;\r\n }\r\n\r\n return resolve(createElementFromString(str));\r\n}\r\n\r\n/**\r\n * Polyfill for safari & firefox for the eventPath event property.\r\n * @param evt The event object.\r\n * @return [String] event path.\r\n */\r\nexport function eventPath(evt) {\r\n let path = evt.path || (evt.composedPath && evt.composedPath());\r\n if (path) return path;\r\n\r\n let el = evt.target.parentElement;\r\n path = [evt.target, el];\r\n while (el = el.parentElement) path.push(el);\r\n\r\n path.push(document, window);\r\n return path;\r\n}\r\n\r\n/**\r\n * Creates the ability to change numbers in an input field with the scroll-wheel.\r\n * @param el\r\n * @param negative\r\n */\r\nexport function adjustableInputNumbers(el, negative = true) {\r\n\r\n // Check if a char represents a number\r\n const isNumChar = c => (c >= '0' && c <= '9') || c === '-' || c === '.';\r\n\r\n function handleScroll(e) {\r\n const val = el.value;\r\n const off = el.selectionStart;\r\n let numStart = off;\r\n let num = ''; // Will be the number as string\r\n\r\n // Look back\r\n for (let i = off - 1; i > 0 && isNumChar(val[i]); i--) {\r\n num = val[i] + num;\r\n numStart--; // Find start of number\r\n }\r\n\r\n // Look forward\r\n for (let i = off, n = val.length; i < n && isNumChar(val[i]); i++) {\r\n num += val[i];\r\n }\r\n\r\n // Check if number is valid\r\n if (num.length > 0 && !isNaN(num) && isFinite(num)) {\r\n\r\n const mul = e.deltaY < 0 ? 1 : -1;\r\n const inc = e.ctrlKey ? mul * 5 : mul;\r\n let newNum = Number(num) + inc;\r\n\r\n if (!negative && newNum < 0) {\r\n newNum = 0;\r\n }\r\n\r\n const newStr = val.substr(0, numStart) + newNum + val.substring(numStart + num.length, val.length);\r\n const curPos = numStart + String(newNum).length;\r\n\r\n // Update value and set cursor\r\n el.value = newStr;\r\n el.focus();\r\n el.setSelectionRange(curPos, curPos);\r\n }\r\n\r\n // Prevent default\r\n e.preventDefault();\r\n\r\n // Trigger input event\r\n el.dispatchEvent(new Event('input'));\r\n }\r\n\r\n // Bind events\r\n on(el, 'focus', () => on(window, 'wheel', handleScroll));\r\n on(el, 'blur', () => off(window, 'wheel', handleScroll));\r\n}","// Shorthands\r\nconst min = Math.min,\r\n max = Math.max;\r\n\r\n/**\r\n * Convert HSV spectrum to RGB.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} Array with rgb values.\r\n */\r\nexport function hsvToRgb(h, s, v) {\r\n h = (h / 360) * 6;\r\n s /= 100;\r\n v /= 100;\r\n\r\n let i = Math.floor(h);\r\n\r\n let f = h - i;\r\n let p = v * (1 - s);\r\n let q = v * (1 - f * s);\r\n let t = v * (1 - (1 - f) * s);\r\n\r\n let mod = i % 6;\r\n let r = [v, q, p, p, t, v][mod];\r\n let g = [t, v, v, q, p, p][mod];\r\n let b = [p, p, t, v, v, q][mod];\r\n\r\n return [\r\n r * 255,\r\n g * 255,\r\n b * 255\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to Hex.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {string[]} Hex values\r\n */\r\nexport function hsvToHex(h, s, v) {\r\n return hsvToRgb(h, s, v).map(v => Math.round(v).toString(16).padStart(2, '0'));\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to CMYK.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} CMYK values\r\n */\r\nexport function hsvToCmyk(h, s, v) {\r\n const rgb = hsvToRgb(h, s, v);\r\n const r = rgb[0] / 255;\r\n const g = rgb[1] / 255;\r\n const b = rgb[2] / 255;\r\n\r\n let k, c, m, y;\r\n\r\n k = min(1 - r, 1 - g, 1 - b);\r\n\r\n c = k === 1 ? 0 : (1 - r - k) / (1 - k);\r\n m = k === 1 ? 0 : (1 - g - k) / (1 - k);\r\n y = k === 1 ? 0 : (1 - b - k) / (1 - k);\r\n\r\n return [\r\n c * 100,\r\n m * 100,\r\n y * 100,\r\n k * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert HSV spectrum to HSL.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @returns {number[]} HSL values\r\n */\r\nexport function hsvToHsl(h, s, v) {\r\n s /= 100, v /= 100;\r\n\r\n let l = (2 - s) * v / 2;\r\n\r\n if (l !== 0) {\r\n if (l === 1) {\r\n s = 0;\r\n } else if (l < 0.5) {\r\n s = s * v / (l * 2);\r\n } else {\r\n s = s * v / (2 - l * 2);\r\n }\r\n }\r\n\r\n return [\r\n h,\r\n s * 100,\r\n l * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert RGB to HSV.\r\n * @param r Red\r\n * @param g Green\r\n * @param b Blue\r\n * @return {number[]} HSV values.\r\n */\r\nfunction rgbToHsv(r, g, b) {\r\n r /= 255, g /= 255, b /= 255;\r\n\r\n let h, s, v;\r\n const minVal = min(r, g, b);\r\n const maxVal = max(r, g, b);\r\n const delta = maxVal - minVal;\r\n\r\n v = maxVal;\r\n if (delta === 0) {\r\n h = s = 0;\r\n } else {\r\n s = delta / maxVal;\r\n let dr = (((maxVal - r) / 6) + (delta / 2)) / delta;\r\n let dg = (((maxVal - g) / 6) + (delta / 2)) / delta;\r\n let db = (((maxVal - b) / 6) + (delta / 2)) / delta;\r\n\r\n if (r === maxVal) {\r\n h = db - dg;\r\n } else if (g === maxVal) {\r\n h = (1 / 3) + dr - db;\r\n } else if (b === maxVal) {\r\n h = (2 / 3) + dg - dr;\r\n }\r\n\r\n if (h < 0) {\r\n h += 1;\r\n } else if (h > 1) {\r\n h -= 1;\r\n }\r\n }\r\n\r\n return [\r\n h * 360,\r\n s * 100,\r\n v * 100\r\n ];\r\n}\r\n\r\n/**\r\n * Convert CMYK to HSV.\r\n * @param c Cyan\r\n * @param m Magenta\r\n * @param y Yellow\r\n * @param k Key (Black)\r\n * @return {number[]} HSV values.\r\n */\r\nfunction cmykToHsv(c, m, y, k) {\r\n c /= 100, m /= 100, y /= 100, k /= 100;\r\n\r\n const r = (1 - min(1, c * (1 - k) + k)) * 255;\r\n const g = (1 - min(1, m * (1 - k) + k)) * 255;\r\n const b = (1 - min(1, y * (1 - k) + k)) * 255;\r\n\r\n return [...rgbToHsv(r, g, b)];\r\n}\r\n\r\n/**\r\n * Convert HSL to HSV.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param l Lightness\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hslToHsv(h, s, l) {\r\n s /= 100, l /= 100;\r\n s *= l < 0.5 ? l : 1 - l;\r\n\r\n let ns = (2 * s / (l + s)) * 100;\r\n let v = (l + s) * 100;\r\n return [h, ns, v];\r\n}\r\n\r\n/**\r\n * Convert HEX to HSV.\r\n * @param hex Hexadecimal string of rgb colors, can have length 3 or 6.\r\n * @return {number[]} HSV values.\r\n */\r\nfunction hexToHsv(hex) {\r\n return rgbToHsv(...hex.match(/.{2}/g).map(v => parseInt(v, 16)));\r\n}\r\n\r\n/**\r\n * Try's to parse a string which represents a color to a HSV array.\r\n * Current supported types are cmyk, rgba, hsla and hexadecimal.\r\n * @param str\r\n * @return {*}\r\n */\r\nexport function parseToHSV(str) {\r\n\r\n // Regular expressions to match different types of color represention\r\n const regex = {\r\n cmyk: /^cmyk[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)/i,\r\n rgba: /^(rgb|rgba)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsla: /^(hsl|hsla)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hsva: /^(hsv|hsva)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]+(\\d+)[\\D]*?([\\d.]+|$)/i,\r\n hex: /^#?(([\\dA-Fa-f]{3,4})|([\\dA-Fa-f]{6})|([\\dA-Fa-f]{8}))$/i\r\n };\r\n\r\n /**\r\n * Takes an Array of any type, convert strings which represents\r\n * a number to a number an anything else to undefined.\r\n * @param array\r\n * @return {*}\r\n */\r\n const numarize = array => array.map(v => /^(|\\d+)\\.\\d+|\\d+$/.test(v) ? Number(v) : undefined);\r\n\r\n let match;\r\n for (let type in regex) {\r\n\r\n // Check if current scheme passed\r\n if (!(match = regex[type].exec(str)))\r\n continue;\r\n\r\n // Try to convert\r\n switch (type) {\r\n case 'cmyk': {\r\n let [, c, m, y, k] = numarize(match);\r\n\r\n if (c > 100 || m > 100 || y > 100 || k > 100)\r\n break;\r\n\r\n return {values: [...cmykToHsv(c, m, y, k), 1], type};\r\n }\r\n case 'rgba': {\r\n let [, , r, g, b, a = 1] = numarize(match);\r\n\r\n if (r > 255 || g > 255 || b > 255 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...rgbToHsv(r, g, b), a], type};\r\n }\r\n case 'hex': {\r\n const splitAt = (s, i) => [s.substring(0, i), s.substring(i, s.length)];\r\n let [, hex] = match;\r\n\r\n // Fill up opacity if not declared\r\n if (hex.length === 3) {\r\n hex += 'F';\r\n } else if (hex.length === 6) {\r\n hex += 'FF';\r\n }\r\n\r\n let alpha;\r\n if (hex.length === 4) {\r\n [hex, alpha] = splitAt(hex, 3).map(v => v + v);\r\n } else if (hex.length === 8) {\r\n [hex, alpha] = splitAt(hex, 6);\r\n }\r\n\r\n // Convert 0 - 255 to 0 - 1 for opacity\r\n alpha = parseInt(alpha, 16) / 255;\r\n return {values: [...hexToHsv(hex), alpha], type};\r\n }\r\n case 'hsla': {\r\n let [, , h, s, l, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || l > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [...hslToHsv(h, s, l), a], type};\r\n }\r\n case 'hsva': {\r\n let [, , h, s, v, a = 1] = numarize(match);\r\n\r\n if (h > 360 || s > 100 || v > 100 || a < 0 || a > 1)\r\n break;\r\n\r\n return {values: [h, s, v, a], type};\r\n }\r\n }\r\n }\r\n\r\n return {values: null, type: null};\r\n}","import * as Color from './color';\r\n\r\n/**\r\n * Simple class which holds the properties\r\n * of the color represention model hsla (hue saturation lightness alpha)\r\n */\r\nexport function HSVaColor(h = 0, s = 0, v = 0, a = 1) {\r\n\r\n const ceil = Math.ceil;\r\n const that = {\r\n h, s, v, a,\r\n\r\n toHSVA() {\r\n const hsv = [that.h, that.s, that.v];\r\n const rhsv = hsv.map(ceil);\r\n\r\n hsv.toString = () => `hsva(${rhsv[0]}, ${rhsv[1]}%, ${rhsv[2]}%, ${that.a.toFixed(1)})`;\r\n return hsv;\r\n },\r\n\r\n toHSLA() {\r\n const hsl = Color.hsvToHsl(that.h, that.s, that.v);\r\n const rhsl = hsl.map(ceil);\r\n\r\n hsl.toString = () => `hsla(${rhsl[0]}, ${rhsl[1]}%, ${rhsl[2]}%, ${that.a.toFixed(1)})`;\r\n return hsl;\r\n },\r\n\r\n toRGBA() {\r\n const rgb = Color.hsvToRgb(that.h, that.s, that.v);\r\n const rrgb = rgb.map(ceil);\r\n\r\n rgb.toString = () => `rgba(${rrgb[0]}, ${rrgb[1]}, ${rrgb[2]}, ${that.a.toFixed(1)})`;\r\n return rgb;\r\n },\r\n\r\n toCMYK() {\r\n const cmyk = Color.hsvToCmyk(that.h, that.s, that.v);\r\n const rcmyk = cmyk.map(ceil);\r\n\r\n cmyk.toString = () => `cmyk(${rcmyk[0]}%, ${rcmyk[1]}%, ${rcmyk[2]}%, ${rcmyk[3]}%)`;\r\n return cmyk;\r\n },\r\n\r\n toHEX() {\r\n const hex = Color.hsvToHex(...[that.h, that.s, that.v]);\r\n\r\n hex.toString = () => {\r\n\r\n // Check if alpha channel make sense, convert it to 255 number space, convert\r\n // to hex and pad it with zeros if needet.\r\n const alpha = that.a >= 1 ? '' : Number((that.a * 255).toFixed(0))\r\n .toString(16)\r\n .toUpperCase()\r\n .padStart(2, '0');\r\n\r\n return `#${hex.join('').toUpperCase() + alpha}`;\r\n };\r\n\r\n return hex;\r\n },\r\n\r\n clone() {\r\n return HSVaColor(that.h, that.s, that.v, that.a);\r\n }\r\n };\r\n\r\n return that;\r\n}","import * as _ from './../lib/utils';\r\n\r\nexport default function Moveable(opt) {\r\n\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n lockX: false,\r\n lockY: false,\r\n onchange: () => 0\r\n }, opt),\r\n\r\n _tapstart(evt) {\r\n _.on(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.on(document, ['mousemove', 'touchmove'], that._tapmove);\r\n\r\n // Prevent default touch event\r\n evt.preventDefault();\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Trigger\r\n that._tapmove(evt);\r\n },\r\n\r\n _tapmove(evt) {\r\n const {options, cache} = that;\r\n const {element} = options;\r\n const b = that.wrapperRect;\r\n\r\n let x = 0, y = 0;\r\n if (evt) {\r\n const touch = evt && evt.touches && evt.touches[0];\r\n x = evt ? (touch || evt).clientX : 0;\r\n y = evt ? (touch || evt).clientY : 0;\r\n\r\n // Reset to bounds\r\n if (x < b.left) x = b.left;\r\n else if (x > b.left + b.width) x = b.left + b.width;\r\n if (y < b.top) y = b.top;\r\n else if (y > b.top + b.height) y = b.top + b.height;\r\n\r\n // Normalize\r\n x -= b.left;\r\n y -= b.top;\r\n } else if (cache) {\r\n x = cache.x;\r\n y = cache.y;\r\n }\r\n\r\n if (!options.lockX)\r\n element.style.left = (x - element.offsetWidth / 2) + 'px';\r\n\r\n if (!options.lockY)\r\n element.style.top = (y - element.offsetHeight / 2) + 'px';\r\n\r\n that.cache = {x, y};\r\n options.onchange(x, y);\r\n },\r\n\r\n _tapstop() {\r\n _.off(document, ['mouseup', 'touchend', 'touchcancel'], that._tapstop);\r\n _.off(document, ['mousemove', 'touchmove'], that._tapmove);\r\n },\r\n\r\n trigger() {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove();\r\n },\r\n\r\n update(x = 0, y = 0) {\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n that._tapmove({\r\n clientX: that.wrapperRect.left + x,\r\n clientY: that.wrapperRect.top + y\r\n });\r\n },\r\n\r\n destroy() {\r\n const {options, _tapstart} = that;\r\n _.off([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.off([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n }\r\n };\r\n\r\n // Instance var\r\n that.wrapperRect = that.options.wrapper.getBoundingClientRect();\r\n\r\n // Initilize\r\n const {options, _tapstart} = that;\r\n _.on([options.wrapper, options.element], 'mousedown', _tapstart);\r\n _.on([options.wrapper, options.element], 'touchstart', _tapstart, {\r\n passive: false\r\n });\r\n\r\n return that;\r\n}","// Import styles\r\nimport '../scss/pickr.scss';\r\n\r\n// Import utils\r\nimport * as _ from './lib/utils';\r\nimport * as Color from './lib/color';\r\n\r\n// Import classes\r\nimport {HSVaColor} from './lib/hsvacolor';\r\nimport Moveable from './helper/moveable';\r\nimport Selectable from './helper/selectable';\r\n\r\nclass Pickr {\r\n\r\n constructor(opt) {\r\n\r\n // Assign default values\r\n this.options = Object.assign({\r\n useAsButton: false,\r\n disabled: false,\r\n comparison: true,\r\n\r\n components: {interaction: {}},\r\n strings: {},\r\n\r\n default: 'fff',\r\n defaultRepresentation: 'HEX',\r\n position: 'middle',\r\n adjustableNumbers: true,\r\n showAlways: false,\r\n parent: undefined,\r\n\r\n closeWithKey: 'Escape',\r\n onChange: () => 0,\r\n onSave: () => 0,\r\n onClear: () => 0\r\n }, opt);\r\n\r\n // Check interaction section\r\n if (!this.options.components.interaction) {\r\n this.options.components.interaction = {};\r\n }\r\n\r\n // Will be used to prevent specific actions during initilization\r\n this._initializingActive = true;\r\n\r\n // Replace element with color picker\r\n this._recalc = true;\r\n\r\n // Current and last color for comparison\r\n this._color = new HSVaColor();\r\n this._lastColor = new HSVaColor();\r\n\r\n // Initialize picker\r\n this._preBuild();\r\n this._buildComponents();\r\n this._bindEvents();\r\n\r\n // Initialize color\r\n this.setColor(this.options.default);\r\n\r\n // Initialize color _epresentation\r\n this._representation = this.options.defaultRepresentation;\r\n this.setColorRepresentation(this._representation);\r\n\r\n // Initilization is finish, pickr is visible and ready to use\r\n this._initializingActive = false;\r\n\r\n // Finalize build\r\n this._finalBuild();\r\n this._rePositioningPicker();\r\n }\r\n\r\n // Does only the absolutly basic thing to initialize the components\r\n _preBuild() {\r\n const opt = this.options;\r\n\r\n // Check if element is selector\r\n if (typeof opt.el === 'string') {\r\n opt.el = document.querySelector(opt.el);\r\n }\r\n\r\n // Create element and append it to body to\r\n // prevent initialization errors\r\n this._root = create(opt);\r\n\r\n // Check if a custom button is used\r\n if (opt.useAsButton) {\r\n\r\n // Check if the user has an alternative location defined, used body as fallback\r\n if (!opt.parent) {\r\n opt.parent = 'body';\r\n }\r\n\r\n this._root.button = opt.el; // Replace button with customized button\r\n }\r\n\r\n document.body.appendChild(this._root.root);\r\n }\r\n\r\n _finalBuild() {\r\n const opt = this.options;\r\n const root = this._root;\r\n\r\n // Remove from body\r\n document.body.removeChild(root.root);\r\n\r\n // Check parent option\r\n if (opt.parent) {\r\n\r\n // Check if element is selector\r\n if (typeof opt.parent === 'string') {\r\n opt.parent = document.querySelector(opt.parent);\r\n }\r\n\r\n opt.parent.appendChild(root.app);\r\n }\r\n\r\n // Don't replace the the element if a custom button is used\r\n if (!opt.useAsButton) {\r\n\r\n // Replace element with actual color-picker\r\n opt.el.parentElement.replaceChild(root.root, opt.el);\r\n }\r\n\r\n // Call disable to also add the disabled class\r\n if (opt.disabled) {\r\n this.disable();\r\n }\r\n\r\n // Check if color comparison is disabled, if yes - remove transitions so everything keeps smoothly\r\n if (!opt.comparison) {\r\n root.button.style.transition = 'none';\r\n if (!opt.useAsButton) {\r\n root.preview.lastColor.style.transition = 'none';\r\n }\r\n }\r\n\r\n // Check showAlways option\r\n opt.showAlways ? root.app.classList.add('visible') : this.hide();\r\n }\r\n\r\n _buildComponents() {\r\n\r\n // Instance reference\r\n const inst = this;\r\n const comp = this.options.components;\r\n\r\n const components = {\r\n\r\n palette: Moveable({\r\n element: inst._root.palette.picker,\r\n wrapper: inst._root.palette.palette,\r\n\r\n onchange(x, y) {\r\n const {_color, _root, options} = inst;\r\n\r\n // Calculate saturation based on the position\r\n _color.s = (x / this.wrapper.offsetWidth) * 100;\r\n\r\n // Calculate the value\r\n _color.v = 100 - (y / this.wrapper.offsetHeight) * 100;\r\n\r\n // Prevent falling under zero\r\n _color.v < 0 ? _color.v = 0 : 0;\r\n\r\n // Set picker and gradient color\r\n const cssRGBaString = _color.toRGBA().toString();\r\n this.element.style.background = cssRGBaString;\r\n this.wrapper.style.background = `\r\n linear-gradient(to top, rgba(0, 0, 0, ${_color.a}), transparent), \r\n linear-gradient(to left, hsla(${_color.h}, 100%, 50%, ${_color.a}), rgba(255, 255, 255, ${_color.a}))\r\n `;\r\n\r\n // Check if color is locked\r\n if (!options.comparison) {\r\n _root.button.style.background = cssRGBaString;\r\n\r\n if (!options.useAsButton) {\r\n _root.preview.lastColor.style.background = cssRGBaString;\r\n }\r\n }\r\n\r\n // Change current color\r\n _root.preview.currentColor.style.background = cssRGBaString;\r\n\r\n // Update the input field only if the user is currently not typing\r\n if (inst._recalc) {\r\n inst._updateOutput();\r\n }\r\n\r\n // If the user changes the color, remove the cleared icon\r\n _root.button.classList.remove('clear');\r\n }\r\n }),\r\n\r\n hue: Moveable({\r\n lockX: true,\r\n element: inst._root.hue.picker,\r\n wrapper: inst._root.hue.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.hue) return;\r\n\r\n // Calculate hue\r\n inst._color.h = (y / this.wrapper.offsetHeight) * 360;\r\n\r\n // Update color\r\n this.element.style.backgroundColor = `hsl(${inst._color.h}, 100%, 50%)`;\r\n components.palette.trigger();\r\n }\r\n }),\r\n\r\n opacity: Moveable({\r\n lockX: true,\r\n element: inst._root.opacity.picker,\r\n wrapper: inst._root.opacity.slider,\r\n\r\n onchange(x, y) {\r\n if (!comp.opacity) return;\r\n\r\n // Calculate opacity\r\n inst._color.a = Math.round(((y / this.wrapper.offsetHeight)) * 1e2) / 100;\r\n\r\n // Update color\r\n this.element.style.background = `rgba(0, 0, 0, ${inst._color.a})`;\r\n inst.components.palette.trigger();\r\n }\r\n }),\r\n\r\n selectable: Selectable({\r\n elements: inst._root.interaction.options,\r\n className: 'active',\r\n onchange(e) {\r\n inst._representation = e.target.getAttribute('data-type').toUpperCase();\r\n inst._updateOutput();\r\n }\r\n })\r\n };\r\n\r\n this.components = components;\r\n }\r\n\r\n _bindEvents() {\r\n const {_root, options} = this;\r\n\r\n const eventBindings = [\r\n\r\n // Clear color\r\n _.on(_root.interaction.clear, 'click', () => this._clearColor()),\r\n\r\n // Select last color on click\r\n _.on(_root.preview.lastColor, 'click', () => this.setHSVA(...this._lastColor.toHSVA())),\r\n\r\n // Save color\r\n _.on(_root.interaction.save, 'click', () => {\r\n !this._saveColor() && !options.showAlways && this.hide();\r\n }),\r\n\r\n // Detect user input and disable auto-recalculation\r\n _.on(_root.interaction.result, ['keyup', 'input'], e => {\r\n this._recalc = false;\r\n\r\n // Fire listener if initialization is finish and changed color was valid\r\n if (this.setColor(e.target.value, true) && !this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n\r\n e.stopImmediatePropagation();\r\n }),\r\n\r\n // Cancel input detection on color change\r\n _.on([\r\n _root.palette.palette,\r\n _root.palette.picker,\r\n _root.hue.slider,\r\n _root.hue.picker,\r\n _root.opacity.slider,\r\n _root.opacity.picker\r\n ], ['mousedown', 'touchstart'], () => this._recalc = true),\r\n\r\n // Repositioning on resize\r\n _.on(window, 'resize', () => this._rePositioningPicker)\r\n ];\r\n\r\n // Provide hiding / showing abilities only if showAlways is false\r\n if (!options.showAlways) {\r\n\r\n // Save and hide / show picker\r\n eventBindings.push(_.on(_root.button, 'click', () => this.isOpen() ? this.hide() : this.show()));\r\n\r\n // Close with escape key\r\n const ck = options.closeWithKey;\r\n eventBindings.push(_.on(document, 'keyup', e => this.isOpen() && (e.key === ck || e.code === ck) && this.hide()));\r\n\r\n // Cancel selecting if the user taps behind the color picker\r\n eventBindings.push(_.on(document, ['touchstart', 'mousedown'], e => {\r\n if (this.isOpen() && !_.eventPath(e).some(el => el === _root.app || el === _root.button)) {\r\n this.hide();\r\n }\r\n }, {capture: true}));\r\n }\r\n\r\n // Make input adjustable if enabled\r\n if (options.adjustableNumbers) {\r\n _.adjustableInputNumbers(_root.interaction.result, false);\r\n }\r\n\r\n // Save bindings\r\n this._eventBindings = eventBindings;\r\n }\r\n\r\n _rePositioningPicker() {\r\n const root = this._root;\r\n const app = this._root.app;\r\n\r\n // Check if user has defined a parent\r\n if (this.options.parent) {\r\n const relative = root.button.getBoundingClientRect();\r\n app.style.position = 'fixed';\r\n app.style.marginLeft = `${relative.left}px`;\r\n app.style.marginTop = `${relative.top}px`;\r\n }\r\n\r\n const bb = root.button.getBoundingClientRect();\r\n const ab = app.getBoundingClientRect();\r\n const as = app.style;\r\n\r\n // Check if picker is cuttet of from the top & bottom\r\n if (ab.bottom > window.innerHeight) {\r\n as.top = `${-(ab.height) - 5}px`;\r\n } else if (bb.bottom + ab.height < window.innerHeight) {\r\n as.top = `${bb.height + 5}px`;\r\n }\r\n\r\n // Positioning picker on the x-axis\r\n const pos = {\r\n left: -(ab.width) + bb.width,\r\n middle: -(ab.width / 2) + bb.width / 2,\r\n right: 0\r\n };\r\n\r\n const cl = parseInt(getComputedStyle(app).left, 10);\r\n let newLeft = pos[this.options.position];\r\n const leftClip = (ab.left - cl) + newLeft;\r\n const rightClip = (ab.left - cl) + newLeft + ab.width;\r\n\r\n /**\r\n * First check if position is left or right but\r\n * pickr-app cannot set to left AND right because it would\r\n * be clipped by the browser width. If so, wrap it and position\r\n * pickr below button via the pos[middle] value.\r\n * The current selected posiotion should'nt be the middle.di\r\n */\r\n if (this.options.position !== 'middle' && (\r\n (leftClip < 0 && -leftClip < ab.width / 2) ||\r\n (rightClip > window.innerWidth && rightClip - window.innerWidth < ab.width / 2))) {\r\n newLeft = pos['middle'];\r\n\r\n /**\r\n * Even if set to middle pickr is getting clipped, so\r\n * set it to left / right.\r\n */\r\n } else if (leftClip < 0) {\r\n newLeft = pos['right'];\r\n } else if (rightClip > window.innerWidth) {\r\n newLeft = pos['left'];\r\n }\r\n\r\n as.left = `${newLeft}px`;\r\n }\r\n\r\n _updateOutput() {\r\n\r\n // Check if component is present\r\n if (this._root.interaction.type()) {\r\n\r\n this._root.interaction.result.value = (() => {\r\n\r\n // Construct function name and call if present\r\n const method = 'to' + this._root.interaction.type().getAttribute('data-type');\r\n return typeof this._color[method] === 'function' ? this._color[method]().toString() : '';\r\n })();\r\n }\r\n\r\n // Fire listener if initialization is finish\r\n if (!this._initializingActive) {\r\n this.options.onChange(this._color, this);\r\n }\r\n }\r\n\r\n _saveColor() {\r\n const {preview, button} = this._root;\r\n\r\n // Change preview and current color\r\n const cssRGBaString = this._color.toRGBA().toString();\r\n preview.lastColor.style.background = cssRGBaString;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!this.options.useAsButton) {\r\n button.style.background = cssRGBaString;\r\n }\r\n\r\n // User changed the color so remove the clear clas\r\n button.classList.remove('clear');\r\n\r\n // Save last color\r\n this._lastColor = this._color.clone();\r\n\r\n // Fire listener\r\n if (!this._initializingActive) {\r\n this.options.onSave(this._color, this);\r\n }\r\n }\r\n\r\n _clearColor() {\r\n const {_root, options} = this;\r\n\r\n // Change only the button color if it isn't customized\r\n if (!options.useAsButton) {\r\n _root.button.style.background = 'rgba(255, 255, 255, 0.4)';\r\n }\r\n\r\n _root.button.classList.add('clear');\r\n\r\n if (!options.showAlways) {\r\n this.hide();\r\n }\r\n\r\n // Fire listener\r\n options.onSave(null, this);\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys\r\n */\r\n destroy() {\r\n this._eventBindings.forEach(args => _.off(...args));\r\n Object.keys(this.components).forEach(key => this.components[key].destroy());\r\n }\r\n\r\n /**\r\n * Destroy's all functionalitys and removes\r\n * the pickr element.\r\n */\r\n destroyAndRemove() {\r\n this.destroy();\r\n\r\n // Remove element\r\n const root = this._root.root;\r\n root.parentElement.removeChild(root);\r\n }\r\n\r\n /**\r\n * Hides the color-picker ui.\r\n */\r\n hide() {\r\n this._root.app.classList.remove('visible');\r\n return this;\r\n }\r\n\r\n /**\r\n * Shows the color-picker ui.\r\n */\r\n show() {\r\n if (this.options.disabled) return;\r\n this._root.app.classList.add('visible');\r\n this._rePositioningPicker();\r\n return this;\r\n }\r\n\r\n /**\r\n * @return {boolean} If the color picker is currently open\r\n */\r\n isOpen() {\r\n return this._root.app.classList.contains('visible');\r\n }\r\n\r\n /**\r\n * Set a specific color.\r\n * @param h Hue\r\n * @param s Saturation\r\n * @param v Value\r\n * @param a Alpha channel (0 - 1)\r\n * @param silent If the button should not change the color\r\n * @return true if the color has been accepted\r\n */\r\n setHSVA(h = 360, s = 0, v = 0, a = 1, silent = false) {\r\n\r\n // Deactivate color calculation\r\n const recalc = this._recalc; // Save state\r\n this._recalc = false;\r\n\r\n // Validate input\r\n if (h < 0 || h > 360 || s < 0 || s > 100 || v < 0 || v > 100 || a < 0 || a > 1) {\r\n return false;\r\n }\r\n\r\n // Short names\r\n const {hue, opacity, palette} = this.components;\r\n\r\n // Calculate y position of hue slider\r\n const hueWrapper = hue.options.wrapper;\r\n const hueY = hueWrapper.offsetHeight * (h / 360);\r\n hue.update(0, hueY);\r\n\r\n // Calculate y position of opacity slider\r\n const opacityWrapper = opacity.options.wrapper;\r\n const opacityY = opacityWrapper.offsetHeight * a;\r\n opacity.update(0, opacityY);\r\n\r\n // Calculate y and x position of color palette\r\n const pickerWrapper = palette.options.wrapper;\r\n const pickerX = pickerWrapper.offsetWidth * (s / 100);\r\n const pickerY = pickerWrapper.offsetHeight * (1 - (v / 100));\r\n palette.update(pickerX, pickerY);\r\n\r\n // Override current color and re-active color calculation\r\n this._color = new HSVaColor(h, s, v, a);\r\n this._recalc = recalc; // Restore old state\r\n\r\n // Update output if recalculation is enabled\r\n if (this._recalc) {\r\n this._updateOutput();\r\n }\r\n\r\n // Check if call is silent\r\n if (!silent) {\r\n this._saveColor();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n /**\r\n * Tries to parse a string which represents a color.\r\n * Examples: #fff\r\n * rgb 10 10 200\r\n * hsva 10 20 5 0.5\r\n * @param string\r\n * @param silent\r\n */\r\n setColor(string, silent = false) {\r\n\r\n // Check if null\r\n if (string === null) {\r\n this._clearColor();\r\n return true;\r\n }\r\n\r\n const {values, type} = Color.parseToHSV(string);\r\n\r\n // Check if color is ok\r\n if (values) {\r\n\r\n // Change selected color format\r\n const utype = type.toUpperCase();\r\n const {options} = this._root.interaction;\r\n const target = options.find(el => el.getAttribute('data-type') === utype);\r\n\r\n // Auto select only if not hidden\r\n if (!target.hidden) {\r\n for (const el of options) {\r\n el.classList[el === target ? 'add' : 'remove']('active');\r\n }\r\n }\r\n\r\n return this.setHSVA(...values, silent);\r\n }\r\n }\r\n\r\n /**\r\n * Changes the color _representation.\r\n * Allowed values are HEX, RGBA, HSVA, HSLA and CMYK\r\n * @param type\r\n * @returns {boolean} if the selected type was valid.\r\n */\r\n setColorRepresentation(type) {\r\n\r\n // Force uppercase to allow a case-sensitiv comparison\r\n type = type.toUpperCase();\r\n\r\n // Find button with given type and trigger click event\r\n return !!this._root.interaction.options.find(v => v.getAttribute('data-type') === type && !v.click());\r\n }\r\n\r\n /**\r\n * Returns the current color representaion. See setColorRepresentation\r\n * @returns {*}\r\n */\r\n getColorRepresentation() {\r\n return this._representation;\r\n }\r\n\r\n /**\r\n * @returns HSVaColor Current HSVaColor object.\r\n */\r\n getColor() {\r\n return this._color;\r\n }\r\n\r\n /**\r\n * @returns The root HTMLElement with all his components.\r\n */\r\n getRoot() {\r\n return this._root;\r\n }\r\n\r\n /**\r\n * Disable pickr\r\n */\r\n disable() {\r\n this.hide();\r\n this.options.disabled = true;\r\n this._root.button.classList.add('disabled');\r\n return this;\r\n }\r\n\r\n /**\r\n * Enable pickr\r\n */\r\n enable() {\r\n this.options.disabled = false;\r\n this._root.button.classList.remove('disabled');\r\n return this;\r\n }\r\n}\r\n\r\nfunction create(options) {\r\n const {components, strings, useAsButton} = options;\r\n const hidden = con => con ? '' : 'style=\"display:none\" hidden';\r\n\r\n const root = _.createFromTemplate(`\r\n
\r\n \r\n ${useAsButton ? '' : '
'}\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n
\r\n
\r\n
\r\n `);\r\n\r\n const int = root.interaction;\r\n\r\n // Select option which is not hidden\r\n int.options.find(o => !o.hidden && !o.classList.add('active'));\r\n\r\n // Create method to find currenlty active option\r\n int.type = () => int.options.find(e => e.classList.contains('active'));\r\n return root;\r\n}\r\n\r\n// Static methods\r\nPickr.utils = {\r\n once: _.once,\r\n on: _.on,\r\n off: _.off,\r\n eventPath: _.eventPath,\r\n createElementFromString: _.createElementFromString,\r\n adjustableInputNumbers: _.adjustableInputNumbers,\r\n removeAttribute: _.removeAttribute,\r\n createFromTemplate: _.createFromTemplate\r\n};\r\n\r\n// Create instance via method\r\nPickr.create = (options) => new Pickr(options);\r\n\r\n// Export\r\nPickr.version = '0.3.2';\r\nexport default Pickr;","import * as _ from './../lib/utils';\r\n\r\nexport default function Selectable(opt = {}) {\r\n const that = {\r\n\r\n // Assign default values\r\n options: Object.assign({\r\n onchange: () => 0,\r\n className: '',\r\n elements: []\r\n }, opt),\r\n\r\n _ontap(evt) {\r\n const opt = that.options;\r\n opt.elements.forEach(e =>\r\n e.classList[evt.target === e ? 'add' : 'remove'](opt.className)\r\n );\r\n\r\n opt.onchange(evt);\r\n },\r\n\r\n destroy() {\r\n _.off(that.options.elements, 'click', this._ontap);\r\n }\r\n };\r\n\r\n _.on(that.options.elements, 'click', that._ontap);\r\n return that;\r\n}"],"sourceRoot":""} \ No newline at end of file From 57d150eb108a42046099d03a703e292f3686b7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Sat, 1 Dec 2018 10:52:08 +0100 Subject: [PATCH 19/65] Removing Assets.json --HG-- branch : issue/OCORE-1 --- Assets.json | 61 ----------------------------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 Assets.json diff --git a/Assets.json b/Assets.json deleted file mode 100644 index 68b2d6f0..00000000 --- a/Assets.json +++ /dev/null @@ -1,61 +0,0 @@ -[ - { - "inputs": [ - "Assets/Lib/jsplumb/jsplumbtoolkit-defaults.css" - ], - "output": "wwwroot/Styles/jsplumbtoolkit-defaults.css" - }, - { - "inputs": [ - "Assets/Lib/jsplumb/jsplumb.js" - ], - "output": "wwwroot/Scripts/jsplumb.js" - }, - { - "inputs": [ - "Assets/Styles/workflow-editor.scss" - ], - "output": "wwwroot/Styles/orchard.workflows-editor.css" - }, - { - "inputs": [ - "Assets/Styles/workflow-viewer.scss" - ], - "output": "wwwroot/Styles/orchard.workflows-viewer.css" - }, - { - "inputs": [ - "Assets/Styles/admin-menu.scss" - ], - "output": "wwwroot/Styles/menu.workflows-admin.css" - }, - { - "inputs": [ - "Assets/Scripts/activity-picker.ts", - "Assets/Scripts/workflow-url-generator.ts", - "Assets/Scripts/workflow-canvas.ts", - "Assets/Scripts/workflow-editor.ts" - ], - "output": "wwwroot/Scripts/orchard.workflows-editor.js" - }, - { - "inputs": [ - "HTTP/Assets/Scripts/workflow-url-generator.ts" - ], - "output": "wwwroot/Scripts/orchard.http-request-event-editor.js" - }, - { - "inputs": [ - "./node_modules/", - "Assets/Scripts/workflow-viewer.ts" - ], - "output": "wwwroot/Scripts/orchard.workflows-viewer.js" - }, - { - "copy": true, - "inputs": [ - "Assets/Images/*" - ], - "output": "wwwroot/Images/@" - } -] From 9d1d28e9ddff2d58fb6ab1a69ad39d0988ed1dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Sat, 1 Dec 2018 10:55:23 +0100 Subject: [PATCH 20/65] Removing test code --HG-- branch : issue/OCORE-1 --- Controllers/PersonListController.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Controllers/PersonListController.cs b/Controllers/PersonListController.cs index 75b761e0..0cce246f 100644 --- a/Controllers/PersonListController.cs +++ b/Controllers/PersonListController.cs @@ -1,7 +1,6 @@ using System.Linq; using System.Threading.Tasks; using Lombiq.TrainingDemo.Indexes; -using Lombiq.TrainingDemo.Models; using Microsoft.AspNetCore.Mvc; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Display; @@ -16,19 +15,16 @@ public class PersonListController : Controller, IUpdateModel private readonly ISession _session; private readonly IClock _clock; private readonly IContentItemDisplayManager _contentItemDisplayManager; - private readonly IContentManager _contentManager; public PersonListController( ISession session, IClock clock, - IContentItemDisplayManager contentItemDisplayManager, - IContentManager contentManager) + IContentItemDisplayManager contentItemDisplayManager) { _session = session; _clock = clock; _contentItemDisplayManager = contentItemDisplayManager; - _contentManager = contentManager; } @@ -41,18 +37,7 @@ public async Task OlderThan30() var shapes = await Task.WhenAll(people.Select(async person => await _contentItemDisplayManager.BuildDisplayAsync(person, this, "Summary"))); - - // Testing 1..2..3... - - var person1 = await _contentManager.NewAsync("Person"); - var personPart1 = person1.As(); - personPart1.Name = "Person 1"; - - var person2 = await _contentManager.NewAsync("Person"); - var personPart2 = person2.As(); - personPart2.Name = "Person 2"; - - + return View(shapes); } } From 37bca083c2c96b590a03cabb3573ae9b7f043a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Sat, 1 Dec 2018 11:36:44 +0100 Subject: [PATCH 21/65] Adding Map.cs --HG-- branch : issue/OCORE-1 --- Map.cs | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 Map.cs diff --git a/Map.cs b/Map.cs new file mode 100644 index 00000000..9ef11313 --- /dev/null +++ b/Map.cs @@ -0,0 +1,98 @@ +using Lombiq.TrainingDemo.Controllers; +using Lombiq.TrainingDemo.Drivers; +using Lombiq.TrainingDemo.Fields; +using Lombiq.TrainingDemo.Indexes; +using Lombiq.TrainingDemo.Indexing; +using Lombiq.TrainingDemo.Models; +using Lombiq.TrainingDemo.Settings; +using Lombiq.TrainingDemo.ViewModels; + +/* + * In this file, you'll find the index of the whole (or at least most of the) module's classes for easier navigation + * between topics. You can navigate directly to classes and their methods by clicking on their names (enclosed in a + * Factory() ) and pressing F12. + * + * This class is not doing anything and only serves as an easy to use table of contents. + */ +namespace Lombiq.TrainingDemo +{ + static class Map + { + private static T Factory() => default(T); + + private static void Treasure() + { + // Manifest.cs: module manifest and dependencies + + // Static resources: styles and scripts + // Declaration + Factory(); + + // Usage: require/include + // Views/PersonListDashboard + + + // Basic controller demonstrating localization, Notifier, routing + Factory(); + + + // Display management, IDisplayManager + Factory(); + + // Display types, zones, placement + // Views/Book.cshtml + // Views/Book.Description.cshtml + Factory(); + + + // ContentPart, ContentField on ContentPart + Factory(); + + // Displaying, editing and updating ContentPart + // Views/PersonPart.cshtml + // Views/PersonPart.Edit.cshtml + // Views/PersonPart.Summary.cshtml built-in Summary display type + // Views/PersonPart.SummaryAdmin.cshtml built-in SummaryAdmin display type + Factory(); + + // Validating ContentPart fields + Factory(); + + // IndexProvider, indexing ContentPart in records + Factory(); + + // Content Type, ContentPart, ContentField, index record creation. + Factory(); + + // ISession, IContentItemDisplayManager, IClock + Factory(); + + + // ContentField + Factory(); + + // ContentFieldSettings + Factory(); + + // Editing and updating ContentFieldSettings + // Views/ColorFieldSettings.Edit.cshtml + Factory(); + + // Displaying, editing and updating ContentField + // Views/ColorField.cshtml + // Views/ColorField.Edit.cshtml + // Views/ColorField.Option.cshtml default editor option name + // Views/ColorField-ColorPicker.Option.cshtml custom editor option name + // Views/ColorField-ColorPicker.Edit.cshtml custom editor option editor + Factory(); + + // ContentFieldIndexHandler, indexing ContentField using custom index provider (e.g. Lucene). + Factory(); + + + // ResourceManifest, scripts, styles + // Views/ColorField-ColorPicker.Edit.cshtml resource injection + Factory(); + } + } +} \ No newline at end of file From 67754583d586ed195604b1563d9b578345e80c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Sat, 1 Dec 2018 12:08:07 +0100 Subject: [PATCH 22/65] Updating Readme --HG-- branch : issue/OCORE-1 --- Readme.md | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/Readme.md b/Readme.md index b5a1618a..133fb0a6 100644 --- a/Readme.md +++ b/Readme.md @@ -1,12 +1,40 @@ -# Orchard Core Training Demo module Readme +# Orchard Core Training Demo module ## Project Description -Demo Orchard module for training purposes. This module completes the training materials at [https://orcharddojo.net/orchard-resources](https://orcharddojo.net/orchard-resources). +Demo Orchard Core module for training purposes. -**For all our training materials and Orchard trainings please visit [Orchard Dojo](https://orcharddojo.net/).** +**If you are interested in Orchard 1.x training materials and Orchard trainings please visit [Orchard Dojo](https://orcharddojo.net/).** -## Documentation \ No newline at end of file +## How to Start + +You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core Nuget packeges, however, it's harder to look under the hood of Orchard Core features. + + +### Using a full Orchard Core source + +* Open an Orchard Core solution +* Add this project to the solution +* Add this project as a reference to OrchardCore.Application.Cms.Targets project (it's in the src/Targets solution folder) +* Run the OrchardCore.Cms.Web project (F5 or CTRL+F5) +* Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) + + +### Using Nuget packages + +* Open a web project that uses Orchard Core Nuget packages +* Add this project to the solution +* Add this project as a reference to web project +* Replace project references with Orchard Core Nuget package references with the same name as the project references +* Run the web project (F5 or CTRL+F5) +* Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) + + +## Using this module for training purposes + +If your module compiles and you are able to enable this module on the dashboard then head over to the **StartHere.txt** file and start exploring all the goodies you can do in Orchard Core. + +Also if you are brave enough to not follow any guide or you want to start the guide from somewhere else then go to the **Map.cs** file and jump to any class you are interested in. \ No newline at end of file From eb93d45d20f2cb2d7316a0eeb578336c2da58a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Sat, 1 Dec 2018 12:10:52 +0100 Subject: [PATCH 23/65] Adding contribution notes to Readme --HG-- branch : issue/OCORE-1 --- Readme.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 133fb0a6..5bbe6cad 100644 --- a/Readme.md +++ b/Readme.md @@ -37,4 +37,17 @@ You can use this module as part of a vanilla Orchard Core source that including If your module compiles and you are able to enable this module on the dashboard then head over to the **StartHere.txt** file and start exploring all the goodies you can do in Orchard Core. -Also if you are brave enough to not follow any guide or you want to start the guide from somewhere else then go to the **Map.cs** file and jump to any class you are interested in. \ No newline at end of file +Also if you are brave enough to not follow any guide or you want to start the guide from somewhere else then go to the **Map.cs** file and jump to any class you are interested in. + + +## Contribution and Feedback + +The module's source is available in two public source repositories, automatically mirrored in both directions with [Git-hg Mirror](https://githgmirror.com): + +- [https://bitbucket.org/Lombiq/orchard-training-demo-module](https://bitbucket.org/Lombiq/orchard-training-demo-module) (Mercurial repository) +- [https://github.com/Lombiq/Orchard-Training-Demo-Module](https://github.com/Lombiq/Orchard-Training-Demo-Module) (Git repository) + +Bug reports, feature requests and comments are warmly welcome, **please do so via GitHub**. +Feel free to send pull requests too, no matter which source repository you choose for this purpose. + +This project is developed by [Lombiq Technologies Ltd](https://lombiq.com/). Commercial-grade support is available through Lombiq. \ No newline at end of file From 709bbaf6e7814118a05014ea92803e46448748ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Mon, 3 Dec 2018 14:01:08 +0100 Subject: [PATCH 24/65] Code cleanup and small fixes --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 5 ++--- Controllers/YourFirstOrchardCoreController.cs | 1 - Drivers/ColorFieldDisplayDriver.cs | 4 ++-- Lombiq.TrainingDemo.csproj | 4 ++++ Migrations.cs | 2 +- Readme.md | 22 +++++++++---------- ResourceManifest.cs | 3 --- Startup.cs | 13 +++-------- 8 files changed, 23 insertions(+), 31 deletions(-) diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index e76e1b59..020c8ff1 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -6,12 +6,11 @@ * To demonstrate this basic functionality, we will create a page for displaying information about a book in two different pages. */ +using System.Threading.Tasks; using Lombiq.TrainingDemo.Models; -using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using OrchardCore.DisplayManagement; using OrchardCore.DisplayManagement.ModelBinding; -using System.Threading.Tasks; namespace Lombiq.TrainingDemo.Controllers { @@ -26,7 +25,7 @@ public class DisplayManagementController : Controller, IUpdateModel private readonly IDisplayManager _bookDisplayManager; - public DisplayManagementController(IHttpContextAccessor hca, IDisplayManager bookDisplayManager) + public DisplayManagementController(IDisplayManager bookDisplayManager) { _bookDisplayManager = bookDisplayManager; } diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index 207018cf..27b8c197 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -42,7 +42,6 @@ public ActionResult Index() => // This attribute will override the default route (see above) and use a custom one. This is also something that is an // ASP.NET Core MVC feature but this can be used on Orchard Core controllers as well. - [Route("TrainingDemo/NotifyMe")] public ActionResult NotifyMe() { _notifier.Information(H["Congratulations! You have been notified!"]); diff --git a/Drivers/ColorFieldDisplayDriver.cs b/Drivers/ColorFieldDisplayDriver.cs index ce2cdfb7..0dda9545 100644 --- a/Drivers/ColorFieldDisplayDriver.cs +++ b/Drivers/ColorFieldDisplayDriver.cs @@ -17,9 +17,9 @@ public class ColorFieldDisplayDriver : ContentFieldDisplayDriver public IStringLocalizer T { get; set; } - public ColorFieldDisplayDriver(IStringLocalizer localizer) + public ColorFieldDisplayDriver(IStringLocalizer stringLocalizer) { - T = localizer; + T = stringLocalizer; } diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index ba4b59f7..723be85c 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -20,6 +20,10 @@
+ + + + diff --git a/Migrations.cs b/Migrations.cs index 70cb0aed..15af08ef 100644 --- a/Migrations.cs +++ b/Migrations.cs @@ -34,7 +34,7 @@ public int Create() .WithDisplayName("Biography") .WithSettings(new TextFieldSettings { - Required = false + Hint = "Person's biography" }))); SchemaBuilder.CreateMapIndexTable(nameof(PersonPartIndex), table => table diff --git a/Readme.md b/Readme.md index 5bbe6cad..96f9725d 100644 --- a/Readme.md +++ b/Readme.md @@ -1,14 +1,14 @@ -# Orchard Core Training Demo module - - - -## Project Description - -Demo Orchard Core module for training purposes. - -**If you are interested in Orchard 1.x training materials and Orchard trainings please visit [Orchard Dojo](https://orcharddojo.net/).** - - +# Orchard Core Training Demo module + + + +## Project Description + +Demo Orchard Core module for training purposes. + +**If you are interested in Orchard 1.x training materials and Orchard trainings please visit [Orchard Dojo](https://orcharddojo.net/).** + + ## How to Start You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core Nuget packeges, however, it's harder to look under the hood of Orchard Core features. diff --git a/ResourceManifest.cs b/ResourceManifest.cs index 899b325b..06a4387f 100644 --- a/ResourceManifest.cs +++ b/ResourceManifest.cs @@ -1,6 +1,3 @@ -using System; -using System.Collections.Generic; -using System.Text; using OrchardCore.ResourceManagement; namespace Lombiq.TrainingDemo diff --git a/Startup.cs b/Startup.cs index 881aee62..4c7d8e44 100644 --- a/Startup.cs +++ b/Startup.cs @@ -60,18 +60,11 @@ public override void ConfigureServices(IServiceCollection services) public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider) { routes.MapAreaRoute( - name: "Home", + name: "TrainingDemo", areaName: "Lombiq.TrainingDemo", - template: "Home/Index", - defaults: new { controller = "Home", action = "Index" } + template: "TrainingDemo/NotifyMe", + defaults: new { controller = "YourFirstOrchardCore", action = "NotifyMe" } ); - - //routes.MapAreaRoute( - // name: "PersonList", - // areaName: "Lombiq.TrainingDemo", - // template: "Admin/PersonList", - // defaults: new { controller = "PersonListAdmin", action = "Index" } - //); } } } \ No newline at end of file From 78267c2d35a4fa347010c627d599ac99b5da4f14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Mon, 3 Dec 2018 16:50:18 +0100 Subject: [PATCH 25/65] Adding custom styling and updating Gulpfile.js --HG-- branch : issue/OCORE-1 --- Assets/Styles/trainingdemo-colorpicker.scss | 5 + Gulpfile.js | 43 +- Lombiq.TrainingDemo.csproj | 3 +- ResourceManifest.cs | 10 +- Views/ColorField-ColorPicker.Edit.cshtml | 35 +- package-lock.json | 3872 ++++++++++++++++++- package.json | 7 +- 7 files changed, 3838 insertions(+), 137 deletions(-) create mode 100644 Assets/Styles/trainingdemo-colorpicker.scss diff --git a/Assets/Styles/trainingdemo-colorpicker.scss b/Assets/Styles/trainingdemo-colorpicker.scss new file mode 100644 index 00000000..3815fece --- /dev/null +++ b/Assets/Styles/trainingdemo-colorpicker.scss @@ -0,0 +1,5 @@ +.colorField { + .pickr { + margin-top: 12px; + } +} diff --git a/Gulpfile.js b/Gulpfile.js index 4c61fb39..691d7620 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -1,21 +1,54 @@ const gulp = require("gulp"); +const sass = require("gulp-sass"); +const cssnano = require('gulp-cssnano'); +const rename = require("gulp-rename"); +const cached = require("gulp-cached"); +const watch = require("gulp-watch"); -const imageFiles = "Assets/Images/**/*"; -const imageFilesDestination = "wwwroot/Images"; +const imageFiles = "./Assets/Images/**/*"; +const imageFilesDestination = "./wwwroot/Images"; -const pickrFiles = "node_modules/pickr-widget/dist/*"; -const pickrFilesDestination = "wwwroot/pickr"; +const pickrFiles = "./node_modules/pickr-widget/dist/*"; +const pickrFilesDestination = "./wwwroot/Pickr"; + +const sassFiles = "./Assets/Styles/**/*.scss"; +const cssFiles = "./wwwroot/Styles/**/*.css"; +const stylingFilesDestination = "./wwwroot/Styles"; gulp.task("images", function () { return gulp .src(imageFiles) + .pipe(cached("images")) .pipe(gulp.dest(imageFilesDestination)); }); gulp.task("pickr", function () { return gulp .src(pickrFiles) + .pipe(cached("pickr")) .pipe(gulp.dest(pickrFilesDestination)); }); -gulp.task("default", ["images", "pickr"]); \ No newline at end of file +gulp.task("sass:compile", function (callback) { + gulp.src(sassFiles) + .pipe(cached("scss")) + .pipe(sass({ linefeed: "crlf" })).on("error", sass.logError) + .pipe(gulp.dest(stylingFilesDestination)) + .on("end", callback); +}); + +gulp.task("sass:minify", ["sass:compile"], function () { + return gulp.src(cssFiles) + .pipe(cached("css")) + .pipe(cssnano()) + .pipe(rename({ suffix: ".min" })) + .pipe(gulp.dest(stylingFilesDestination)); +}); + +gulp.task("default", ["images", "pickr", "sass:minify"]); + +gulp.task("sass:watch", function () { + watch(sassFiles, function () { + gulp.start("sass:minify"); + }); +}); \ No newline at end of file diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index 723be85c..a4473109 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -21,7 +21,8 @@ - + + diff --git a/ResourceManifest.cs b/ResourceManifest.cs index 06a4387f..35dc1a7d 100644 --- a/ResourceManifest.cs +++ b/ResourceManifest.cs @@ -10,11 +10,17 @@ public void BuildManifests(IResourceManifestBuilder builder) manifest .DefineScript("Pickr") - .SetUrl("/Lombiq.TrainingDemo/pickr/pickr.min.js"); + .SetUrl("/Lombiq.TrainingDemo/Pickr/pickr.min.js"); manifest .DefineStyle("Pickr") - .SetUrl("/Lombiq.TrainingDemo/pickr/pickr.min.css"); + .SetUrl("/Lombiq.TrainingDemo/Pickr/pickr.min.css"); + + manifest + .DefineStyle("Lombiq.TrainingDemo.ColorPicker") + .SetUrl("/Lombiq.TrainingDemo/Styles/trainingdemo-colorpicker.min.css", + "/Lombiq.TrainingDemo/Styles/trainingdemo-colorpicker.css") + .SetDependencies("Pickr"); } } } diff --git a/Views/ColorField-ColorPicker.Edit.cshtml b/Views/ColorField-ColorPicker.Edit.cshtml index d80a1fa6..4f047818 100644 --- a/Views/ColorField-ColorPicker.Edit.cshtml +++ b/Views/ColorField-ColorPicker.Edit.cshtml @@ -4,23 +4,27 @@ @{ var settings = Model.PartFieldDefinition.Settings.ToObject(); + + const string BlockName = "colorField"; + + var pickerInputElementId = Html.IdFor(m => m.Value); + var pickerElementId = $"{pickerInputElementId}-ColorPicker"; } - + -
- @Model.PartFieldDefinition.DisplayName() +
+ @Model.PartFieldDefinition.DisplayName() - - + + - -
- - @if (!String.IsNullOrEmpty(settings.Hint)) +
+ + @if (!string.IsNullOrEmpty(settings.Hint)) { - @settings.Hint + @settings.Hint }
@@ -28,25 +32,20 @@ // m.Value)-ColorPicker', - + el: "#@pickerElementId", default: '@Model.Value', - components: { - preview: true, opacity: true, hue: true, - interaction: { input: true, clear: true, save: true } }, - - onSave(hsva, instance) { - document.getElementById('@Html.IdFor(m => m.Value)').value = hsva ? hsva.toHEX().toString() : ""; + onSave(hsva) { + document.getElementById("@pickerInputElementId").value = hsva ? hsva.toHEX().toString() : ""; } }); })(); diff --git a/package-lock.json b/package-lock.json index 901fb54f..1d3d1add 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,6 +2,45 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "ajv": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.1.tgz", + "integrity": "sha512-ZoJjft5B+EJBjUyu9C9Hc0OZyPZSSlOF+plzouTrg6UlA8f+e/n8NIgBFG/9tppJtpPWfthHakK7juJdNDODww==", + "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" + } + }, + "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", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, "ansi-gray": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", @@ -29,12 +68,170 @@ "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.3" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -65,6 +262,12 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, "array-slice": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", @@ -83,18 +286,77 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "2.1.2" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, "assign-symbols": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "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.7", + "caniuse-db": "1.0.30000913", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", + "dev": true + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -156,12 +418,36 @@ } } }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, "beeper": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", "dev": true }, + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -201,6 +487,28 @@ } } }, + "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.30000913", + "electron-to-chromium": "1.3.87" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -218,6 +526,46 @@ "unset-value": "1.0.0" } }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "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.7.7", + "caniuse-db": "1.0.30000913", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" + } + }, + "caniuse-db": { + "version": "1.0.30000913", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000913.tgz", + "integrity": "sha512-+3qNxt3n8TaF+ZQOiRFPjP+OltDCJkHc7dSlMu1GlLu6sBnLPGLZMogNOlkI96+gft/Mn8u6Z10GMKVOxiBckQ==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, "chalk": { "version": "1.1.3", "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -231,6 +579,57 @@ "supports-color": "2.0.0" } }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.2", + "fsevents": "1.2.4", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "lodash.debounce": "4.0.8", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.2.1", + "upath": "1.1.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.10", + "normalize-path": "2.1.1" + } + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.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" + } + }, "class-utils": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", @@ -254,18 +653,93 @@ } } }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, "clone-stats": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", "dev": true }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "1.5.1" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -276,13 +750,74 @@ "object-visit": "1.0.1" } }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true + "color": { + "version": "0.11.4", + "resolved": "http://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "1.0.4", + "color-convert": "1.9.3", + "color-string": "0.3.0" + } }, - "component-emitter": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "0.3.0", + "resolved": "http://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "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.4", + "css-color-names": "0.0.4", + "has": "1.0.3" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "http://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", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "component-emitter": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", @@ -294,6 +829,12 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, "copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -306,6 +847,100 @@ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "4.1.5", + "which": "1.3.1" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + } + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "http://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "cssnano": { + "version": "3.10.0", + "resolved": "http://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "dev": true, + "requires": { + "autoprefixer": "6.7.7", + "decamelize": "1.2.0", + "defined": "1.0.0", + "has": "1.0.3", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-calc": "5.3.1", + "postcss-colormin": "2.2.2", + "postcss-convert-values": "2.6.1", + "postcss-discard-comments": "2.0.4", + "postcss-discard-duplicates": "2.1.0", + "postcss-discard-empty": "2.1.0", + "postcss-discard-overridden": "0.1.1", + "postcss-discard-unused": "2.2.3", + "postcss-filter-plugins": "2.0.3", + "postcss-merge-idents": "2.1.7", + "postcss-merge-longhand": "2.0.2", + "postcss-merge-rules": "2.1.2", + "postcss-minify-font-values": "1.0.5", + "postcss-minify-gradients": "1.0.5", + "postcss-minify-params": "1.2.2", + "postcss-minify-selectors": "2.1.1", + "postcss-normalize-charset": "1.1.1", + "postcss-normalize-url": "3.0.8", + "postcss-ordered-values": "2.2.3", + "postcss-reduce-idents": "2.4.0", + "postcss-reduce-initial": "1.0.1", + "postcss-reduce-transforms": "1.0.4", + "postcss-svgo": "2.1.6", + "postcss-unique-selectors": "2.0.2", + "postcss-value-parser": "3.3.1", + "postcss-zindex": "2.2.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "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.2" + } + }, + "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" + } + }, "dateformat": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", @@ -321,6 +956,12 @@ "ms": "2.0.0" } }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -377,6 +1018,24 @@ } } }, + "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", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, "deprecated": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", @@ -398,6 +1057,22 @@ "readable-stream": "1.1.14" } }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "0.1.1", + "safer-buffer": "2.1.2" + } + }, + "electron-to-chromium": { + "version": "1.3.87", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.87.tgz", + "integrity": "sha512-EV5FZ68Hu+n9fHVhOc9AcG3Lvf+E1YqR36ulJUpwaQTkf4LwdvBqmGIazaIrt4kt6J8Gw3Kv7r9F+PQjAkjWeA==", + "dev": true + }, "end-of-stream": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", @@ -407,12 +1082,27 @@ "once": "1.3.3" } }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -448,6 +1138,63 @@ } } }, + "expand-range": { + "version": "1.8.2", + "resolved": "http://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.4" + }, + "dependencies": { + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "3.1.1", + "repeat-element": "1.1.3", + "repeat-string": "1.6.1" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, "expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", @@ -549,6 +1296,12 @@ } } }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, "fancy-log": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", @@ -561,6 +1314,24 @@ "time-stamp": "1.1.0" } }, + "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 + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", @@ -590,6 +1361,16 @@ "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", "dev": true }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, "findup-sync": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", @@ -627,6 +1408,12 @@ "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", "dev": true }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -642,6 +1429,23 @@ "for-in": "1.0.2" } }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.7", + "mime-types": "2.1.21" + } + }, "fragment-cache": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", @@ -651,75 +1455,727 @@ "map-cache": "0.2.2" } }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.3.3" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "dev": true, + "optional": true, "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" + "nan": "2.11.1", + "node-pre-gyp": "0.10.0" }, "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, "dev": true, + "optional": true, "requires": { - "core-util-is": "1.0.2", + "delegates": "1.0.0", + "readable-stream": "2.3.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, - "through2": { - "version": "0.6.5", - "resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, "dev": true, + "optional": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "safer-buffer": "2.1.2" } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "http://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "2.2.4" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.9", + "iconv-lite": "0.4.21", + "sax": "1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.3", + "mkdirp": "0.5.1", + "needle": "2.2.0", + "nopt": "4.0.1", + "npm-packlist": "1.1.10", + "npmlog": "4.1.2", + "rc": "1.2.7", + "rimraf": "2.6.2", + "semver": "5.5.0", + "tar": "4.4.1" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.5" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "3.0.1", + "npm-bundled": "1.0.3" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.5.1", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "1.0.1", + "fs-minipass": "1.2.5", + "minipass": "2.2.4", + "minizlib": "1.1.0", + "mkdirp": "0.5.1", + "safe-buffer": "5.1.1", + "yallist": "3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + }, + "dependencies": { + "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 + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.3" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.3.3" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "http://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { "gaze": "0.5.2" @@ -843,6 +2299,111 @@ "vinyl-fs": "0.3.14" } }, + "gulp-cached": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gulp-cached/-/gulp-cached-1.1.1.tgz", + "integrity": "sha1-/nzU+H83YB5gc8/t7lwr2vi2rM4=", + "dev": true, + "requires": { + "lodash.defaults": "4.2.0", + "through2": "2.0.5" + } + }, + "gulp-cssnano": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/gulp-cssnano/-/gulp-cssnano-2.1.3.tgz", + "integrity": "sha512-r8qdX5pTXsBb/IRm9loE8Ijz8UiPW/URMC/bKJe4FPNHRaz4aEx8Bev03L0FYHd/7BSGu/ebmfumAkpGuTdenA==", + "dev": true, + "requires": { + "buffer-from": "1.1.1", + "cssnano": "3.10.0", + "object-assign": "4.1.1", + "plugin-error": "1.0.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "gulp-rename": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz", + "integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==", + "dev": true + }, + "gulp-sass": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-4.0.2.tgz", + "integrity": "sha512-q8psj4+aDrblJMMtRxihNBdovfzGrXJp1l4JU0Sz4b/Mhsi2DPrKFYCGDwjIWRENs04ELVHxdOJQ7Vs98OFohg==", + "dev": true, + "requires": { + "chalk": "2.4.1", + "lodash.clonedeep": "4.5.0", + "node-sass": "4.10.0", + "plugin-error": "1.0.1", + "replace-ext": "1.0.0", + "strip-ansi": "4.0.0", + "through2": "2.0.5", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "1.9.3" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.5.0" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "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" + } + } + } + }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", @@ -869,13 +2430,139 @@ "vinyl": "0.5.3" } }, + "gulp-watch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/gulp-watch/-/gulp-watch-5.0.1.tgz", + "integrity": "sha512-HnTSBdzAOFIT4wmXYPDUn783TaYAq9bpaN05vuZNP5eni3z3aRx0NAKbjhhMYtcq76x4R1wf4oORDGdlrEjuog==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "anymatch": "1.3.2", + "chokidar": "2.0.4", + "fancy-log": "1.3.2", + "glob-parent": "3.1.0", + "object-assign": "4.1.1", + "path-is-absolute": "1.0.1", + "plugin-error": "1.0.1", + "readable-stream": "2.3.6", + "slash": "1.0.0", + "vinyl": "2.2.0", + "vinyl-file": "2.0.0" + }, + "dependencies": { + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "vinyl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", + "dev": true, + "requires": { + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" + } + } + } + }, "gulplog": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.1" + "glogg": "1.0.1" + } + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "dev": true, + "requires": { + "ajv": "6.6.1", + "har-schema": "2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "1.1.1" } }, "has-ansi": { @@ -887,6 +2574,12 @@ "ansi-regex": "2.1.1" } }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, "has-gulplog": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", @@ -896,6 +2589,12 @@ "sparkles": "1.0.1" } }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -937,6 +2636,50 @@ "parse-passwd": "1.0.0" } }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "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", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.15.2" + } + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -965,6 +2708,12 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, "is-absolute": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", @@ -975,6 +2724,12 @@ "is-windows": "1.0.2" } }, + "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", @@ -995,12 +2750,36 @@ } } }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.12.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -1040,6 +2819,21 @@ } } }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -1052,6 +2846,24 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", @@ -1081,6 +2893,12 @@ } } }, + "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", @@ -1090,6 +2908,18 @@ "isobject": "3.0.1" } }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -1099,6 +2929,21 @@ "is-unc-path": "1.0.0" } }, + "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.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -1138,12 +2983,79 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-base64": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.9.tgz", + "integrity": "sha512-xcinL3AuDJk7VSzsHgb9DvvIXayBbadtMZ4HFPx8rUszbW1MuNMlwYVC4zzCZ6e1sqZpnNS5ZFYOhXqA39T7LQ==", + "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=", + "dev": true, + "requires": { + "argparse": "1.0.10", + "esprima": "2.7.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "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 + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, "liftoff": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", @@ -1160,6 +3072,36 @@ "resolve": "1.8.1" } }, + "load-json-file": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "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 + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, "lodash": { "version": "1.0.2", "resolved": "http://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", @@ -1220,6 +3162,30 @@ "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", "dev": true }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, "lodash.escape": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", @@ -1252,6 +3218,18 @@ "lodash.isarray": "3.0.4" } }, + "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", + "integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==", + "dev": true + }, "lodash.restparam": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", @@ -1285,6 +3263,22 @@ "lodash.escape": "3.2.0" } }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, "lru-cache": { "version": "2.7.3", "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", @@ -1306,6 +3300,12 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, "map-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", @@ -1315,6 +3315,44 @@ "object-visit": "1.0.1" } }, + "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", + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true + }, + "meow": { + "version": "3.7.0", + "resolved": "http://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -1336,6 +3374,21 @@ "to-regex": "3.0.2" } }, + "mime-db": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==", + "dev": true + }, + "mime-types": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", + "dev": true, + "requires": { + "mime-db": "1.37.0" + } + }, "minimatch": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", @@ -1404,6 +3457,12 @@ "duplexer2": "0.0.2" } }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "dev": true + }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -1423,10 +3482,231 @@ "to-regex": "3.0.2" } }, - "natives": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", - "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "dev": true + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "dev": true, + "requires": { + "fstream": "1.0.11", + "glob": "7.1.3", + "graceful-fs": "4.1.15", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.5", + "request": "2.88.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.1" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } + }, + "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 + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "node-sass": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.10.0.tgz", + "integrity": "sha512-fDQJfXszw6vek63Fe/ldkYXmRYK/QS6NbvM3i5oEo9ntPDy4XX7BcKZyTKv+/kSSxRtXXc7l+MSwEmYc0CSy6Q==", + "dev": true, + "requires": { + "async-foreach": "0.1.3", + "chalk": "1.1.3", + "cross-spawn": "3.0.1", + "gaze": "1.1.3", + "get-stdin": "4.0.1", + "glob": "7.1.3", + "in-publish": "2.0.0", + "lodash.assign": "4.2.0", + "lodash.clonedeep": "4.5.0", + "lodash.mergewith": "4.6.1", + "meow": "3.7.0", + "mkdirp": "0.5.1", + "nan": "2.11.1", + "node-gyp": "3.8.0", + "npmlog": "4.1.2", + "request": "2.88.0", + "sass-graph": "2.2.4", + "stdout-stream": "1.4.1", + "true-case-path": "1.0.3" + }, + "dependencies": { + "gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "requires": { + "globule": "1.2.1" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } + }, + "globule": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz", + "integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==", + "dev": true, + "requires": { + "glob": "7.1.3", + "lodash": "4.17.11", + "minimatch": "3.0.4" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.7.1", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.4" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "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.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.5", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, "object-assign": { @@ -1497,6 +3777,27 @@ "make-iterator": "1.0.1" } }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + }, + "dependencies": { + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + } + } + }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -1538,65 +3839,539 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "dev": true, + "requires": { + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + }, + "dependencies": { + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + } + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.2" + } + }, + "parse-node-version": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", + "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", + "dev": true + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "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 + } + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pickr-widget": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/pickr-widget/-/pickr-widget-0.3.2.tgz", + "integrity": "sha512-ysOy+fJFOFuU+/vYQfkDqBRY9s4msUtGS3nDFFycPMHd3BEqG6TP0IyuiMfGbMqWcK78xR5CBYmX0Gs6IRE4bg==" + }, + "pify": { + "version": "2.3.0", + "resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", + "dev": true, + "requires": { + "ansi-colors": "1.1.0", + "arr-diff": "4.0.0", + "arr-union": "3.1.0", + "extend-shallow": "3.0.2" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "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.4.9", + "source-map": "0.5.7", + "supports-color": "3.2.3" + }, + "dependencies": { + "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 + }, + "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-calc": { + "version": "5.3.1", + "resolved": "http://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.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.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "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.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "http://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "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.2.18" + } + }, + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "http://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "http://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "uniqs": "2.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.2.18" + } + }, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "http://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "dev": true, + "requires": { + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "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.2.18" + } + }, + "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.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.2" + } + }, + "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": "http://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "http://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "http://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1", + "uniqs": "2.0.0" + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "http://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.3", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "http://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.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "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.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "http://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" + "postcss": "5.2.18" } }, - "parse-node-version": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.0.tgz", - "integrity": "sha512-02GTVHD1u0nWc20n2G7WX/PgdhNFG04j5fi1OkaJzPWLTcf6vh6229Lta1wTmXG/7Dg42tCssgkccVt7qvd8Kg==", - "dev": true + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "http://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "dev": true, + "requires": { + "has": "1.0.3", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1" + } }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true + "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" + } }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true + "postcss-svgo": { + "version": "2.1.6", + "resolved": "http://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "dev": true, + "requires": { + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.1", + "svgo": "0.7.2" + } }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "http://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "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 }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "postcss-zindex": { + "version": "2.2.0", + "resolved": "http://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { - "path-root-regex": "0.1.2" + "has": "1.0.3", + "postcss": "5.2.18", + "uniqs": "2.0.0" } }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "pickr-widget": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/pickr-widget/-/pickr-widget-0.3.2.tgz", - "integrity": "sha512-ysOy+fJFOFuU+/vYQfkDqBRY9s4msUtGS3nDFFycPMHd3BEqG6TP0IyuiMfGbMqWcK78xR5CBYmX0Gs6IRE4bg==" - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, "pretty-hrtime": { @@ -1611,6 +4386,94 @@ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "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.1", + "strict-uri-encode": "1.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "requires": { + "is-number": "4.0.0", + "kind-of": "6.0.2", + "math-random": "1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, "readable-stream": { "version": "1.1.14", "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", @@ -1623,6 +4486,55 @@ "string_decoder": "0.10.31" } }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "micromatch": "3.1.10", + "readable-stream": "2.3.6" + }, + "dependencies": { + "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 + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", @@ -1632,6 +4544,61 @@ "resolve": "1.8.1" } }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "http://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.17", + "reduce-function-call": "1.0.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 + } + } + }, + "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 + } + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -1642,6 +4609,12 @@ "safe-regex": "1.1.0" } }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, "repeat-element": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", @@ -1654,12 +4627,61 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, "replace-ext": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", "dev": true }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "dev": true, + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.8.0", + "caseless": "0.12.0", + "combined-stream": "1.0.7", + "extend": "3.0.2", + "forever-agent": "0.6.1", + "form-data": "2.3.3", + "har-validator": "5.1.3", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.21", + "oauth-sign": "0.9.0", + "performance-now": "2.1.0", + "qs": "6.5.2", + "safe-buffer": "5.1.2", + "tough-cookie": "2.4.3", + "tunnel-agent": "0.6.0", + "uuid": "3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "resolve": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", @@ -1691,6 +4713,40 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -1706,6 +4762,82 @@ "ret": "0.1.15" } }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "requires": { + "glob": "7.1.3", + "lodash": "4.17.11", + "scss-tokenizer": "0.2.3", + "yargs": "7.1.0" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "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 + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "2.4.9", + "source-map": "0.4.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "http://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, "semver": { "version": "4.3.6", "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.6.tgz", @@ -1718,6 +4850,12 @@ "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", "dev": true }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, "set-value": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", @@ -1747,6 +4885,18 @@ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", "dev": true }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -1854,6 +5004,15 @@ } } }, + "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.1.0" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -1885,6 +5044,38 @@ "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", "dev": true }, + "spdx-correct": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "dev": true, + "requires": { + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.2" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "2.2.0", + "spdx-license-ids": "3.0.2" + } + }, + "spdx-license-ids": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", + "dev": true + }, "split-string": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", @@ -1894,6 +5085,29 @@ "extend-shallow": "3.0.2" } }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", + "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", + "dev": true, + "requires": { + "asn1": "0.2.4", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.2", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.2", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "safer-buffer": "2.1.2", + "tweetnacl": "0.14.5" + } + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -1915,12 +5129,70 @@ } } }, + "stdout-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", + "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + } + } + }, "stream-consume": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==", "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", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, "string_decoder": { "version": "0.10.31", "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -1946,12 +5218,119 @@ "is-utf8": "0.2.1" } }, + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", + "dev": true, + "requires": { + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" + }, + "dependencies": { + "first-chunk-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "dev": true, + "requires": { + "readable-stream": "2.3.6" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, "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 }, + "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.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" + }, + "dependencies": { + "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.2.3", + "source-map": "0.5.7" + } + } + } + }, + "tar": { + "version": "2.2.1", + "resolved": "http://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -2051,6 +5430,79 @@ "repeat-string": "1.6.1" } }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "dev": true, + "requires": { + "psl": "1.1.29", + "punycode": "1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", + "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", + "dev": true, + "requires": { + "glob": "7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.3.3", + "path-is-absolute": "1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, "unc-path-regex": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", @@ -2092,6 +5544,18 @@ } } }, + "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-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", @@ -2144,6 +5608,21 @@ } } }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "2.1.1" + } + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", @@ -2168,6 +5647,12 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "dev": true + }, "v8flags": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", @@ -2177,6 +5662,33 @@ "user-home": "1.1.1" } }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "3.0.2", + "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", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, "vinyl": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", @@ -2188,6 +5700,48 @@ "replace-ext": "0.0.1" } }, + "vinyl-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-2.0.0.tgz", + "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", + "dev": true, + "requires": { + "graceful-fs": "4.1.15", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "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 + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.4", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, "vinyl-fs": { "version": "0.3.14", "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", @@ -2244,6 +5798,21 @@ } } }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "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", @@ -2253,6 +5822,31 @@ "isexe": "2.0.0" } }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2264,6 +5858,64 @@ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.3", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } } } } diff --git a/package.json b/package.json index 00f52f94..d09a066a 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,11 @@ "pickr-widget": "^0.3.2" }, "devDependencies": { - "gulp": "^3.9.1" + "gulp": "^3.9.1", + "gulp-cached": "^1.1.1", + "gulp-cssnano": "^2.1.3", + "gulp-rename": "^1.4.0", + "gulp-sass": "^4.0.2", + "gulp-watch": "^5.0.1" } } From 15522d37471a9381b3b6ded1c7062257b5e8fb71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Mon, 10 Dec 2018 23:39:03 +0100 Subject: [PATCH 26/65] Typos --HG-- branch : issue/OCORE-1 --- Controllers/YourFirstOrchardCoreController.cs | 7 +++---- Manifest.cs | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index 27b8c197..7df45d44 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -34,10 +34,9 @@ public YourFirstOrchardCoreController( public ActionResult Index() => // For now we just return an empty view. This action is accessible from under - // Lombiq.TraningDemo/YourFirstOrchard/Index route (appended to your site's root path; so using defaults it - // would look something like this: - // http://localhost:44300/Lombiq.TraningDemo/YourFirstOrchardCore/Index) If you don't know how this - // path gets together take a second look at how ASP.NET Core MVC routing works! + // Lombiq.TrainingDemo/YourFirstOrchardCore/Index route (appended to your site's root path; so using defaults + // it would look something like this: https://localhost:44300/Lombiq.TrainingDemo/YourFirstOrchardCore/Index). + // If you don't know how this path gets together take a second look at how ASP.NET Core MVC routing works! View(new { Message = T["Hello you!"] }); // This attribute will override the default route (see above) and use a custom one. This is also something that is an diff --git a/Manifest.cs b/Manifest.cs index 22c78d7a..35a425e6 100644 --- a/Manifest.cs +++ b/Manifest.cs @@ -5,14 +5,14 @@ Name = "Orchard Core Training Demo", // Your name, company or any name that identifies the developers working on the project. Author = "Lombiq", - // Optionally you can add a website URL (e.g. your company's website, GitHub reporitory URL). + // Optionally you can add a website URL (e.g. your company's website, GitHub repository URL). Website = "http://orchardproject.net", // Version of the module. Version = "2.0", - // Short description of the module. It will be displayed on the the Dashboard. + // Short description of the module. It will be displayed on the Dashboard. Description = "Orchard Core training demo module for teaching Orchard Core fundamentals primarily by going " + "through its source code.", - // Modules are categorized on the Dashboard so it's a good idea to put similar modules together to a separate + // Modules are categorized on the Dashboard so it's a good idea to put similar modules together into a separate // section. Category = "Training", // Modules can have dependencies which are other module names (name of the project) or if these modules have From 78fcce61cd77e1dd8890dadc1112b6255552290c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 13 Dec 2018 13:35:58 +0100 Subject: [PATCH 27/65] Commenting YourFirstOrchardCoreController --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 20 +++---- Controllers/YourFirstOrchardCoreController.cs | 44 +++++++++----- Drivers/BookDisplayDriver.cs | 41 +++++++------ Map.cs | 2 +- StartHere.txt | 54 ----------------- StartLearningHere.md | 59 +++++++++++++++++++ 6 files changed, 121 insertions(+), 99 deletions(-) delete mode 100644 StartHere.txt create mode 100644 StartLearningHere.md diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index 020c8ff1..5497602c 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -14,10 +14,10 @@ namespace Lombiq.TrainingDemo.Controllers { - // Notice, that the controller implements the IUpdateModel interface. This interface encapsulates all the properties and - // methods related to ASP.NET Core MVC model binding which is already there in the Controller object so further - // implementations are not required. Orchard Core needs this model binding functionality outside the controllers (you will - // see it later). + // Notice, that the controller implements the IUpdateModel interface. This interface encapsulates all the properties + // and methods related to ASP.NET Core MVC model binding which is already there in the Controller object so further + // implementations are not required. Orchard Core needs this model binding functionality outside the controllers (you + // will see it later). public class DisplayManagementController : Controller, IUpdateModel { // For display management functionality we can use the IDisplayManager service where the T generic parameter is the @@ -30,29 +30,29 @@ public DisplayManagementController(IDisplayManager bookDisplayManager) _bookDisplayManager = bookDisplayManager; } - + // First, let's see how the book summary page is generated. public async Task DisplayBook() { // Since we don't store the book object in the database let's create one for demonstration purposes. var book = CreateDemoBook(); - // Here the shape is generated. Before going any further let's dig deeper and see what happens when this method - // is called. + // Here the shape is generated. Before going any further let's dig deeper and see what happens when this + // method is called. var shape = await _bookDisplayManager.BuildDisplayAsync(book, this); // NEXT STATION: Go to Views/DisplayManagement/DisplayBook.cshtml. return View(shape); } - + // Let's generate another Book display shape, but now with a display type. public async Task DisplayBookDescription() { // Generate another book object to be used for demonstration purposes. var book = CreateDemoBook(); - // We can add a display type when we generate display shape. This time it will be Description. - // If display type is given then Orchard Core will search a cshtml file with a name [ObjectName].[DisplayType].cshtml. + // We can add a display type when we generate display shape. This time it will be Description. If display + // type is given then Orchard Core will search a cshtml file with a name [ObjectName].[DisplayType].cshtml. // NEXT STATION: Go to Views/Book.Description.cshtml var shape = await _bookDisplayManager.BuildDisplayAsync(book, this, "Description"); diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index 7df45d44..db49012f 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -1,14 +1,17 @@ /* - * This is a controller you can find in any ASP.NET Core MVC application; Orchard is an MVC application, although much-much more - * than that. - * - * An Orchard module is basically an MVC area. You could create areas that don't interact with Orchard and you'd just use standard - * ASP.NET Core MVC skills. Of course we want more than that, so let's take a closer look. + * This is a controller you can find in any ASP.NET Core MVC application; Orchard is an MVC application, although + * much-much more than that. + * + * An Orchard module is basically an MVC area. You could create areas that don't interact with Orchard and you'd just + * use standard ASP.NET Core MVC skills. Of course we want more than that, so let's take a closer look. + * + * Here you will see how to use some simple ASP.NET Core and Orchard Core services. */ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Localization; using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; using OrchardCore.DisplayManagement.Notify; namespace Lombiq.TrainingDemo.Controllers @@ -18,32 +21,44 @@ public class YourFirstOrchardCoreController : Controller private readonly INotifier _notifier; private readonly IStringLocalizer T; private readonly IHtmlLocalizer H; + private readonly ILogger _logger; public YourFirstOrchardCoreController( INotifier notifier, IStringLocalizer stringLocalizer, - IHtmlLocalizer htmlLocalizer) + IHtmlLocalizer htmlLocalizer, + ILogger logger) { _notifier = notifier; + _logger = logger; T = stringLocalizer; H = htmlLocalizer; } + // Here's a simple action that will return some message. Nothing special here just demonstrates that this will work + // in Orchard Core right after enabling the module. The route for this action will be + // /Lombiq.TrainingDemo/YourFirstOrchardCore/Index. public ActionResult Index() => - // For now we just return an empty view. This action is accessible from under - // Lombiq.TrainingDemo/YourFirstOrchardCore/Index route (appended to your site's root path; so using defaults - // it would look something like this: https://localhost:44300/Lombiq.TrainingDemo/YourFirstOrchardCore/Index). - // If you don't know how this path gets together take a second look at how ASP.NET Core MVC routing works! + // Simple texts can be localized using the IStringLocalizer service as you can see below. View(new { Message = T["Hello you!"] }); - // This attribute will override the default route (see above) and use a custom one. This is also something that is an - // ASP.NET Core MVC feature but this can be used on Orchard Core controllers as well. + // Let's see some custom routing here. This attribute will override the default route and use this one. + [Route("TrainingDemo/NotifyMe")] public ActionResult NotifyMe() { - _notifier.Information(H["Congratulations! You have been notified!"]); + // ILogger is an ASP.NET Core service that will write something in the specific log files. In Orchard Core + // NLog is used for logging and the error level is "Error" by default. You can find the error log in the + // /App_Data/logs/orchard-log-[date].log file. Logger can be configured in the NLog.config file in the web + // project (e.g. OrchardCore.Cms.Web). + _logger.LogError("You have been notified about some error!"); + + // INotifier is an Orchard Core service to send messages to the user. This service can be used almost + // everywhere in the code base not only in Controllers. This service requires a LocalizedHtmlString object + // so the IHtmlLocalizer service needs to be used for localization. + _notifier.Information(H["Congratulations! You have been notified! Check the error log too!"]); return View(); } @@ -51,6 +66,5 @@ public ActionResult NotifyMe() } /* - * If you've finished with both actions (and their .cshtml files as well), then - * NEXT STATION: Controllers/BasicOrchardCoreServicesController is what's next. + * NEXT STATION: Controllers/DisplayManagementController */ diff --git a/Drivers/BookDisplayDriver.cs b/Drivers/BookDisplayDriver.cs index e22c0f22..89eb7d24 100644 --- a/Drivers/BookDisplayDriver.cs +++ b/Drivers/BookDisplayDriver.cs @@ -4,24 +4,26 @@ namespace Lombiq.TrainingDemo.Drivers { - // A DisplayDriver is an abstraction over all the functionality for displaying or editing a specific object that is usually - // done in the Controllers. You can create a driver for any object or contents (i.e. ContentParts or ContentFields) where - // you can implement their very specific logic for generating reusable shapes or validating them after model binding. - // Furthermore, you can create multiple drivers for one object where all the driver methods will be executed even if the - // original driver is implemented in another (e.g. Orchard Core) module. + // A DisplayDriver is an abstraction over all the functionality for displaying or editing a specific object that is + // usually done in the Controllers. You can create a driver for any object or contents (i.e. ContentParts or + // ContentFields) where you can implement their very specific logic for generating reusable shapes or validating + // them after model binding. Furthermore, you can create multiple drivers for one object where all the driver + // methods will be executed even if the original driver is implemented in another (e.g. Orchard Core) module. public class BookDisplayDriver : DisplayDriver { - // This method gets called when building the display shape of object. If you need to call async methods here you can - // override DisplayAsync instead of this. Please note, that only one can be used since if the DisplayAsync is not - // overriden then it will be called asynchronously - either way, it will be async. + // This method gets called when building the display shape of object. If you need to call async methods here + // you can override DisplayAsync instead of this. Please note, that only one can be used since if the + // DisplayAsync is not overriden then it will be called asynchronously - either way, it will be async. public override IDisplayResult Display(Book model) => - // For the sake of demonstration we use Combined() here. It makes it possible to return multiple shapes from - // a driver method. Use this if you'd like to return different shapes that can be used e.g. with different - // display types or you need to display specific shapes in different zones. Zones will be described later. + // For the sake of demonstration we use Combined() here. It makes it possible to return multiple shapes + // from a driver method. Use this if you'd like to return different shapes that can be used e.g. with + // different display types or you need to display specific shapes in different zones. Zones will be + // described later. Combine( - // Here we define a shape for the Title. The shapeType parameter will also define the default file name that - // will contain the actual markup. For this one it will be Book.Display.Title.cshtml which is located in the - // Views/Items folder. This shape will be placed in the first position of the Header zone. + // Here we define a shape for the Title. The shapeType parameter will also define the default file name + // that will contain the actual markup. For this one it will be Book.Display.Title.cshtml which is + // located in the Views/Items folder. This shape will be placed in the first position of the Header + // zone. View("Book_Display_Title", model) .Location("Header: 1"), // Same applies here. This shape will be displayed in the Header zone too but in the second position. @@ -31,13 +33,14 @@ public override IDisplayResult Display(Book model) => // The cover photo will be in a different zone. View("Book_Display_Cover", model) .Location("Cover: 1"), - // The description, however, won't be displayed by default because its location targets a different display type. - // Note, that the previous shapes had no display type parameter so those will be displayed in every display type. - // This one will be displayed in the first position of the Content zone if the Book display shape will be - // generated with the Description display type. + // The description, however, won't be displayed by default because its location targets a different + // display type. Note, that the previous shapes had no display type parameter so those will be + // displayed in every display type. This one will be displayed in the first position of the Content + // zone if the Book display shape will be generated with the Description display type. View("Book_Display_Description", model) .Location("Description", "Content: 1")); - // NEXT STATION: Now let's see what are those zones and how these shapes will come together! Go to Views/Book.cshtml. + // NEXT STATION: Now let's see what are those zones and how these shapes will come together! Go to + // Views/Book.cshtml. } } diff --git a/Map.cs b/Map.cs index 9ef11313..b487ad08 100644 --- a/Map.cs +++ b/Map.cs @@ -32,7 +32,7 @@ private static void Treasure() // Views/PersonListDashboard - // Basic controller demonstrating localization, Notifier, routing + // Basic controller demonstrating localization, Notifier, Logger, routing Factory(); diff --git a/StartHere.txt b/StartHere.txt deleted file mode 100644 index 42a386df..00000000 --- a/StartHere.txt +++ /dev/null @@ -1,54 +0,0 @@ -Hi there! - - -Good to see you want to learn the ins and outs of Orchard Core module creation. Reading code is always a good way for this! - -We'll guide you on your journey to become an Orchard Core developer. Look for "NEXT STATION" comments in the code to see where -to head next, otherwise look throught the code as you like. - -Before you dive deep into this module it'd be best if you made sure that you have done the following: -* You know how ASP.NET Core works. It's important that you understand how ASP.NET Core works or - generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at - https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. -* You've read through the documentation at https://orchardcore.readthedocs.io (at least the "About Orchard Core" section, - but it would be great if you'd read the whole documentation). -* You know Orchard Core from a user's perspecive and understand the concepts underlying the system. -* If you want to be more familiar with Orchard Core fundamentals you can watch some of the following video about the - beta2 capabalities here: https://www.youtube.com/watch?v=6ZaqWmq8Pog or simply pick some of the interesting Orchard CMS - podcasts from this YouTube playlist: https://www.youtube.com/watch?v=Xu6S2XawyY4&list=PLuskKJW0FhJfOAN3dL0Y0KBMdG1pKESVn - -We've invested a lot of time creating this module. If you have ideas regarding it or have found mistakes, please let us -know on the project page: https://github.com/Lombiq/Orchard-Training-Demo-Module - -If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at Orchard -Dojo's trainings: https://orcharddojo.net/orchard-training - -Although the module has no function apart from serving as a demonstration we've written everything in a way that it really -runs and you can try it out in action. There are two ways of creating Orchard Core applications and trying out this module. -The recommended way to try this module out is to grab the full OrchardCore source and copy this module to the -src/OrchardCore.Modules folder and add it to the Solution file. The second way is to create a an Orchard Core ASP.NET Web -Application (simply follow the instructions in the Code Generation Templates section of the documentation) and adding the -Lombiq.TrainingDemo project as reference to it. If you go with the second way you need to replace project references to NuGet -package references. Don't forget to run the solution in Debug mode and break into the code to be able to look into some -specific details! - -After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules -how they solve similar tasks. If you chose to use the simpler way to add this project to Orchard Core then you should try the -other way as well to have the whole Orchard source at your hands: let it be your tutor :-). - -Later on, you may want to take a look at Map.cs (remember, "X marks the spot!") in the project root for -reminders regarding specific solutions. - ---- - -FIRST STATION: First of all, let's discuss how a .NET Standard library becomes an Orchard Module. If you look into the -Dependencies of this project you will find either a NuGet reference for the OrchardCore.Module.Targets package or if you go with -the full Orchard Core source code way you can add this particular project as a Project reference. - -On the other hand the module manifest file is also required. So... - -NEXT STATION: Head over to Manifest.cs. That file is the module's manifest; a Manifest.cs is required for Orchard modules. - - -This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session (http://www.youtube.com/watch?v=MH9mcodTX-U) -and brought to you by the Orchard Hungary team (http://english.orchardproject.hu/) and Lombiq (https://lombiq.com/). \ No newline at end of file diff --git a/StartLearningHere.md b/StartLearningHere.md new file mode 100644 index 00000000..772d46cf --- /dev/null +++ b/StartLearningHere.md @@ -0,0 +1,59 @@ +Hi there! + + +Good to see you want to learn the ins and outs of Orchard Core module creation. Reading code is always a good way for +this! + +We'll guide you on your journey to become an Orchard Core developer. Look for "NEXT STATION" comments in the code to +see where to head next, otherwise look throught the code as you like. + +Before you dive deep into this module it'd be best if you made sure that you have done the following: * You know how +ASP.NET Core works. It's important that you understand how ASP.NET Core works or + generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at + https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. +* You've read through the documentation at https://orchardcore.readthedocs.io (at least the "About Orchard Core" +section, + but it would be great if you'd read the whole documentation). +* You know Orchard Core from a user's perspecive and understand the concepts underlying the system. * If you want to be +more familiar with Orchard Core fundamentals you can watch some of the following video about the + beta2 capabalities here: https://www.youtube.com/watch?v=6ZaqWmq8Pog or simply pick some of the interesting Orchard + CMS podcasts from this YouTube playlist: + https://www.youtube.com/watch?v=Xu6S2XawyY4&list=PLuskKJW0FhJfOAN3dL0Y0KBMdG1pKESVn + +We've invested a lot of time creating this module. If you have ideas regarding it or have found mistakes, please let us +know on the project page: https://github.com/Lombiq/Orchard-Training-Demo-Module + +If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at +Orchard Dojo's trainings: https://orcharddojo.net/orchard-training + +Although the module has no function apart from serving as a demonstration we've written everything in a way that it +really runs and you can try it out in action. There are two ways of creating Orchard Core applications and trying out +this module. The recommended way to try this module out is to grab the full OrchardCore source and copy this module to +the src/OrchardCore.Modules folder and add it to the Solution file. The second way is to create a an Orchard Core +ASP.NET Web Application (simply follow the instructions in the Code Generation Templates section of the documentation) +and adding the Lombiq.TrainingDemo project as reference to it. If you go with the second way you need to replace +project references to NuGet package references. Don't forget to run the solution in Debug mode and break into the code +to be able to look into some specific details! + +After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules +how they solve similar tasks. If you chose to use the simpler way to add this project to Orchard Core then you should +try the other way as well to have the whole Orchard source at your hands: let it be your tutor :-). + +Later on, you may want to take a look at Map.cs (remember, "X marks the spot!") in the project root for reminders +regarding specific solutions. + +--- + +FIRST STATION: First of all, let's discuss how a .NET Standard library becomes an Orchard Module. If you look into the +Dependencies of this project you will find either a NuGet reference for the OrchardCore.Module.Targets package or if +you go with the full Orchard Core source code way you can add this particular project as a Project reference. + +On the other hand the module manifest file is also required. So... + +NEXT STATION: Head over to Manifest.cs. That file is the module's manifest; a Manifest.cs is required for Orchard +modules. + + +This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session +(http://www.youtube.com/watch?v=MH9mcodTX-U) and brought to you by the Orchard Hungary team +(http://english.orchardproject.hu/) and Lombiq (https://lombiq.com/). \ No newline at end of file From 5ff803b7f69c97b794805990e5faf1788c6fd4ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Fri, 4 Jan 2019 13:49:26 +0100 Subject: [PATCH 28/65] Adding demo for storing items that are not content items --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 41 ++++---- Controllers/StoreController.cs | 94 +++++++++++++++++++ .../YourFirstOrchardCoreController.cs.orig | 77 +++++++++++++++ Drivers/BookDisplayDriver.cs | 70 +++++++++----- Indexes/BookIndex.cs | 26 +++++ Map.cs | 3 +- Migrations/BookMigrations.cs | 28 ++++++ .../PersonMigrations.cs | 6 +- Models/PersonPart.cs | 15 ++- Startup.cs | 5 +- ViewModels/BookViewModel.cs | 15 +++ Views/Book.Description.cshtml | 13 +-- Views/Book.cshtml | 8 +- Views/DisplayManagement/DisplayBook.cshtml | 5 +- Views/Store/CreateBooks.cshtml | 3 + Views/Store/JKRowlingBooks.cshtml | 11 +++ Views/_ViewImports.cshtml | 4 +- 17 files changed, 362 insertions(+), 62 deletions(-) create mode 100644 Controllers/StoreController.cs create mode 100644 Controllers/YourFirstOrchardCoreController.cs.orig create mode 100644 Indexes/BookIndex.cs create mode 100644 Migrations/BookMigrations.cs rename Migrations.cs => Migrations/PersonMigrations.cs (87%) create mode 100644 ViewModels/BookViewModel.cs create mode 100644 Views/Store/CreateBooks.cshtml create mode 100644 Views/Store/JKRowlingBooks.cshtml diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index 5497602c..8c3fef3b 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -1,9 +1,10 @@ /* - * In this section you will learn how Orchard Core deals with displaying different so-called shapes used for displaying various - * information to the users. This is a very huge and powerful part of Orchard Core, here you will learn the basics of Display + * In this section you will learn how Orchard Core deals with displaying various information on the UI using reusable + * components shapes. This is a very huge and powerful part of Orchard Core, here you will learn the basics of Display * Management. - * - * To demonstrate this basic functionality, we will create a page for displaying information about a book in two different pages. + * + * To demonstrate this basic functionality, we will create two slightly different pages for displaying information + * about a book. */ using System.Threading.Tasks; @@ -14,14 +15,13 @@ namespace Lombiq.TrainingDemo.Controllers { - // Notice, that the controller implements the IUpdateModel interface. This interface encapsulates all the properties - // and methods related to ASP.NET Core MVC model binding which is already there in the Controller object so further - // implementations are not required. Orchard Core needs this model binding functionality outside the controllers (you - // will see it later). + // Notice, that the controller implements the IUpdateModel interface. This interface encapsulates the properties + // and methods related to ASP.NET Core MVC model binding. Orchard Core needs this model binding functionality + // outside the controllers (you will see it later). public class DisplayManagementController : Controller, IUpdateModel { - // For display management functionality we can use the IDisplayManager service where the T generic parameter is the - // object you want to create shapes for. + // The core display management features can be used by the IDisplayManagement service. The generic parameter + // will be the object that needs to be displayed on the UI somehow. private readonly IDisplayManager _bookDisplayManager; @@ -31,17 +31,19 @@ public DisplayManagementController(IDisplayManager bookDisplayManager) } - // First, let's see how the book summary page is generated. + // First, create a page that will display a summary and some additional data of the book. public async Task DisplayBook() { - // Since we don't store the book object in the database let's create one for demonstration purposes. + // For demonstration purposes create a dummy book object. var book = CreateDemoBook(); - // Here the shape is generated. Before going any further let's dig deeper and see what happens when this - // method is called. + // This method will generate a shape primarily for displaying information about the given object. var shape = await _bookDisplayManager.BuildDisplayAsync(book, this); + // We will see how this display shape is generated and what will contain but first let's see how is this + // rendered in the MVC view. // NEXT STATION: Go to Views/DisplayManagement/DisplayBook.cshtml. + return View(shape); } @@ -51,11 +53,12 @@ public async Task DisplayBookDescription() // Generate another book object to be used for demonstration purposes. var book = CreateDemoBook(); - // We can add a display type when we generate display shape. This time it will be Description. If display - // type is given then Orchard Core will search a cshtml file with a name [ObjectName].[DisplayType].cshtml. - // NEXT STATION: Go to Views/Book.Description.cshtml + // This time give an additional parameter which is the display type. If display type is given then Orchard + // Core will search a cshtml file with a name [ObjectName].[DisplayType].cshtml. var shape = await _bookDisplayManager.BuildDisplayAsync(book, this, "Description"); + // NEXT STATION: Go to Views/Book.Description.cshtml + return View(shape); } @@ -66,8 +69,8 @@ private Book CreateDemoBook() => CoverPhotoUrl = "/Lombiq.TrainingDemo/Images/HarryPotter.jpg", Title = "Harry Potter and The Sorcerer's Stone", Author = "J.K. (Joanne) Rowling", - Description = "Harry hasn't had a birthday party in eleven years - but all that is about to change when a mysterious " + - "letter arrives with an invitation to an incredible place.", + Description = "Harry hasn't had a birthday party in eleven years - but all that is about to change " + + "when a mysterious letter arrives with an invitation to an incredible place.", }; } } diff --git a/Controllers/StoreController.cs b/Controllers/StoreController.cs new file mode 100644 index 00000000..4a34fbe1 --- /dev/null +++ b/Controllers/StoreController.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Lombiq.TrainingDemo.Indexes; +using Lombiq.TrainingDemo.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Localization; +using OrchardCore.DisplayManagement; +using OrchardCore.DisplayManagement.ModelBinding; +using OrchardCore.DisplayManagement.Notify; +using YesSql; + +namespace Lombiq.TrainingDemo.Controllers +{ + public class StoreController : Controller, IUpdateModel + { + private readonly ISession _session; + private readonly IDisplayManager _bookDisplayManager; + private readonly INotifier _notifier; + private readonly IHtmlLocalizer H; + + + public StoreController( + ISession session, + IDisplayManager bookDisplayManager, + INotifier notifier, + IHtmlLocalizer htmlLocalizer) + { + _session = session; + _bookDisplayManager = bookDisplayManager; + _notifier = notifier; + H = htmlLocalizer; + } + + + [HttpGet] + public ActionResult CreateBooks() => View(); + + [HttpPost, ActionName(nameof(CreateBooks))] + public ActionResult CreateBooksPost() + { + foreach (var book in CreateDemoBooks()) + { + _session.Save(book); + } + + _notifier.Information(H["Books have been created in the database."]); + + return RedirectToAction(nameof(CreateBooks)); + } + + public async Task JKRowlingBooks() + { + var jkRowlingBooks = await _session + .Query() + .Where(book => book.Author == "J.K. (Joanne) Rowling") + .ListAsync(); + + var bookShapes = await Task.WhenAll(jkRowlingBooks.Select(async book => + await _bookDisplayManager.BuildDisplayAsync(book, this, "Description"))); + + return View(bookShapes); + } + + + private IEnumerable CreateDemoBooks() => + new Book[] + { + new Book + { + CoverPhotoUrl = "/Lombiq.TrainingDemo/Images/HarryPotter.jpg", + Title = "Harry Potter and The Sorcerer's Stone", + Author = "J.K. (Joanne) Rowling", + Description = "Harry hasn't had a birthday party in eleven years - but all that is about to " + + "change when a mysterious letter arrives with an invitation to an incredible place." + }, + new Book + { + Title = "Fantastic Beasts and Where To Find Them", + Author = "J.K. (Joanne) Rowling", + Description = "With his magical suitcase in hand, Magizoologist Newt Scamander arrives in New " + + "York in 1926 for a brief stopover. However, when the suitcase is misplaced and some of his " + + "fantastic beasts escape, there will be trouble for everyone." + }, + new Book + { + Title = "The Hunger Games", + Author = "Suzanne Collins", + Description = "The nation of Panem, formed from a post-apocalyptic North America, is a country " + + "that consists of a wealthy Capitol region surrounded by 12 poorer districts." + } + }; + } +} \ No newline at end of file diff --git a/Controllers/YourFirstOrchardCoreController.cs.orig b/Controllers/YourFirstOrchardCoreController.cs.orig new file mode 100644 index 00000000..36529e85 --- /dev/null +++ b/Controllers/YourFirstOrchardCoreController.cs.orig @@ -0,0 +1,77 @@ +/* + * This is a controller you can find in any ASP.NET Core MVC application; Orchard is an MVC application, although + * much-much more than that. + * + * An Orchard module is basically an MVC area. You could create areas that don't interact with Orchard and you'd just + * use standard ASP.NET Core MVC skills. Of course we want more than that, so let's take a closer look. + * + * Here you will see how to use some simple ASP.NET Core and Orchard Core services. + */ + +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Localization; +using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; +using OrchardCore.DisplayManagement.Notify; + +namespace Lombiq.TrainingDemo.Controllers +{ + public class YourFirstOrchardCoreController : Controller + { + private readonly INotifier _notifier; + private readonly IStringLocalizer T; + private readonly IHtmlLocalizer H; + private readonly ILogger _logger; + + + public YourFirstOrchardCoreController( + INotifier notifier, + IStringLocalizer stringLocalizer, + IHtmlLocalizer htmlLocalizer, + ILogger logger) + { + _notifier = notifier; + _logger = logger; + + T = stringLocalizer; + H = htmlLocalizer; + } + + + // Here's a simple action that will return some message. Nothing special here just demonstrates that this will work + // in Orchard Core right after enabling the module. The route for this action will be + // /Lombiq.TrainingDemo/YourFirstOrchardCore/Index. + public ActionResult Index() => +<<<<<<< dest + // For now we just return an empty view. This action is accessible from under + // Lombiq.TrainingDemo/YourFirstOrchardCore/Index route (appended to your site's root path; so using defaults + // it would look something like this: https://localhost:44300/Lombiq.TrainingDemo/YourFirstOrchardCore/Index). + // If you don't know how this path gets together take a second look at how ASP.NET Core MVC routing works! +======= + // Simple texts can be localized using the IStringLocalizer service as you can see below. +>>>>>>> source + View(new { Message = T["Hello you!"] }); + + // Let's see some custom routing here. This attribute will override the default route and use this one. + [Route("TrainingDemo/NotifyMe")] + public ActionResult NotifyMe() + { + // ILogger is an ASP.NET Core service that will write something in the specific log files. In Orchard Core + // NLog is used for logging and the error level is "Error" by default. You can find the error log in the + // /App_Data/logs/orchard-log-[date].log file. Logger can be configured in the NLog.config file in the web + // project (e.g. OrchardCore.Cms.Web). + _logger.LogError("You have been notified about some error!"); + + // INotifier is an Orchard Core service to send messages to the user. This service can be used almost + // everywhere in the code base not only in Controllers. This service requires a LocalizedHtmlString object + // so the IHtmlLocalizer service needs to be used for localization. + _notifier.Information(H["Congratulations! You have been notified! Check the error log too!"]); + + return View(); + } + } +} + +/* + * NEXT STATION: Controllers/DisplayManagementController + */ diff --git a/Drivers/BookDisplayDriver.cs b/Drivers/BookDisplayDriver.cs index 89eb7d24..3beac70d 100644 --- a/Drivers/BookDisplayDriver.cs +++ b/Drivers/BookDisplayDriver.cs @@ -1,46 +1,68 @@ +using System.Threading.Tasks; using Lombiq.TrainingDemo.Models; +using Lombiq.TrainingDemo.ViewModels; using OrchardCore.DisplayManagement.Handlers; +using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; namespace Lombiq.TrainingDemo.Drivers { - // A DisplayDriver is an abstraction over all the functionality for displaying or editing a specific object that is - // usually done in the Controllers. You can create a driver for any object or contents (i.e. ContentParts or - // ContentFields) where you can implement their very specific logic for generating reusable shapes or validating - // them after model binding. Furthermore, you can create multiple drivers for one object where all the driver - // methods will be executed even if the original driver is implemented in another (e.g. Orchard Core) module. + // DisplayDrivers are for implementing the functionality for specific shapes generated by the DisplayManager. You + // can create a driver for any object (persisted or not-persisted) where you can implement their specific logic for + // generating reusable shapes. In case of an editor shape the model update and custom validation is also done in + // these drivers. Finally, you can create multiple drivers for one object and the DisplayDriver will make sure that + // all of your drivers are used and their specific logic will be executed. public class BookDisplayDriver : DisplayDriver { - // This method gets called when building the display shape of object. If you need to call async methods here - // you can override DisplayAsync instead of this. Please note, that only one can be used since if the - // DisplayAsync is not overriden then it will be called asynchronously - either way, it will be async. + // So we have a Book object and we want to register some display shapes. For this you need to override the + // Display or DisplayAsync methods depending on your code (only one can be used!). Ultimately, the + // DisplayManager will return a shape that contains all (or some) of these shapes. public override IDisplayResult Display(Book model) => // For the sake of demonstration we use Combined() here. It makes it possible to return multiple shapes - // from a driver method. Use this if you'd like to return different shapes that can be used e.g. with - // different display types or you need to display specific shapes in different zones. Zones will be - // described later. + // from a driver method - won't necessarily be displayed all at once! Combine( - // Here we define a shape for the Title. The shapeType parameter will also define the default file name - // that will contain the actual markup. For this one it will be Book.Display.Title.cshtml which is - // located in the Views/Items folder. This shape will be placed in the first position of the Header - // zone. + // Here we define a shape for the Title. It's not necessary to split these to atomic pieces but it + // would make sense to make a reusable shape for the title. In the Location helper you define a + // position for the shape. "Header" means that it will be displayed in the Header zone. "1" means that + // it will be the first in the Header zone. Soon you will see what the zones are. View("Book_Display_Title", model) .Location("Header: 1"), // Same applies here. This shape will be displayed in the Header zone too but in the second position. - // This way we make sure that the Title goes first. View("Book_Display_Author", model) .Location("Header: 2"), - // The cover photo will be in a different zone. + // Create a separate shape for the cover photo. This will go to a different zone, the "Cover" zone. View("Book_Display_Cover", model) .Location("Cover: 1"), - // The description, however, won't be displayed by default because its location targets a different - // display type. Note, that the previous shapes had no display type parameter so those will be - // displayed in every display type. This one will be displayed in the first position of the Content - // zone if the Book display shape will be generated with the Description display type. + // The shape for the description will be the first in the Content zone. Although, you can see another + // parameter here, this is the display type. It is used to differentiate circumstances of displaying a + // shape. Let's say you want to display Title, Author and Cover all the time (no shape type parameter), + // but the description will be displayed only if the display type is "Description". You'll see an + // example for that. View("Book_Display_Description", model) .Location("Description", "Content: 1")); - // NEXT STATION: Now let's see what are those zones and how these shapes will come together! Go to - // Views/Book.cshtml. + // Now let's see what those zones are and slowly clarify all these things you've seen above! + // NEXT STATION: Views/Book.cshtml. + + public override IDisplayResult Edit(Book book) => + Initialize("Book_Edit", model => + { + model.Author = book.Author; + model.Title = book.Title; + model.Description = book.Description; + }); + + public override async Task UpdateAsync(Book book, IUpdateModel updater) + { + var viewModel = new BookViewModel(); + + await updater.TryUpdateModelAsync(viewModel, Prefix); + + book.Title = viewModel.Title; + book.Author = viewModel.Author; + book.Description = viewModel.Description; + + return Edit(book); + } } -} +} \ No newline at end of file diff --git a/Indexes/BookIndex.cs b/Indexes/BookIndex.cs new file mode 100644 index 00000000..82ac7407 --- /dev/null +++ b/Indexes/BookIndex.cs @@ -0,0 +1,26 @@ +using Lombiq.TrainingDemo.Models; +using YesSql.Indexes; + +namespace Lombiq.TrainingDemo.Indexes +{ + public class BookIndex : MapIndex + { + public string Author { get; set; } + public string Title { get; set; } + } + + + public class BookIndexProvider : IndexProvider + { + public override void Describe(DescribeContext context) + { + context.For() + .Map(book => + new BookIndex + { + Author = book.Author, + Title = book.Title, + }); + } + } +} \ No newline at end of file diff --git a/Map.cs b/Map.cs index b487ad08..94cbf3ba 100644 --- a/Map.cs +++ b/Map.cs @@ -3,6 +3,7 @@ using Lombiq.TrainingDemo.Fields; using Lombiq.TrainingDemo.Indexes; using Lombiq.TrainingDemo.Indexing; +using Lombiq.TrainingDemo.Migrations; using Lombiq.TrainingDemo.Models; using Lombiq.TrainingDemo.Settings; using Lombiq.TrainingDemo.ViewModels; @@ -62,7 +63,7 @@ private static void Treasure() Factory(); // Content Type, ContentPart, ContentField, index record creation. - Factory(); + Factory(); // ISession, IContentItemDisplayManager, IClock Factory(); diff --git a/Migrations/BookMigrations.cs b/Migrations/BookMigrations.cs new file mode 100644 index 00000000..30e265dc --- /dev/null +++ b/Migrations/BookMigrations.cs @@ -0,0 +1,28 @@ +using Lombiq.TrainingDemo.Indexes; +using OrchardCore.ContentManagement.Metadata; +using OrchardCore.Data.Migration; + +namespace Lombiq.TrainingDemo.Migrations +{ + public class BookMigrations : DataMigration + { + IContentDefinitionManager _contentDefinitionManager; + + + public BookMigrations(IContentDefinitionManager contentDefinitionManager) + { + _contentDefinitionManager = contentDefinitionManager; + } + + + public int Create() + { + SchemaBuilder.CreateMapIndexTable(nameof(BookIndex), table => table + .Column(nameof(BookIndex.Author)) + .Column(nameof(BookIndex.Title)) + ); + + return 1; + } + } +} \ No newline at end of file diff --git a/Migrations.cs b/Migrations/PersonMigrations.cs similarity index 87% rename from Migrations.cs rename to Migrations/PersonMigrations.cs index 15af08ef..dfbd7b59 100644 --- a/Migrations.cs +++ b/Migrations/PersonMigrations.cs @@ -7,14 +7,14 @@ using OrchardCore.ContentManagement.Metadata.Settings; using OrchardCore.Data.Migration; -namespace Lombiq.TrainingDemo +namespace Lombiq.TrainingDemo.Migrations { - public class Migrations : DataMigration + public class PersonMigrations : DataMigration { IContentDefinitionManager _contentDefinitionManager; - public Migrations(IContentDefinitionManager contentDefinitionManager) + public PersonMigrations(IContentDefinitionManager contentDefinitionManager) { _contentDefinitionManager = contentDefinitionManager; } diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs index a9d3ccea..2332e98d 100644 --- a/Models/PersonPart.cs +++ b/Models/PersonPart.cs @@ -4,11 +4,22 @@ namespace Lombiq.TrainingDemo.Models { + // Now let's see how Orchard Core stores different data in the database. Here you can see a ContentPart. Each + // ContentPart can be part of one or more content types. Using the content type you can create ContentItems that is + // the most important part of the Orchard Core content management. Here is a PersonPart containing some properties + // of a person. public class PersonPart : ContentPart { + // A ContentPart is serialized as a JSON object so you need to keep this in mind when creating properties. For + // further information check the Json.NET documentation: + // https://www.newtonsoft.com/json/help/html/Introduction.htm public string Name { get; set; } public Handedness Handedness { get; set; } public DateTime? BirthDateUtc { get; set; } + + // This is a ContentField. ContentFields are similar to ContentParts, however, fields are a bit more smaller + // components encapsulating simple editor and display for a single data and ContentParts could have a more + // complex functionality and also can contain a set of fields. public TextField Biography { get; set; } } @@ -17,4 +28,6 @@ public enum Handedness Right, Left } -} \ No newline at end of file +} + +// NEXT STATION: Migrations.cs \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index 4c7d8e44..a347e95a 100644 --- a/Startup.cs +++ b/Startup.cs @@ -4,6 +4,7 @@ using Lombiq.TrainingDemo.Fields; using Lombiq.TrainingDemo.Indexes; using Lombiq.TrainingDemo.Indexing; +using Lombiq.TrainingDemo.Migrations; using Lombiq.TrainingDemo.Models; using Lombiq.TrainingDemo.Settings; using Lombiq.TrainingDemo.ViewModels; @@ -40,10 +41,12 @@ public override void ConfigureServices(IServiceCollection services) // Book services.AddScoped, BookDisplayDriver>(); services.AddScoped, DisplayManager>(); + services.AddScoped(); + services.AddSingleton(); // Person Part services.AddSingleton(); - services.AddScoped(); + services.AddScoped(); services.AddScoped(); services.AddSingleton(); diff --git a/ViewModels/BookViewModel.cs b/ViewModels/BookViewModel.cs new file mode 100644 index 00000000..9fbb7c55 --- /dev/null +++ b/ViewModels/BookViewModel.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; + +namespace Lombiq.TrainingDemo.ViewModels +{ + public class BookViewModel + { + [Required] + public string Title { get; set; } + + [Required] + public string Author { get; set; } + + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Views/Book.Description.cshtml b/Views/Book.Description.cshtml index 11ed6a4b..180ddf31 100644 --- a/Views/Book.Description.cshtml +++ b/Views/Book.Description.cshtml @@ -1,10 +1,11 @@ -@* This is a very similar display shape for Book object, however, this one will be used only if the display type is Description. - The zone-related properties of the Model objects will be populated accordingly. *@ +@* This is a very similar display shape for the Book object, however, this one will be used only if the display type is +Description. The zone-related properties of the Model objects will be populated accordingly. *@
- @* Display Header zone if there is any shape placed in the zone. *@ - @if (Model.Header != null) - { + @* Display Header zone if there is any shape placed in the zone. Remember that since Title and Author shapes have + no display type property given in the Driver these will also be rendered here. This way you can reuse any shapes + you want in Orchard Core! *@ + @if (Model.Header != null) {
@await DisplayAsync(Model.Header)
@@ -19,4 +20,4 @@ }
-@* NEXT STATION: Go to Views/_ViewImports.cshtml *@ \ No newline at end of file +@* NEXT STATION: Go to Models/PersonPart *@ \ No newline at end of file diff --git a/Views/Book.cshtml b/Views/Book.cshtml index 137d8ba0..a8bbcbb9 100644 --- a/Views/Book.cshtml +++ b/Views/Book.cshtml @@ -1,5 +1,6 @@ -@* This is the display shape of any Book item if no display type given. This is generated by Orchard Core and the model - contains all the zones defined in any DisplayDrivers (remember, there can be multiple drivers for one object).*@ +@* This is the display shape of any Book item if no display type given (actually the default display type is +"Details"). This is generated by Orchard Core and the model contains all the zones defined in any DisplayDrivers +where the zones will contain the rendered smaller shapes you've seen earlier. *@
@* Display Cover zone if there is any shape placed in the zone. *@ @@ -21,4 +22,5 @@ @T["View Description"]
-@* NEXT STATION: Go back to Controllers/DisplayManagementController.cs and find the DisplayBookDescription action. *@ \ No newline at end of file +@* Now create another display type for the Book where the Description will be rendered. +NEXT STATION: Go back to Controllers/DisplayManagementController.cs and find the DisplayBookDescription action. *@ \ No newline at end of file diff --git a/Views/DisplayManagement/DisplayBook.cshtml b/Views/DisplayManagement/DisplayBook.cshtml index 5d26a52a..50745b77 100644 --- a/Views/DisplayManagement/DisplayBook.cshtml +++ b/Views/DisplayManagement/DisplayBook.cshtml @@ -1,5 +1,6 @@ -@* We passed the generated display shape to this view. To actually render any shapes generated in Orchard we use Display helpers. - To use these Orchard Core-related helpers in shapes we need to add a few usings and tag helpers to _ViewImports.cshtml file.*@ +@* We passed the generated display shape object to this view. To actually render any shapes generated in Orchard we use +Display helpers. To use these Orchard Core-related helpers in any .cshtml files we need to add a few usings and tag +helpers to _ViewImports.cshtml file.*@ @await DisplayAsync(Model) diff --git a/Views/Store/CreateBooks.cshtml b/Views/Store/CreateBooks.cshtml new file mode 100644 index 00000000..a209b0cc --- /dev/null +++ b/Views/Store/CreateBooks.cshtml @@ -0,0 +1,3 @@ +
+ +
\ No newline at end of file diff --git a/Views/Store/JKRowlingBooks.cshtml b/Views/Store/JKRowlingBooks.cshtml new file mode 100644 index 00000000..33187d94 --- /dev/null +++ b/Views/Store/JKRowlingBooks.cshtml @@ -0,0 +1,11 @@ +@model IEnumerable + +

@T["J.K. Rowling Books"]

+
    + @foreach (var shape in Model) + { +
  • + @await DisplayAsync(shape) +
  • + } +
\ No newline at end of file diff --git a/Views/_ViewImports.cshtml b/Views/_ViewImports.cshtml index a6c29f57..8bd758c0 100644 --- a/Views/_ViewImports.cshtml +++ b/Views/_ViewImports.cshtml @@ -1,5 +1,5 @@ -@* _ViewImports.cshtml is an ASP.NET Core MVC-related feature. What is interesting to us is the Orchard Core-related usings - and tag helpers that we will possibly use in most of our shapes (.cshtml files). *@ +@* _ViewImports.cshtml is an ASP.NET Core MVC-related feature. What is interesting to us is the Orchard Core-related +usings and tag helpers that we will possibly use in most of our shapes (.cshtml files). *@ @inherits OrchardCore.DisplayManagement.Razor.RazorPage From e89bce41c5bca305f34ff7bed04756614e328866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Fri, 4 Jan 2019 14:01:06 +0100 Subject: [PATCH 29/65] Excluding node_modules from csproj --HG-- branch : issue/OCORE-1 --- Lombiq.TrainingDemo.csproj | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index a4473109..834ee43a 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -1,9 +1,15 @@ - + netstandard2.0 + + + + + + From 5dfd5f55e66b8cd43e1d68cc0a71c69ff411969e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Fri, 4 Jan 2019 14:02:08 +0100 Subject: [PATCH 30/65] Excluding .git and .hg files --HG-- branch : issue/OCORE-1 --- Lombiq.TrainingDemo.csproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index 834ee43a..26651e69 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -10,6 +10,12 @@ + + + + + + From 9f8dac5b066099ec022de361df332546b57a4a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 9 Jan 2019 17:18:44 +0100 Subject: [PATCH 31/65] Documenting person part and adding a demonstration for persisting simple objects --HG-- branch : issue/OCORE-1 --- Controllers/PersonListController.cs | 23 +++++++++++++++++ Controllers/StoreController.cs | 38 ++++++++++++++++++++++++++--- Drivers/PersonPartDisplayDriver.cs | 36 ++++++++++++++++++++++----- Indexes/BookIndex.cs | 10 +++++++- Indexes/PersonPartIndex.cs | 8 ++++++ Migrations/BookMigrations.cs | 33 ++++++++++++++++++++++++- Migrations/PersonMigrations.cs | 28 +++++++++++++++------ Models/PersonPart.cs | 4 +-- ViewModels/PersonPartViewModel.cs | 6 ++++- Views/Book.Description.cshtml | 2 +- Views/PersonList/OlderThan30.cshtml | 7 +++++- Views/PersonPart.Edit.cshtml | 9 ++++++- 12 files changed, 179 insertions(+), 25 deletions(-) diff --git a/Controllers/PersonListController.cs b/Controllers/PersonListController.cs index 0cce246f..c8c9057a 100644 --- a/Controllers/PersonListController.cs +++ b/Controllers/PersonListController.cs @@ -1,3 +1,13 @@ +/* + * In this Controller you will see again how to query items but this time it will be the newly created Person content + * type. It doesn't make too much difference but you need to keep in mind that the ContentItems are stored in the + * documents (which contains the parts and fields serialized) and can have multiple index records referencing a content + * item (e.g. the previously created PersonPartIndex that indexes data in from the PersonPart). + * + * Note, that there is no custom controller or action demonstrated for displaying the editor for the Person. Go to the + * administration page and create a few Person content item. + */ + using System.Linq; using System.Threading.Tasks; using Lombiq.TrainingDemo.Indexes; @@ -32,11 +42,24 @@ public async Task OlderThan30() { var thresholdDate = _clock.UtcNow.AddYears(-30); var people = await _session + // It will query for content items where the related PersonPartIndex.BirthDateUtc is lower than the + // threshold date. Notice that there is no Where method. The Query method has an overload for that + // which can be useful if you don't want to filter in multiple indexes. .Query(index => index.BirthDateUtc < thresholdDate) .ListAsync(); + // Now let's build the display shape for a content item! Notice that this is not the IDisplayManager + // service. The IContentItemDisplayManager is an abstraction over that and it's specifically for content + // items. The reason we need that is that a ContentItem doesn't have a DisplayDriver but the ContentParts + // and ContentFields attached to the ContentItem have. This service will handle generating all the drivers + // created for these parts and fields. + // NEXT STATION: Drivers/PersonPartDriver var shapes = await Task.WhenAll(people.Select(async person => await _contentItemDisplayManager.BuildDisplayAsync(person, this, "Summary"))); + + // Now that assuming that you've already created a few Person content items on the dashboard and some of + // these persons are more than 30 years old then this query will contain items to display. + // NEXT STATION: Views/PersonList/OlderThan30.cshtml return View(shapes); } diff --git a/Controllers/StoreController.cs b/Controllers/StoreController.cs index 4a34fbe1..78036b5c 100644 --- a/Controllers/StoreController.cs +++ b/Controllers/StoreController.cs @@ -1,3 +1,16 @@ +/* + * Now it's time to save something to the database. Orchard Core uses YesSql to store data in database which is + * document database interface for relational databases. In simple, you need to plan your database as a document + * database but it will be stored in your favorite SQL database. If you want to learn more go to + * https://github.com/sebastienros/yessql and read the documentation. + * + * Here you will see how to store simple data in the database and then query it without actually using Orchard Core + * content management features and practices (i.e. you can store Orchard Core content items). + * + * This demonstration will be really simple because more features will be shown later and you can also learn more from + * the YesSql documentation. + */ + using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -33,14 +46,22 @@ public StoreController( } + // A page with a button that will call the CreateBooks POST action. [HttpGet] public ActionResult CreateBooks() => View(); - + [HttpPost, ActionName(nameof(CreateBooks))] public ActionResult CreateBooksPost() { + // For demonstration purposes it will create 3 books and store them in the database one-by-one using the + // ISession service. + + // Since storing them in the documents is not enough we need to index them to be able to + // filter them in a query. + // NEXT STATION: Indexes/BookIndex.cs foreach (var book in CreateDemoBooks()) { + // So now you understand what will happen in the background when this service is being called. _session.Save(book); } @@ -49,19 +70,30 @@ public ActionResult CreateBooksPost() return RedirectToAction(nameof(CreateBooks)); } + // This page will display the books written by J.K. Rowling. public async Task JKRowlingBooks() { + // ISession service is used for querying items. var jkRowlingBooks = await _session + // First, we define what object (document) we want to query and what index should be used for + // filtering. .Query() - .Where(book => book.Author == "J.K. (Joanne) Rowling") + // In the .Where() method you can describe a lambda where the object will be the index object. + .Where(index => index.Author == "J.K. (Joanne) Rowling") + // When the query is built up you can call the ListAsync() to execute it. This will return a list of + // books. .ListAsync(); + // Now this is what we possibly understand now, we will create a list of display shapes from the previously + // fetched books. var bookShapes = await Task.WhenAll(jkRowlingBooks.Select(async book => - await _bookDisplayManager.BuildDisplayAsync(book, this, "Description"))); + await _bookDisplayManager.BuildDisplayAsync(book, this))); return View(bookShapes); } + // NEXT STATION: Models/PersonPart.cs + private IEnumerable CreateDemoBooks() => new Book[] diff --git a/Drivers/PersonPartDisplayDriver.cs b/Drivers/PersonPartDisplayDriver.cs index 88c6960d..5e6e3b85 100644 --- a/Drivers/PersonPartDisplayDriver.cs +++ b/Drivers/PersonPartDisplayDriver.cs @@ -2,21 +2,27 @@ using Lombiq.TrainingDemo.Models; using Lombiq.TrainingDemo.ViewModels; using OrchardCore.ContentManagement.Display.ContentDisplay; -using OrchardCore.DisplayManagement.Handlers; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; namespace Lombiq.TrainingDemo.Drivers { + // Drivers inherited from ContentPartDisplayDrivers have a similar functionality described in the BookDisplayDriver + // but these are for ContentParts. public class PersonPartDisplayDriver : ContentPartDisplayDriver { - public override IDisplayResult Display(PersonPart part) - { - return View(nameof(PersonPart), part).Location("Content: 1"); - } + // A Display method that we already know. This time it's much simpler because we don't want to create multiple + // shapes for the PersonPart - however we could. + public override IDisplayResult Display(PersonPart part) => + View(nameof(PersonPart), part).Location("Content: 1"); + // This is something that wasn't implemented in the BookDisplayDriver (but could've been). It will generate the + // editor shape for the PersonPart. public override IDisplayResult Edit(PersonPart personPart) { + // Similar happens to the Display, you have a shape helper with a shape name possibly and a factory. For + // editing the Initialize is the best idea. It will instantiate a view model from a type given as a generic + // parameter. In the factory you will map the content part properties to the view model. return Initialize("PersonPart_Edit", model => { model.PersonPart = personPart; @@ -27,12 +33,28 @@ public override IDisplayResult Edit(PersonPart personPart) }); } + // NEXT STATION: Views/PersonPart.Edit.cshtml + + // So we had an Edit (or EditAsync) that generates the editor shape now it's time to do the content + // part-specific model binding and validation. public override async Task UpdateAsync(PersonPart model, IUpdateModel updater) { var viewModel = new PersonPartViewModel(); + // Now it's where the IUpdateModel interface is really used. With this you will be able to use the + // Controller's model binding helpers here in the driver. The prefix property will be used to distinguish + // between similarly named input fields when building the editor form. By default Orchard Core will use the + // content part name but if you have multiple drivers for a content part you need to override it in the + // driver. await updater.TryUpdateModelAsync(viewModel, Prefix); - + + // Now you can do some validation if needed. One way to do it you can simply write your own validation here + // or you can do it in the view model class. + + // Go and check the ViewModels/PersonPartViewModel to see how to do it and then come back here. + + // Finally map the view model to the content part. By default these changes won't be persisted if there was + // a validation error. Otherwise, these will be automatically stored in the database. model.BirthDateUtc = viewModel.BirthDateUtc; model.Name = viewModel.Name; model.Handedness = viewModel.Handedness; @@ -41,3 +63,5 @@ public override async Task UpdateAsync(PersonPart model, IUpdate } } } + +// NEXT STATION: Controllers/PersonListController and go back to the OlderThan30 method where we left. \ No newline at end of file diff --git a/Indexes/BookIndex.cs b/Indexes/BookIndex.cs index 82ac7407..d67de2f8 100644 --- a/Indexes/BookIndex.cs +++ b/Indexes/BookIndex.cs @@ -3,6 +3,8 @@ namespace Lombiq.TrainingDemo.Indexes { + // The BookIndex objects will be stored in the database. Since this is actually a relational database these will be + // actual records in a table specifically created for this index. public class BookIndex : MapIndex { public string Author { get; set; } @@ -10,6 +12,10 @@ public class BookIndex : MapIndex } + // These IndexProvider services will provide the mappings between the objects stored in the document database and + // the index objects stored in records. When a Book object is being saved by the ISession service an index record + // will also be stored in the related index table. + // You need to register this service to the service provider. public class BookIndexProvider : IndexProvider { public override void Describe(DescribeContext context) @@ -19,8 +25,10 @@ public override void Describe(DescribeContext context) new BookIndex { Author = book.Author, - Title = book.Title, + Title = book.Title }); } } + + // NEXT STATION: Migrations/BookMigrations. } \ No newline at end of file diff --git a/Indexes/PersonPartIndex.cs b/Indexes/PersonPartIndex.cs index 69fb79e0..01961126 100644 --- a/Indexes/PersonPartIndex.cs +++ b/Indexes/PersonPartIndex.cs @@ -5,14 +5,20 @@ namespace Lombiq.TrainingDemo.Indexes { + // This is also very similar to the one we've seen in the BookIndex.cs. The difference is that we have ContentItems + // now instead of simple objects. public class PersonPartIndex : MapIndex { + // Here we will reference the ContentItem ID. public string ContentItemId { get; set; } + + // Store the birth date only for demonstration purposes. public DateTime? BirthDateUtc { get; set; } } public class PersonPartIndexProvider : IndexProvider { + // Notice that ContentItem is what we are describing the provider for not the part. public override void Describe(DescribeContext context) { context.For() @@ -32,4 +38,6 @@ public override void Describe(DescribeContext context) }); } } + + // NEXT STATION: Controllers/PersonListController } \ No newline at end of file diff --git a/Migrations/BookMigrations.cs b/Migrations/BookMigrations.cs index 30e265dc..efd9f0fd 100644 --- a/Migrations/BookMigrations.cs +++ b/Migrations/BookMigrations.cs @@ -1,3 +1,9 @@ +/* + * Previously we've seen how to describe an index. We also have to declare how to store it as well. This is where we + * need migrations. Migrations are automatically run by the framework (after you've registered it in the service + * provider). You can use them to describe DB schema changes. + */ + using Lombiq.TrainingDemo.Indexes; using OrchardCore.ContentManagement.Metadata; using OrchardCore.Data.Migration; @@ -15,6 +21,8 @@ public BookMigrations(IContentDefinitionManager contentDefinitionManager) } + // Migrations have Create() and UpdateFromX methods. When the module is first enabled the Create() is called so + // it can set up DB tables. public int Create() { SchemaBuilder.CreateMapIndexTable(nameof(BookIndex), table => table @@ -22,7 +30,30 @@ public int Create() .Column(nameof(BookIndex.Title)) ); - return 1; + // Here we return the number of the migration. If there were no update methods we'd return 1. But we have + // one, see it for more details. + return 2; } + + /* + * This is an update method. It is used to modify the existing schema. Update methods will be run when the + * module was already enabled before and the create method was run. The X in UpdateFromX is the number of the + * update (the method's name is conventional). It means: "run this update if the module's current migration + * version is X". This method will run if it's 1. + */ + public int UpdateFrom1() + { + // The initial version of our module did not store the book's title. We quickly fix the issue by pushing + // out an update that modifies the schema to add the Name. Remember, we've returned 2 in the Create method + // so this update method won't be executed in a fresh setup. This is why you need to include all these + // changes in the Create method as well. + SchemaBuilder.CreateMapIndexTable(nameof(BookIndex), table => table + .Column(nameof(BookIndex.Title)) + ); + + return 2; + } + + // NEXT STATION: Controllers/StoreController and go to the CreateBooksPost action where we previously left. } } \ No newline at end of file diff --git a/Migrations/PersonMigrations.cs b/Migrations/PersonMigrations.cs index dfbd7b59..a2dfe8ca 100644 --- a/Migrations/PersonMigrations.cs +++ b/Migrations/PersonMigrations.cs @@ -9,6 +9,7 @@ namespace Lombiq.TrainingDemo.Migrations { + // Here's another migrations file but specifically for Person-related operations. public class PersonMigrations : DataMigration { IContentDefinitionManager _contentDefinitionManager; @@ -22,13 +23,10 @@ public PersonMigrations(IContentDefinitionManager contentDefinitionManager) public int Create() { - _contentDefinitionManager.AlterTypeDefinition("Person", builder => builder - .Creatable() - .Listable() - .WithPart(nameof(PersonPart)) - ); - + // Now you can configure PersonPart. For example you can add content fields (as mentioned earlier) here. _contentDefinitionManager.AlterPartDefinition(nameof(PersonPart), part => part + // Each field has it's own configuration. Here you will give a display name for it and add some + // additional settings like a hint to be displayed in the editor. .WithField(nameof(PersonPart.Biography), field => field .OfType(nameof(TextField)) .WithDisplayName("Biography") @@ -37,13 +35,27 @@ public int Create() Hint = "Person's biography" }))); + /* + * We create a new content type. Note that there's only an alter method: this will create the type if it + * doesn't exist or modify it if it does. Make sure you understand what content types are: + * http://docs.orchardproject.net/Documentation/Content-types. The content type's name is arbitrary, but + * choose a meaningful one. Notice that we attach parts by specifying their name. For our own parts we use + * nameof(): this is not mandatory but serves great if we change the part's name during development. + */ + _contentDefinitionManager.AlterTypeDefinition("Person", builder => builder + .Creatable() + .Listable() + .WithPart(nameof(PersonPart)) + ); + + // This one will create an index table for the PersonPartIndex as explained in the BookMigrations file. SchemaBuilder.CreateMapIndexTable(nameof(PersonPartIndex), table => table .Column(nameof(PersonPartIndex.BirthDateUtc)) .Column(nameof(PersonPartIndex.ContentItemId), c => c.WithLength(26)) - ).AlterTable(nameof(PersonPartIndex), table => table - .CreateIndex($"IDX_{nameof(PersonPartIndex)}_{nameof(PersonPartIndex.BirthDateUtc)}", nameof(PersonPartIndex.BirthDateUtc)) ); + // NEXT STATION: Indexes/PersonPartIndex + return 1; } } diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs index 2332e98d..d8c8f956 100644 --- a/Models/PersonPart.cs +++ b/Models/PersonPart.cs @@ -4,7 +4,7 @@ namespace Lombiq.TrainingDemo.Models { - // Now let's see how Orchard Core stores different data in the database. Here you can see a ContentPart. Each + // Now let's see what practices Orchard Core provides when it stores data. Here you can see a ContentPart. Each // ContentPart can be part of one or more content types. Using the content type you can create ContentItems that is // the most important part of the Orchard Core content management. Here is a PersonPart containing some properties // of a person. @@ -30,4 +30,4 @@ public enum Handedness } } -// NEXT STATION: Migrations.cs \ No newline at end of file +// NEXT STATION: Migrations/PersonMigrations \ No newline at end of file diff --git a/ViewModels/PersonPartViewModel.cs b/ViewModels/PersonPartViewModel.cs index 064cb78c..c3870d7f 100644 --- a/ViewModels/PersonPartViewModel.cs +++ b/ViewModels/PersonPartViewModel.cs @@ -9,6 +9,8 @@ namespace Lombiq.TrainingDemo.ViewModels { + // IValidateObject is az ASP.NET Core feature to use on view models where the model binder will automatically + // execute the Validate method which will return any validation error. public class PersonPartViewModel : IValidatableObject { [Required] @@ -27,7 +29,7 @@ public class PersonPartViewModel : IValidatableObject public IEnumerable Validate(ValidationContext validationContext) { // To use GetService overload you need to add the Microsoft.Extensions.DependencyInjection nuget package - // to your module. + // to your module. This way you can get any service you want as you've injected them in a constructor. var T = validationContext.GetService>(); var clock = validationContext.GetService(); @@ -41,6 +43,8 @@ public IEnumerable Validate(ValidationContext validationContex yield return new ValidationResult(T["The person must be 18 or older."], new[] { nameof(BirthDateUtc) }); } } + + // Now go back to the PersonPartDisplayDrvier. } } } \ No newline at end of file diff --git a/Views/Book.Description.cshtml b/Views/Book.Description.cshtml index 180ddf31..c96f8eb3 100644 --- a/Views/Book.Description.cshtml +++ b/Views/Book.Description.cshtml @@ -20,4 +20,4 @@ Description. The zone-related properties of the Model objects will be populated } -@* NEXT STATION: Go to Models/PersonPart *@ \ No newline at end of file +@* NEXT STATION: Go to Controllers/StoreController *@ \ No newline at end of file diff --git a/Views/PersonList/OlderThan30.cshtml b/Views/PersonList/OlderThan30.cshtml index ee283813..4a017d6d 100644 --- a/Views/PersonList/OlderThan30.cshtml +++ b/Views/PersonList/OlderThan30.cshtml @@ -1,3 +1,6 @@ +@* The "shapes" object is an IEnumerable so we just simply enumerate it and use the previously seen +DisplayAsync helper to display these shapes. *@ + @model IEnumerable

@T["People older then 30 years old"]

@@ -8,4 +11,6 @@ @await DisplayAsync(shape) } - \ No newline at end of file + + +@* NEXT STATION: Fields/ColorField.cs *@ \ No newline at end of file diff --git a/Views/PersonPart.Edit.cshtml b/Views/PersonPart.Edit.cshtml index ce4d30fe..89c4309d 100644 --- a/Views/PersonPart.Edit.cshtml +++ b/Views/PersonPart.Edit.cshtml @@ -1,6 +1,11 @@ +@* As you can see the model here is the view model object this time not a ShapeViewModel. *@ + @model PersonPartViewModel @using Lombiq.TrainingDemo.ViewModels; +@* Nothing special here regarding to the editor fields. However, notice that the Biography (ContentField) editor is not +here, because (as mentioned) it has its own editor and display shape so no need to worry about that. *@ +
@@ -15,4 +20,6 @@
-
\ No newline at end of file +
+ +@* NEXT STATION: Go back to Drivers/PersonPartDisplayDriver and find the UpdateAsync method. *@ \ No newline at end of file From 6ef067a10b5dcbc254effecc3193b442a8d53cce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 9 Jan 2019 18:46:57 +0100 Subject: [PATCH 32/65] Adding content field and resource management documentation --HG-- branch : issue/OCORE-1 --- Drivers/ColorFieldDisplayDriver.cs | 22 +++++++++++++++++- Fields/ColorField.cs | 8 +++++++ Gulpfile.js | 22 +++++++++++++++++- Indexing/ColorFieldIndexHandler.cs | 8 ++++++- Lombiq.TrainingDemo.csproj | 9 +++++++- ResourceManifest.cs | 26 ++++++++++++++++++++++ Settings/ColorFieldSettings.cs | 14 ++++++++++++ Settings/ColorFieldSettingsDriver.cs | 25 +++++++++++++++------ Views/ColorField-ColorPicker.Edit.cshtml | 11 ++++++++- Views/ColorField-ColorPicker.Option.cshtml | 4 ++++ Views/ColorField.Edit.cshtml | 7 +++++- Views/ColorField.Option.cshtml | 13 +++++++++++ Views/ColorField.cshtml | 8 +++++-- 13 files changed, 162 insertions(+), 15 deletions(-) diff --git a/Drivers/ColorFieldDisplayDriver.cs b/Drivers/ColorFieldDisplayDriver.cs index 0dda9545..2b4d376a 100644 --- a/Drivers/ColorFieldDisplayDriver.cs +++ b/Drivers/ColorFieldDisplayDriver.cs @@ -12,6 +12,8 @@ namespace Lombiq.TrainingDemo.Drivers { + // You shouldn't be surprised - content fields also have display drivers. ContentFieldDisplayDriver is specifically + // for content fields. public class ColorFieldDisplayDriver : ContentFieldDisplayDriver { public IStringLocalizer T { get; set; } @@ -25,6 +27,12 @@ public ColorFieldDisplayDriver(IStringLocalizer stringL public override IDisplayResult Display(ColorField field, BuildFieldDisplayContext context) { + // Same Display method for generating display shape but this time the Initialize shape helper is being + // used. We've seen it in the PersonPartDisplayDriver.Edit method. For this we need a view model object + // that will be populated with the field data. The GetDisplayShapeType helper will generate a + // conventionally shape type for our content field which will be the name of our content field. Obviously, + // alternates can also be used - so if the content item is being displayed with a Custom display type then + // the ColorField.Custom.cshtml file name can be used, otherwise, the ColorField.cshtml will be active. return Initialize(GetDisplayShapeType(context), model => { model.Field = field; @@ -35,8 +43,12 @@ public override IDisplayResult Display(ColorField field, BuildFieldDisplayContex .Location("SummaryAdmin", ""); } + // NEXT STATION: Take a look at the Views/ColorField.cshtml shape to see how our field should display the given + // color and then come back here. + public override IDisplayResult Edit(ColorField field, BuildFieldEditorContext context) { + // Nothing new here, the Initialize shape helper is being used to generate an editor shape. return Initialize(GetEditorShapeType(context), model => { model.Value = field.Value; @@ -47,18 +59,24 @@ public override IDisplayResult Edit(ColorField field, BuildFieldEditorContext co }); } + // NEXT STATION: Settings/ColorFieldSettings + public override async Task UpdateAsync(ColorField field, IUpdateModel updater, UpdateFieldEditorContext context) { var viewModel = new EditColorFieldViewModel(); + // Using this overload of the model updater you can specifically say what properties need to be updated + // only. This way you make sure no other properties will be bound to the view model. if (await updater.TryUpdateModelAsync(viewModel, Prefix, f => f.Value, f => f.ColorName)) { + // Use the settings are now let's use them for validation. var settings = context.PartFieldDefinition.Settings.ToObject(); if (settings.Required && string.IsNullOrWhiteSpace(field.Value)) { updater.ModelState.AddModelError(Prefix, T["A value is required for {0}.", context.PartFieldDefinition.DisplayName()]); } + // Also some custom validation for our ColorField hex value. Could be done in the view model instead. if (!string.IsNullOrWhiteSpace(field.Value) && !Regex.IsMatch(viewModel.Value, "^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$")) { @@ -72,4 +90,6 @@ public override async Task UpdateAsync(ColorField field, IUpdate return Edit(field, context); } } -} \ No newline at end of file +} + +// NEXT STATION: Indexing/ColorFieldIndexHandler.cs \ No newline at end of file diff --git a/Fields/ColorField.cs b/Fields/ColorField.cs index c73db668..e60e3b73 100644 --- a/Fields/ColorField.cs +++ b/Fields/ColorField.cs @@ -2,9 +2,17 @@ namespace Lombiq.TrainingDemo.Fields { + /* + * Now we will develop a content field. Just like with content part development, we'll start with creating a model + * class. We want to store a color name and the actual color in HEX so we need two strings for that. + * + * Conventionally we put these objects in the Fields folder. + */ public class ColorField : ContentField { public string Value { get; set; } public string ColorName { get; set; } } } + +// NEXT STATION: Drivers/ColorFieldDisplayDriver \ No newline at end of file diff --git a/Gulpfile.js b/Gulpfile.js index 691d7620..577fc0f0 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -1,8 +1,22 @@ +// There are multiple ways of managing your resources (including scripts, stylesheets, images etc.). OrchardCore itself +// provide its own pipeline for it using an Assets.json file. We don't use it this time but check the +// http://docs.orchardproject.net/en/latest/Documentation/Processing-client-side-assets/ documentation for more +// information. + +// Here you will see a standalone Gulpfile for copying third-party resources from the node_modules folder to wwwroot +// folder and also compiling our own resources (styles and scripts) and moving the resoults to the wwwroot folder as +// well. + const gulp = require("gulp"); +// Gulp plugin used for compiling sass files. const sass = require("gulp-sass"); +// Minifies css files. const cssnano = require('gulp-cssnano'); +// Renames the file so the result will have a different name (i.e. .min.css or .min.js). const rename = require("gulp-rename"); +// Cache the result so the task won't be fully executed if it is not necessary. const cached = require("gulp-cached"); +// Gulp watcher if needed when we are actively developing a resource. const watch = require("gulp-watch"); const imageFiles = "./Assets/Images/**/*"; @@ -15,6 +29,7 @@ const sassFiles = "./Assets/Styles/**/*.scss"; const cssFiles = "./wwwroot/Styles/**/*.css"; const stylingFilesDestination = "./wwwroot/Styles"; +// This task will collect all the images and move it to the wwwroot folder. gulp.task("images", function () { return gulp .src(imageFiles) @@ -22,6 +37,7 @@ gulp.task("images", function () { .pipe(gulp.dest(imageFilesDestination)); }); +// Task specifically created for our third-party plugin, pickr. It will just copy the files to the wwwroot folder. gulp.task("pickr", function () { return gulp .src(pickrFiles) @@ -29,6 +45,7 @@ gulp.task("pickr", function () { .pipe(gulp.dest(pickrFilesDestination)); }); +// It will compile our sass files to css. gulp.task("sass:compile", function (callback) { gulp.src(sassFiles) .pipe(cached("scss")) @@ -37,6 +54,7 @@ gulp.task("sass:compile", function (callback) { .on("end", callback); }); +// It will minify our css files and renames them to contain the .min.css suffix. gulp.task("sass:minify", ["sass:compile"], function () { return gulp.src(cssFiles) .pipe(cached("css")) @@ -51,4 +69,6 @@ gulp.task("sass:watch", function () { watch(sassFiles, function () { gulp.start("sass:minify"); }); -}); \ No newline at end of file +}); + +// NEXT STATION: Lombiq.TrainingDemo.csproj and find the target with the "NpmInstall" name. \ No newline at end of file diff --git a/Indexing/ColorFieldIndexHandler.cs b/Indexing/ColorFieldIndexHandler.cs index b9ed42f1..aa8c4078 100644 --- a/Indexing/ColorFieldIndexHandler.cs +++ b/Indexing/ColorFieldIndexHandler.cs @@ -4,6 +4,9 @@ namespace Lombiq.TrainingDemo.Indexing { + // IndexHandlers are different from IndexProviders. While IndexProviders will store values in the SQL database to + // index documents these will use an actual index provider (e.g. Lucene) index data. This way no database query is + // required when you want to use a search widget on your website. public class ColorFieldIndexHandler : ContentFieldIndexHandler { public override Task BuildIndexAsync(ColorField field, BuildFieldIndexContext context) @@ -12,10 +15,13 @@ public override Task BuildIndexAsync(ColorField field, BuildFieldIndexContext co foreach (var key in context.Keys) { + // The color name will be indexed. context.DocumentIndex.Set(key, field.ColorName, options); } return Task.CompletedTask; } } -} \ No newline at end of file +} + +// NEXT STATION: Views/ColorField.Option.cshtml \ No newline at end of file diff --git a/Lombiq.TrainingDemo.csproj b/Lombiq.TrainingDemo.csproj index 26651e69..8040653f 100644 --- a/Lombiq.TrainingDemo.csproj +++ b/Lombiq.TrainingDemo.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -37,9 +37,16 @@
+ + + + + +
diff --git a/ResourceManifest.cs b/ResourceManifest.cs index 35dc1a7d..949a5040 100644 --- a/ResourceManifest.cs +++ b/ResourceManifest.cs @@ -2,25 +2,51 @@ namespace Lombiq.TrainingDemo { + // ResourceManifest classes implement IResourceManifestProvider and possess the BuildManifests method. public class ResourceManifest : IResourceManifestProvider { + // This is the only method to implement. Using it we're going to register some static resources + // to be able to use them in our templates. public void BuildManifests(IResourceManifestBuilder builder) { + // We add a new instance of ResourceManifest to the ResourceManifestBuilder, + // instantiated by the Add method. var manifest = builder.Add(); manifest + // We're registering a script with DefineStyle and defining it's name. It's a global name, so choose + // wisely. There is no strict naming convention, but we can give you and advice how to choose a unique + // name: it should contain the module's full namespace followed by a meaningful name. Although if it's + // a third-party library you can give a more general name like you see below. This script will be the + // javascript plugin for the color picker. .DefineScript("Pickr") + // This is the actual stylesheet that will be assigned to the resource name. Please note that the + // naming of the file itself is following similar rules as the resource name, with some modifications + // applied as it's a file name. Since stylesheets and script are shapes, it's possible to override + // them, so you should try to avoid name collisions: file names (not the full path, just the name!) + // should be globally unique. .SetUrl("/Lombiq.TrainingDemo/Pickr/pickr.min.js"); manifest + // With the DefineStyle method you can define a stylesheet. The way of doing this is very similar to + // defining scripts. .DefineStyle("Pickr") .SetUrl("/Lombiq.TrainingDemo/Pickr/pickr.min.css"); manifest + // Finally let's see an example for defining a resource for our custom work. You can see the naming is + // more specific and contains our namespace. .DefineStyle("Lombiq.TrainingDemo.ColorPicker") .SetUrl("/Lombiq.TrainingDemo/Styles/trainingdemo-colorpicker.min.css", "/Lombiq.TrainingDemo/Styles/trainingdemo-colorpicker.css") + // You can give a list of resource names to SetDependencies to force the loading of other resources + // when a given resource is used. Here the Pickr is a dependency. .SetDependencies("Pickr"); + + // If you go back to the Views/ColorField-ColorPicker.Edit.cshtml you will understand why all these three + // resources will be loaded using those style and script tag helpers. } } } + +// NEXT STATION: Gulpfile.js \ No newline at end of file diff --git a/Settings/ColorFieldSettings.cs b/Settings/ColorFieldSettings.cs index 06b64a79..ba21d482 100644 --- a/Settings/ColorFieldSettings.cs +++ b/Settings/ColorFieldSettings.cs @@ -1,9 +1,23 @@ namespace Lombiq.TrainingDemo.Settings { + // Every content part and content field can have settings. If you have a PersonPart content part where you use + // ColorField these settings will be applied on every content item where the PersonPart is in present, however, if + // you have multiple ColorFields, each fields will have their own settings. In our case we have three settings. public class ColorFieldSettings { + // We'll use this setting to determine whether the value of the field is required to be given by the user. public bool Required { get; set; } + + // Hint text to be displayed on the editor. public string Hint { get; set; } + + // The label to be used on the editor and the display shape. public string Label { get; set; } } + + // How can these settings be edited? If you attach a content field to a content part / content type you can set + // these values there (see: Migrations/PersonMigrations where the Biography field is being added to the + // PersonPart). If you attach the field on the dashboard yourself then Orchard Core will display its editor. + // Editor of an object like this? You know what you need to do... Create a DisplayDriver for this! + // NEXT STATION: Settings/ColorFieldSettingsDriver } \ No newline at end of file diff --git a/Settings/ColorFieldSettingsDriver.cs b/Settings/ColorFieldSettingsDriver.cs index 54a4c2a3..92f5de01 100644 --- a/Settings/ColorFieldSettingsDriver.cs +++ b/Settings/ColorFieldSettingsDriver.cs @@ -6,23 +6,34 @@ namespace Lombiq.TrainingDemo.Settings { + // It's in the Settings folder by convention but it's the same DisplayDriver as the others, except, it also has a + // specific base class. public class ColorFieldSettingsDriver : ContentPartFieldDefinitionDisplayDriver { - public override IDisplayResult Edit(ContentPartFieldDefinition partFieldDefinition) - { - return Initialize("ColorFieldSettings_Edit", model => partFieldDefinition.Settings.Populate(model)) - .Location("Content"); - } + // This won't have a Display override since it wouldn't make too much sense. + public override IDisplayResult Edit(ContentPartFieldDefinition partFieldDefinition) => + // Same old Initialize shape helper. + Initialize("ColorFieldSettings_Edit", + model => partFieldDefinition.Settings.Populate(model)) + .Location("Content"); - public override async Task UpdateAsync(ContentPartFieldDefinition partFieldDefinition, UpdatePartFieldEditorContext context) + // ColorFieldSettings.Edit.cshtml file will contain the editor inputs. + + public override async Task UpdateAsync( + ContentPartFieldDefinition partFieldDefinition, + UpdatePartFieldEditorContext context) { var model = new ColorFieldSettings(); await context.Updater.TryUpdateModelAsync(model, Prefix); + // A content field or a content part can have multiple settings. These settings are stored in a single JSON + // object. This helper will merge our settings to this JSON object so these will be stored. context.Builder.MergeSettings(model); return Edit(partFieldDefinition); } } -} \ No newline at end of file +} + +// NEXT STATION: Views/ColorField.Edit.cshtml \ No newline at end of file diff --git a/Views/ColorField-ColorPicker.Edit.cshtml b/Views/ColorField-ColorPicker.Edit.cshtml index 4f047818..c2f35167 100644 --- a/Views/ColorField-ColorPicker.Edit.cshtml +++ b/Views/ColorField-ColorPicker.Edit.cshtml @@ -11,6 +11,10 @@ var pickerElementId = $"{pickerInputElementId}-ColorPicker"; } +@* Script and styling resources can be used in these shapes. We'll get to it really soon first go through this file and +understand what is happening. Pickr is a javascript plugin used for displaying color pickers. With these two tag +helpers all the necessary scripts and styles will be loaded.*@ + @@ -28,6 +32,9 @@ }
+@* The following script will contain the initialization for the color picker. The at="Foot" will make it rendered in +the end of the Body tag. *@ + \ No newline at end of file + + +@* NEXT STATION: ResourceManifest.cs *@ \ No newline at end of file diff --git a/Views/ColorField-ColorPicker.Option.cshtml b/Views/ColorField-ColorPicker.Option.cshtml index ed94c801..30a2574b 100644 --- a/Views/ColorField-ColorPicker.Option.cshtml +++ b/Views/ColorField-ColorPicker.Option.cshtml @@ -1,4 +1,8 @@ @{ string currentEditor = Model.Editor; } + +@* This is a custom editor option wher we want to define a color picker editor for our field. The value is ColorPicker. +NEXT STATION: ColorField-ColorPicker.Edit.cshtml *@ + diff --git a/Views/ColorField.Edit.cshtml b/Views/ColorField.Edit.cshtml index 383f2bf5..2a889f6e 100644 --- a/Views/ColorField.Edit.cshtml +++ b/Views/ColorField.Edit.cshtml @@ -3,6 +3,9 @@ @using OrchardCore.ContentManagement.Metadata.Models @{ + // In editor shapes you can access the settings from the PartFieldDefinition.Settings. Since it contains all the + // settings you need to extract your own settings object. After that you can use it to display hint for example. + var settings = Model.PartFieldDefinition.Settings.ToObject(); } @@ -18,4 +21,6 @@ { @settings.Hint } - \ No newline at end of file + + +@* NEXT STATION: Drivers/ColorFieldDriver and find the UpdateAsync method where we left. *@ \ No newline at end of file diff --git a/Views/ColorField.Option.cshtml b/Views/ColorField.Option.cshtml index 039edfa0..cbab200f 100644 --- a/Views/ColorField.Option.cshtml +++ b/Views/ColorField.Option.cshtml @@ -1,4 +1,17 @@ +@* There is an extensibility to create different editor and display shapes for content fields. This is a setting that +every content fields have. When you attach a content field to the content part or content type you'll see two editors, +one will be the display option the other will be the editor option. You can add new options by adding cshtml or liquid +files with the [FieldName]-[OptionName].Option.cshtml pattern where you can specify your own option name and value. +After this you can create the [FieldName]-[OptionName].Edit.cshtml to create your new editor. This way no coding is +required so you can do it in a liquid theme as well. *@ + @{ string currentEditor = Model.Editor; } + +@* Now this is a default option with no value. We gave the name Hexadecimal. The ColorField.Edit.cshtml will be applied +as the default editor shape. *@ + + +@* NEXT STATION: Views/ColorField-ColorPicker.Option.cshtml *@ \ No newline at end of file diff --git a/Views/ColorField.cshtml b/Views/ColorField.cshtml index e833cbb2..18a18cbe 100644 --- a/Views/ColorField.cshtml +++ b/Views/ColorField.cshtml @@ -2,10 +2,14 @@ @using OrchardCore.Mvc.Utilities; @{ - var name = (Model.PartFieldDefinition.PartDefinition.Name + "-" + Model.PartFieldDefinition.Name).HtmlClassify(); - var hex = Model.Field.Value; + // To display a very-specific class name depending on the actual usage (i.e. technical name given on the dashboard) + // you can use these helpers. + var name = (Model.PartFieldDefinition.PartDefinition.Name + "-" + + Model.PartFieldDefinition.Name).HtmlClassify(); var hex = Model.Field.Value; } +@* Using these class names are conventions. All the Orchard Core fields have similar classes. Custom classes can be +added of course. *@
@Model.Field.ColorName
\ No newline at end of file From 005a86f4663cd2b429aed83e3efa1638224a8d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 9 Jan 2019 18:53:01 +0100 Subject: [PATCH 33/65] Using BEM classes --HG-- branch : issue/OCORE-1 --- Views/Book.Description.cshtml | 4 ++-- Views/Book.cshtml | 6 +++--- Views/ColorField.Edit.cshtml | 12 ++++++------ Views/ColorField.cshtml | 4 ++-- Views/Items/Book.Display.Author.cshtml | 2 +- Views/Items/Book.Display.Cover.cshtml | 2 +- Views/Items/Book.Display.Description.cshtml | 2 +- Views/Items/Book.Display.Title.cshtml | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Views/Book.Description.cshtml b/Views/Book.Description.cshtml index c96f8eb3..c498dca8 100644 --- a/Views/Book.Description.cshtml +++ b/Views/Book.Description.cshtml @@ -6,7 +6,7 @@ Description. The zone-related properties of the Model objects will be populated no display type property given in the Driver these will also be rendered here. This way you can reuse any shapes you want in Orchard Core! *@ @if (Model.Header != null) { -
+
@await DisplayAsync(Model.Header)
} @@ -14,7 +14,7 @@ Description. The zone-related properties of the Model objects will be populated @* Display Content zone if there is any shape placed in the zone. *@ @if (Model.Content != null) { -
+
@await DisplayAsync(Model.Content)
} diff --git a/Views/Book.cshtml b/Views/Book.cshtml index a8bbcbb9..33e33a82 100644 --- a/Views/Book.cshtml +++ b/Views/Book.cshtml @@ -6,7 +6,7 @@ where the zones will contain the rendered smaller shapes you've seen earlier. *@ @* Display Cover zone if there is any shape placed in the zone. *@ @if (Model.Cover != null) { -
+
@await DisplayAsync(Model.Cover)
} @@ -14,12 +14,12 @@ where the zones will contain the rendered smaller shapes you've seen earlier. *@ @* Display Header zone if there is any shape placed in the zone. *@ @if (Model.Header != null) { -
+
@await DisplayAsync(Model.Header)
} - @T["View Description"] + @T["View Description"]
@* Now create another display type for the Book where the Description will be rendered. diff --git a/Views/ColorField.Edit.cshtml b/Views/ColorField.Edit.cshtml index 2a889f6e..1ad72262 100644 --- a/Views/ColorField.Edit.cshtml +++ b/Views/ColorField.Edit.cshtml @@ -9,17 +9,17 @@ var settings = Model.PartFieldDefinition.Settings.ToObject(); } -
+
@Model.PartFieldDefinition.DisplayName() - - + + - - +
diff --git a/Views/ColorField.cshtml b/Views/ColorField.cshtml index 18a18cbe..d698b072 100644 --- a/Views/ColorField.cshtml +++ b/Views/ColorField.cshtml @@ -9,7 +9,7 @@ } @* Using these class names are conventions. All the Orchard Core fields have similar classes. Custom classes can be -added of course. *@ -
+added of course (e.g. BEM classes). *@ +
@Model.Field.ColorName
\ No newline at end of file diff --git a/Views/Items/Book.Display.Author.cshtml b/Views/Items/Book.Display.Author.cshtml index c724c7f3..d2e6c141 100644 --- a/Views/Items/Book.Display.Author.cshtml +++ b/Views/Items/Book.Display.Author.cshtml @@ -1,5 +1,5 @@ @model ShapeViewModel -

+

@Model.Value.Author

\ No newline at end of file diff --git a/Views/Items/Book.Display.Cover.cshtml b/Views/Items/Book.Display.Cover.cshtml index b8caebd5..6e49b059 100644 --- a/Views/Items/Book.Display.Cover.cshtml +++ b/Views/Items/Book.Display.Cover.cshtml @@ -1,3 +1,3 @@ @model ShapeViewModel - \ No newline at end of file + \ No newline at end of file diff --git a/Views/Items/Book.Display.Description.cshtml b/Views/Items/Book.Display.Description.cshtml index c67d28e6..a4ed1fb6 100644 --- a/Views/Items/Book.Display.Description.cshtml +++ b/Views/Items/Book.Display.Description.cshtml @@ -1,5 +1,5 @@ @model ShapeViewModel -
+
@Model.Value.Description
\ No newline at end of file diff --git a/Views/Items/Book.Display.Title.cshtml b/Views/Items/Book.Display.Title.cshtml index 1d4ce857..b9306b8a 100644 --- a/Views/Items/Book.Display.Title.cshtml +++ b/Views/Items/Book.Display.Title.cshtml @@ -1,5 +1,5 @@ @model ShapeViewModel -

+

@Model.Value.Title

\ No newline at end of file From 235ebe2ee30a3811b7c2bff699842f99d3a5d3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Wed, 9 Jan 2019 18:54:44 +0100 Subject: [PATCH 34/65] Updating Map.cs --HG-- branch : issue/OCORE-1 --- Map.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Map.cs b/Map.cs index 94cbf3ba..21a0349a 100644 --- a/Map.cs +++ b/Map.cs @@ -59,13 +59,17 @@ private static void Treasure() // Validating ContentPart fields Factory(); - // IndexProvider, indexing ContentPart in records + // IndexProvider, indexing simple obj + + // IndexProvider, indexing simple object or ContentPart in records + Factory(); Factory(); // Content Type, ContentPart, ContentField, index record creation. Factory(); // ISession, IContentItemDisplayManager, IClock + Factory(); Factory(); From 6f03e26294d2e6e72ed2ce18936a82b3c99fbadd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 10 Jan 2019 13:01:19 +0100 Subject: [PATCH 35/65] Updating StartLearningHere.md --HG-- branch : issue/OCORE-1 --- StartLearningHere.md | 71 +++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 44 deletions(-) diff --git a/StartLearningHere.md b/StartLearningHere.md index 772d46cf..d75aef61 100644 --- a/StartLearningHere.md +++ b/StartLearningHere.md @@ -1,59 +1,42 @@ -Hi there! +# Hi there! - Learn Orchard Core module development -Good to see you want to learn the ins and outs of Orchard Core module creation. Reading code is always a good way for -this! -We'll guide you on your journey to become an Orchard Core developer. Look for "NEXT STATION" comments in the code to -see where to head next, otherwise look throught the code as you like. +## Introduction -Before you dive deep into this module it'd be best if you made sure that you have done the following: * You know how -ASP.NET Core works. It's important that you understand how ASP.NET Core works or - generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at - https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. -* You've read through the documentation at https://orchardcore.readthedocs.io (at least the "About Orchard Core" -section, - but it would be great if you'd read the whole documentation). -* You know Orchard Core from a user's perspecive and understand the concepts underlying the system. * If you want to be -more familiar with Orchard Core fundamentals you can watch some of the following video about the - beta2 capabalities here: https://www.youtube.com/watch?v=6ZaqWmq8Pog or simply pick some of the interesting Orchard - CMS podcasts from this YouTube playlist: - https://www.youtube.com/watch?v=Xu6S2XawyY4&list=PLuskKJW0FhJfOAN3dL0Y0KBMdG1pKESVn -We've invested a lot of time creating this module. If you have ideas regarding it or have found mistakes, please let us -know on the project page: https://github.com/Lombiq/Orchard-Training-Demo-Module +Good to see you want to learn the ins and outs of Orchard Core module creation. Reading code is always a good way for this! -If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at -Orchard Dojo's trainings: https://orcharddojo.net/orchard-training +We'll guide you on your journey to become an Orchard Core developer. Look for "NEXT STATION" comments in the code to see where to head next, otherwise look through the code as you like. -Although the module has no function apart from serving as a demonstration we've written everything in a way that it -really runs and you can try it out in action. There are two ways of creating Orchard Core applications and trying out -this module. The recommended way to try this module out is to grab the full OrchardCore source and copy this module to -the src/OrchardCore.Modules folder and add it to the Solution file. The second way is to create a an Orchard Core -ASP.NET Web Application (simply follow the instructions in the Code Generation Templates section of the documentation) -and adding the Lombiq.TrainingDemo project as reference to it. If you go with the second way you need to replace -project references to NuGet package references. Don't forget to run the solution in Debug mode and break into the code -to be able to look into some specific details! +Before you dive deep into this module it'd be best if you made sure that you have done the following: -After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules -how they solve similar tasks. If you chose to use the simpler way to add this project to Orchard Core then you should -try the other way as well to have the whole Orchard source at your hands: let it be your tutor :-). +* You know how ASP.NET Core works. It's important that you understand how ASP.NET Core works or generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. +* You've read through the documentation at https://orchardcore.readthedocs.io (at least the "About Orchard Core" section, but it would be great if you'd read the whole documentation). +* At the point of developing this module the Orchard Core documentation doesn't explain basic Orchard features and concepts (e.g. Content Items or Content Parts). That's why **some Orchard 1.x documentation will be referenced in the code base**. In these cases these will be explained in the comments as well. +* You know Orchard Core from a user's perspective and understand the concepts underlying the system. +* If you want to be more familiar with Orchard Core fundamentals you can watch some of the following video about the beta2 capabilities here: https://www.youtube.com/watch?v=6ZaqWmq8Pog or simply pick some of the interesting Orchard CMS podcasts from this YouTube playlist: https://www.youtube.com/watch?v=Xu6S2XawyY4&list=PLuskKJW0FhJfOAN3dL0Y0KBMdG1pKESVn -Later on, you may want to take a look at Map.cs (remember, "X marks the spot!") in the project root for reminders -regarding specific solutions. ---- +## Moving forward -FIRST STATION: First of all, let's discuss how a .NET Standard library becomes an Orchard Module. If you look into the -Dependencies of this project you will find either a NuGet reference for the OrchardCore.Module.Targets package or if -you go with the full Orchard Core source code way you can add this particular project as a Project reference. -On the other hand the module manifest file is also required. So... +We've invested a lot of time creating this module. If you have ideas regarding it or have found mistakes, please let us know on the project page: https://github.com/Lombiq/Orchard-Training-Demo-Module + +If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at Orchard Dojo's trainings: https://orcharddojo.net/orchard-training + +After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules how they solve similar tasks. If you chose to use the simpler way to add this project to Orchard Core then you should try the other way as well to have the whole Orchard source at your hands: let it be your tutor :-). + +Later on, you may want to take a look at *Map.cs* (remember, "X marks the spot!") in the project root for reminders regarding specific solutions. + -NEXT STATION: Head over to Manifest.cs. That file is the module's manifest; a Manifest.cs is required for Orchard -modules. +## Let's get started! + + +**FIRST STATION**: First of all, let's discuss how a .NET Standard library becomes an Orchard Module. If you look into the Dependencies of this project you will find either a NuGet reference for the OrchardCore.Module.Targets package or if you go with the full Orchard Core source code way you can add this particular project as a Project reference. + +On the other hand the module manifest file is also required. So... +**NEXT STATION**: Head over to Manifest.cs. That file is the module's manifest; a Manifest.cs is required for Orchard modules. -This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session -(http://www.youtube.com/watch?v=MH9mcodTX-U) and brought to you by the Orchard Hungary team -(http://english.orchardproject.hu/) and Lombiq (https://lombiq.com/). \ No newline at end of file +This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session (http://www.youtube.com/watch?v=MH9mcodTX-U) and brought to you by the Orchard Hungary team (http://english.orchardproject.hu/) and Lombiq (https://lombiq.com/). \ No newline at end of file From c1c2a0b212e9a82e3db6322958af98190beed74a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 10 Jan 2019 13:01:32 +0100 Subject: [PATCH 36/65] Updating documentation in ColorField.Option.cshtml --HG-- branch : issue/OCORE-1 --- Views/ColorField.Option.cshtml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Views/ColorField.Option.cshtml b/Views/ColorField.Option.cshtml index cbab200f..30da04f6 100644 --- a/Views/ColorField.Option.cshtml +++ b/Views/ColorField.Option.cshtml @@ -1,16 +1,18 @@ -@* There is an extensibility to create different editor and display shapes for content fields. This is a setting that -every content fields have. When you attach a content field to the content part or content type you'll see two editors, -one will be the display option the other will be the editor option. You can add new options by adding cshtml or liquid -files with the [FieldName]-[OptionName].Option.cshtml pattern where you can specify your own option name and value. -After this you can create the [FieldName]-[OptionName].Edit.cshtml to create your new editor. This way no coding is -required so you can do it in a liquid theme as well. *@ +@* There is an extensibility to create different editor shapes for content fields. This is a setting that + every content fields have. When you attach a content field to the content part or content type you'll see an editor + for the editor option. You can add new options by adding cshtml or liquid files with the + [FieldName]-[OptionName].Option.cshtml pattern where you can specify your own option name and value. After this you + can create the [FieldName]-[OptionName].Edit.cshtml to create your new editor. This way no coding is required so you + can do it in a liquid theme as well. For detailed documentation see: + https://orchardcore.readthedocs.io/en/latest/OrchardCore.Modules/OrchardCore.ContentFields/README/#creating-custom-editors +*@ @{ string currentEditor = Model.Editor; } @* Now this is a default option with no value. We gave the name Hexadecimal. The ColorField.Edit.cshtml will be applied -as the default editor shape. *@ + as the default editor shape. *@ From 89cec5caf8413219fc5bddcb724bacf26ac53c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 10 Jan 2019 13:07:46 +0100 Subject: [PATCH 37/65] Adding service provider registration reminders --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 3 ++- Drivers/BookDisplayDriver.cs | 3 ++- Drivers/ColorFieldDisplayDriver.cs | 2 +- Drivers/PersonPartDisplayDriver.cs | 2 +- Fields/ColorField.cs | 4 +++- Indexes/BookIndex.cs | 4 ++-- Indexes/PersonPartIndex.cs | 1 + Indexing/ColorFieldIndexHandler.cs | 3 ++- Migrations/BookMigrations.cs | 1 + Migrations/PersonMigrations.cs | 3 ++- Models/PersonPart.cs | 2 +- ResourceManifest.cs | 3 ++- Settings/ColorFieldSettingsDriver.cs | 2 +- Startup.cs | 2 ++ 14 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index 8c3fef3b..ef48c9f2 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -21,7 +21,8 @@ namespace Lombiq.TrainingDemo.Controllers public class DisplayManagementController : Controller, IUpdateModel { // The core display management features can be used by the IDisplayManagement service. The generic parameter - // will be the object that needs to be displayed on the UI somehow. + // will be the object that needs to be displayed on the UI somehow. Don't forget to register this generic class + // to the service provider (see: Startup.cs). private readonly IDisplayManager _bookDisplayManager; diff --git a/Drivers/BookDisplayDriver.cs b/Drivers/BookDisplayDriver.cs index 3beac70d..8c7a8546 100644 --- a/Drivers/BookDisplayDriver.cs +++ b/Drivers/BookDisplayDriver.cs @@ -11,7 +11,8 @@ namespace Lombiq.TrainingDemo.Drivers // can create a driver for any object (persisted or not-persisted) where you can implement their specific logic for // generating reusable shapes. In case of an editor shape the model update and custom validation is also done in // these drivers. Finally, you can create multiple drivers for one object and the DisplayDriver will make sure that - // all of your drivers are used and their specific logic will be executed. + // all of your drivers are used and their specific logic will be executed. Don't forget to register this class to + // the service provider (see: Startup.cs). public class BookDisplayDriver : DisplayDriver { // So we have a Book object and we want to register some display shapes. For this you need to override the diff --git a/Drivers/ColorFieldDisplayDriver.cs b/Drivers/ColorFieldDisplayDriver.cs index 2b4d376a..34ce2f0d 100644 --- a/Drivers/ColorFieldDisplayDriver.cs +++ b/Drivers/ColorFieldDisplayDriver.cs @@ -13,7 +13,7 @@ namespace Lombiq.TrainingDemo.Drivers { // You shouldn't be surprised - content fields also have display drivers. ContentFieldDisplayDriver is specifically - // for content fields. + // for content fields. Don't forget to register this class to the service provider (see: Startup.cs). public class ColorFieldDisplayDriver : ContentFieldDisplayDriver { public IStringLocalizer T { get; set; } diff --git a/Drivers/PersonPartDisplayDriver.cs b/Drivers/PersonPartDisplayDriver.cs index 5e6e3b85..2554ad2e 100644 --- a/Drivers/PersonPartDisplayDriver.cs +++ b/Drivers/PersonPartDisplayDriver.cs @@ -8,7 +8,7 @@ namespace Lombiq.TrainingDemo.Drivers { // Drivers inherited from ContentPartDisplayDrivers have a similar functionality described in the BookDisplayDriver - // but these are for ContentParts. + // but these are for ContentParts. Don't forget to register this class to the service provider (see: Startup.cs). public class PersonPartDisplayDriver : ContentPartDisplayDriver { // A Display method that we already know. This time it's much simpler because we don't want to create multiple diff --git a/Fields/ColorField.cs b/Fields/ColorField.cs index e60e3b73..5f14ee3f 100644 --- a/Fields/ColorField.cs +++ b/Fields/ColorField.cs @@ -7,6 +7,8 @@ namespace Lombiq.TrainingDemo.Fields * class. We want to store a color name and the actual color in HEX so we need two strings for that. * * Conventionally we put these objects in the Fields folder. + * + * You also need to register this class to the service provider (see: Startup.cs). */ public class ColorField : ContentField { @@ -15,4 +17,4 @@ public class ColorField : ContentField } } -// NEXT STATION: Drivers/ColorFieldDisplayDriver \ No newline at end of file +// NEXT STATION: Startup.cs and find the constructor \ No newline at end of file diff --git a/Indexes/BookIndex.cs b/Indexes/BookIndex.cs index d67de2f8..fb00df24 100644 --- a/Indexes/BookIndex.cs +++ b/Indexes/BookIndex.cs @@ -14,8 +14,8 @@ public class BookIndex : MapIndex // These IndexProvider services will provide the mappings between the objects stored in the document database and // the index objects stored in records. When a Book object is being saved by the ISession service an index record - // will also be stored in the related index table. - // You need to register this service to the service provider. + // will also be stored in the related index table. Don't forget to register this class to the service provider + // (see: Startup.cs). public class BookIndexProvider : IndexProvider { public override void Describe(DescribeContext context) diff --git a/Indexes/PersonPartIndex.cs b/Indexes/PersonPartIndex.cs index 01961126..eaae18a7 100644 --- a/Indexes/PersonPartIndex.cs +++ b/Indexes/PersonPartIndex.cs @@ -16,6 +16,7 @@ public class PersonPartIndex : MapIndex public DateTime? BirthDateUtc { get; set; } } + // Don't forget to register this class to the service provider (see: Startup.cs). public class PersonPartIndexProvider : IndexProvider { // Notice that ContentItem is what we are describing the provider for not the part. diff --git a/Indexing/ColorFieldIndexHandler.cs b/Indexing/ColorFieldIndexHandler.cs index aa8c4078..c5e879d6 100644 --- a/Indexing/ColorFieldIndexHandler.cs +++ b/Indexing/ColorFieldIndexHandler.cs @@ -6,7 +6,8 @@ namespace Lombiq.TrainingDemo.Indexing { // IndexHandlers are different from IndexProviders. While IndexProviders will store values in the SQL database to // index documents these will use an actual index provider (e.g. Lucene) index data. This way no database query is - // required when you want to use a search widget on your website. + // required when you want to use a search widget on your website. Don't forget to register this class to the + // service provider (see: Startup.cs). public class ColorFieldIndexHandler : ContentFieldIndexHandler { public override Task BuildIndexAsync(ColorField field, BuildFieldIndexContext context) diff --git a/Migrations/BookMigrations.cs b/Migrations/BookMigrations.cs index efd9f0fd..2897e116 100644 --- a/Migrations/BookMigrations.cs +++ b/Migrations/BookMigrations.cs @@ -10,6 +10,7 @@ namespace Lombiq.TrainingDemo.Migrations { + // Don't forget to register this class to the service provider (see: Startup.cs). public class BookMigrations : DataMigration { IContentDefinitionManager _contentDefinitionManager; diff --git a/Migrations/PersonMigrations.cs b/Migrations/PersonMigrations.cs index a2dfe8ca..ee8a4c18 100644 --- a/Migrations/PersonMigrations.cs +++ b/Migrations/PersonMigrations.cs @@ -9,7 +9,8 @@ namespace Lombiq.TrainingDemo.Migrations { - // Here's another migrations file but specifically for Person-related operations. + // Here's another migrations file but specifically for Person-related operations. Don't forget to register this + // class to the service provider (see: Startup.cs). public class PersonMigrations : DataMigration { IContentDefinitionManager _contentDefinitionManager; diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs index d8c8f956..479e3cd4 100644 --- a/Models/PersonPart.cs +++ b/Models/PersonPart.cs @@ -7,7 +7,7 @@ namespace Lombiq.TrainingDemo.Models // Now let's see what practices Orchard Core provides when it stores data. Here you can see a ContentPart. Each // ContentPart can be part of one or more content types. Using the content type you can create ContentItems that is // the most important part of the Orchard Core content management. Here is a PersonPart containing some properties - // of a person. + // of a person. You also need to register this class to the service provider (see: Startup.cs). public class PersonPart : ContentPart { // A ContentPart is serialized as a JSON object so you need to keep this in mind when creating properties. For diff --git a/ResourceManifest.cs b/ResourceManifest.cs index 949a5040..b5ab1e9c 100644 --- a/ResourceManifest.cs +++ b/ResourceManifest.cs @@ -2,7 +2,8 @@ namespace Lombiq.TrainingDemo { - // ResourceManifest classes implement IResourceManifestProvider and possess the BuildManifests method. + // ResourceManifest classes implement IResourceManifestProvider and possess the BuildManifests method. Don't forget + // to register this class to the service provider (see: Startup.cs). public class ResourceManifest : IResourceManifestProvider { // This is the only method to implement. Using it we're going to register some static resources diff --git a/Settings/ColorFieldSettingsDriver.cs b/Settings/ColorFieldSettingsDriver.cs index 92f5de01..11c8b55e 100644 --- a/Settings/ColorFieldSettingsDriver.cs +++ b/Settings/ColorFieldSettingsDriver.cs @@ -7,7 +7,7 @@ namespace Lombiq.TrainingDemo.Settings { // It's in the Settings folder by convention but it's the same DisplayDriver as the others, except, it also has a - // specific base class. + // specific base class. Don't forget to register this class to the service provider (see: Startup.cs). public class ColorFieldSettingsDriver : ContentPartFieldDefinitionDisplayDriver { // This won't have a Display override since it wouldn't make too much sense. diff --git a/Startup.cs b/Startup.cs index a347e95a..e0346e9d 100644 --- a/Startup.cs +++ b/Startup.cs @@ -33,6 +33,8 @@ static Startup() TemplateContext.GlobalMemberAccessStrategy.Register(); TemplateContext.GlobalMemberAccessStrategy.Register(); + + // NEXT STATION: Drivers/ColorFieldDisplayDriver } From 0d70ba819fedc921ac74f7c9093432a923bae40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 10 Jan 2019 13:25:40 +0100 Subject: [PATCH 38/65] Updating commenting styling, deleting unnecessary files --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 6 ++--- Controllers/YourFirstOrchardCoreController.cs | 4 +--- Drivers/BookDisplayDriver.cs | 21 ------------------ Fields/ColorField.cs | 19 +++++++++------- Indexing/ColorFieldIndexHandler.cs | 11 ++++++---- Migrations/BookMigrations.cs | 16 ++++++-------- Migrations/PersonMigrations.cs | 18 +++++++-------- Models/PersonPart.cs | 7 ++++++ ResourceManifest.cs | 3 ++- Settings/ColorFieldSettings.cs | 22 +++++++++++-------- StartLearningHere.md | 1 - Startup.cs | 8 ++----- ViewModels/BookViewModel.cs | 15 ------------- ViewModels/PersonPartViewModel.cs | 2 +- 14 files changed, 61 insertions(+), 92 deletions(-) delete mode 100644 ViewModels/BookViewModel.cs diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index ef48c9f2..f1271b39 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -76,7 +76,5 @@ private Book CreateDemoBook() => } } -/* - * If you've finished with both actions (and their .cshtml files as well), then - * NEXT STATION: Controllers/BasicOrchardCoreServicesController is what's next. - */ +// If you've finished with both actions (and their .cshtml files as well), then +// NEXT STATION: Controllers/BasicOrchardCoreServicesController is what's next. \ No newline at end of file diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index db49012f..3e7f7674 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -65,6 +65,4 @@ public ActionResult NotifyMe() } } -/* - * NEXT STATION: Controllers/DisplayManagementController - */ +// NEXT STATION: Controllers/DisplayManagementController diff --git a/Drivers/BookDisplayDriver.cs b/Drivers/BookDisplayDriver.cs index 8c7a8546..69cf910b 100644 --- a/Drivers/BookDisplayDriver.cs +++ b/Drivers/BookDisplayDriver.cs @@ -44,26 +44,5 @@ public override IDisplayResult Display(Book model) => // Now let's see what those zones are and slowly clarify all these things you've seen above! // NEXT STATION: Views/Book.cshtml. - - public override IDisplayResult Edit(Book book) => - Initialize("Book_Edit", model => - { - model.Author = book.Author; - model.Title = book.Title; - model.Description = book.Description; - }); - - public override async Task UpdateAsync(Book book, IUpdateModel updater) - { - var viewModel = new BookViewModel(); - - await updater.TryUpdateModelAsync(viewModel, Prefix); - - book.Title = viewModel.Title; - book.Author = viewModel.Author; - book.Description = viewModel.Description; - - return Edit(book); - } } } \ No newline at end of file diff --git a/Fields/ColorField.cs b/Fields/ColorField.cs index 5f14ee3f..dfa2ea7b 100644 --- a/Fields/ColorField.cs +++ b/Fields/ColorField.cs @@ -1,15 +1,18 @@ +/* + * Now we will develop a content field. Just like with content part development, we'll start with creating a model + * class. We want to store a color name and the actual color in HEX so we need two strings for that. + * + * Conventionally we put these objects in the Fields folder. + * + * To learn more about content fields see: + * https://orchardcore.readthedocs.io/en/latest/OrchardCore.Modules/OrchardCore.ContentFields/README/ + */ + using OrchardCore.ContentManagement; namespace Lombiq.TrainingDemo.Fields { - /* - * Now we will develop a content field. Just like with content part development, we'll start with creating a model - * class. We want to store a color name and the actual color in HEX so we need two strings for that. - * - * Conventionally we put these objects in the Fields folder. - * - * You also need to register this class to the service provider (see: Startup.cs). - */ + // You also need to register this class to the service provider (see: Startup.cs). public class ColorField : ContentField { public string Value { get; set; } diff --git a/Indexing/ColorFieldIndexHandler.cs b/Indexing/ColorFieldIndexHandler.cs index c5e879d6..6c5009c9 100644 --- a/Indexing/ColorFieldIndexHandler.cs +++ b/Indexing/ColorFieldIndexHandler.cs @@ -1,13 +1,16 @@ +/* + * IndexHandlers are different from IndexProviders. While IndexProviders will store values in the SQL database to index + * documents these will use an actual index provider (e.g. Lucene) index data. This way no database query is required + * when you want to use a search widget on your website. + */ + using System.Threading.Tasks; using Lombiq.TrainingDemo.Fields; using OrchardCore.Indexing; namespace Lombiq.TrainingDemo.Indexing { - // IndexHandlers are different from IndexProviders. While IndexProviders will store values in the SQL database to - // index documents these will use an actual index provider (e.g. Lucene) index data. This way no database query is - // required when you want to use a search widget on your website. Don't forget to register this class to the - // service provider (see: Startup.cs). + // Don't forget to register this class to the service provider (see: Startup.cs). public class ColorFieldIndexHandler : ContentFieldIndexHandler { public override Task BuildIndexAsync(ColorField field, BuildFieldIndexContext context) diff --git a/Migrations/BookMigrations.cs b/Migrations/BookMigrations.cs index 2897e116..92897d3d 100644 --- a/Migrations/BookMigrations.cs +++ b/Migrations/BookMigrations.cs @@ -36,12 +36,10 @@ public int Create() return 2; } - /* - * This is an update method. It is used to modify the existing schema. Update methods will be run when the - * module was already enabled before and the create method was run. The X in UpdateFromX is the number of the - * update (the method's name is conventional). It means: "run this update if the module's current migration - * version is X". This method will run if it's 1. - */ + // This is an update method. It is used to modify the existing schema. Update methods will be run when the + // module was already enabled before and the create method was run. The X in UpdateFromX is the number of the + // update (the method's name is conventional). It means: "run this update if the module's current migration + // version is X". This method will run if it's 1. public int UpdateFrom1() { // The initial version of our module did not store the book's title. We quickly fix the issue by pushing @@ -54,7 +52,7 @@ public int UpdateFrom1() return 2; } - - // NEXT STATION: Controllers/StoreController and go to the CreateBooksPost action where we previously left. } -} \ No newline at end of file +} + +// NEXT STATION: Controllers/StoreController and go to the CreateBooksPost action where we previously left. \ No newline at end of file diff --git a/Migrations/PersonMigrations.cs b/Migrations/PersonMigrations.cs index ee8a4c18..24039249 100644 --- a/Migrations/PersonMigrations.cs +++ b/Migrations/PersonMigrations.cs @@ -36,13 +36,11 @@ public int Create() Hint = "Person's biography" }))); - /* - * We create a new content type. Note that there's only an alter method: this will create the type if it - * doesn't exist or modify it if it does. Make sure you understand what content types are: - * http://docs.orchardproject.net/Documentation/Content-types. The content type's name is arbitrary, but - * choose a meaningful one. Notice that we attach parts by specifying their name. For our own parts we use - * nameof(): this is not mandatory but serves great if we change the part's name during development. - */ + // We create a new content type. Note that there's only an alter method: this will create the type if it + // doesn't exist or modify it if it does. Make sure you understand what content types are: + // http://docs.orchardproject.net/Documentation/Content-types. The content type's name is arbitrary, but + // choose a meaningful one. Notice that we attach parts by specifying their name. For our own parts we use + // nameof(): this is not mandatory but serves great if we change the part's name during development. _contentDefinitionManager.AlterTypeDefinition("Person", builder => builder .Creatable() .Listable() @@ -55,9 +53,9 @@ public int Create() .Column(nameof(PersonPartIndex.ContentItemId), c => c.WithLength(26)) ); - // NEXT STATION: Indexes/PersonPartIndex - return 1; } } -} \ No newline at end of file +} + +// NEXT STATION: Indexes/PersonPartIndex \ No newline at end of file diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs index 479e3cd4..d45db9dd 100644 --- a/Models/PersonPart.cs +++ b/Models/PersonPart.cs @@ -1,3 +1,10 @@ +/* + * Now let's see what practices Orchard Core provides when it stores data. Here you can see a ContentPart. Each + * ContentPart can be part of one or more content types. Using the content type you can create ContentItems that is the + * most important part of the Orchard Core content management. Here is a PersonPart containing some properties of a + * person. + */ + using System; using OrchardCore.ContentFields.Fields; using OrchardCore.ContentManagement; diff --git a/ResourceManifest.cs b/ResourceManifest.cs index b5ab1e9c..2c724603 100644 --- a/ResourceManifest.cs +++ b/ResourceManifest.cs @@ -3,7 +3,8 @@ namespace Lombiq.TrainingDemo { // ResourceManifest classes implement IResourceManifestProvider and possess the BuildManifests method. Don't forget - // to register this class to the service provider (see: Startup.cs). + // to register this class to the service provider (see: Startup.cs). If you want to learn more about resources see: + // https://orchardcore.readthedocs.io/en/latest/OrchardCore.Modules/OrchardCore.Resources/README/ public class ResourceManifest : IResourceManifestProvider { // This is the only method to implement. Using it we're going to register some static resources diff --git a/Settings/ColorFieldSettings.cs b/Settings/ColorFieldSettings.cs index ba21d482..a81fc023 100644 --- a/Settings/ColorFieldSettings.cs +++ b/Settings/ColorFieldSettings.cs @@ -1,8 +1,11 @@ +/* + * Every content part and content field can have settings.If you have a PersonPart content part where you use + * ColorField these settings will be applied on every content item where the PersonPart is in present, however, if you + * have multiple ColorFields, each fields will have their own settings.In our case we have three settings. + */ + namespace Lombiq.TrainingDemo.Settings { - // Every content part and content field can have settings. If you have a PersonPart content part where you use - // ColorField these settings will be applied on every content item where the PersonPart is in present, however, if - // you have multiple ColorFields, each fields will have their own settings. In our case we have three settings. public class ColorFieldSettings { // We'll use this setting to determine whether the value of the field is required to be given by the user. @@ -14,10 +17,11 @@ public class ColorFieldSettings // The label to be used on the editor and the display shape. public string Label { get; set; } } +} + +// How can these settings be edited? If you attach a content field to a content part / content type you can set +// these values there (see: Migrations/PersonMigrations where the Biography field is being added to the +// PersonPart). If you attach the field on the dashboard yourself then Orchard Core will display its editor. Editor +// of an object like this? You know what you need to do... Create a DisplayDriver for this! - // How can these settings be edited? If you attach a content field to a content part / content type you can set - // these values there (see: Migrations/PersonMigrations where the Biography field is being added to the - // PersonPart). If you attach the field on the dashboard yourself then Orchard Core will display its editor. - // Editor of an object like this? You know what you need to do... Create a DisplayDriver for this! - // NEXT STATION: Settings/ColorFieldSettingsDriver -} \ No newline at end of file +// NEXT STATION: Settings/ColorFieldSettingsDriver \ No newline at end of file diff --git a/StartLearningHere.md b/StartLearningHere.md index d75aef61..7ab2d025 100644 --- a/StartLearningHere.md +++ b/StartLearningHere.md @@ -13,7 +13,6 @@ Before you dive deep into this module it'd be best if you made sure that you hav * You know how ASP.NET Core works. It's important that you understand how ASP.NET Core works or generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. * You've read through the documentation at https://orchardcore.readthedocs.io (at least the "About Orchard Core" section, but it would be great if you'd read the whole documentation). -* At the point of developing this module the Orchard Core documentation doesn't explain basic Orchard features and concepts (e.g. Content Items or Content Parts). That's why **some Orchard 1.x documentation will be referenced in the code base**. In these cases these will be explained in the comments as well. * You know Orchard Core from a user's perspective and understand the concepts underlying the system. * If you want to be more familiar with Orchard Core fundamentals you can watch some of the following video about the beta2 capabilities here: https://www.youtube.com/watch?v=6ZaqWmq8Pog or simply pick some of the interesting Orchard CMS podcasts from this YouTube playlist: https://www.youtube.com/watch?v=Xu6S2XawyY4&list=PLuskKJW0FhJfOAN3dL0Y0KBMdG1pKESVn diff --git a/Startup.cs b/Startup.cs index e0346e9d..3d548403 100644 --- a/Startup.cs +++ b/Startup.cs @@ -64,12 +64,8 @@ public override void ConfigureServices(IServiceCollection services) public override void Configure(IApplicationBuilder builder, IRouteBuilder routes, IServiceProvider serviceProvider) { - routes.MapAreaRoute( - name: "TrainingDemo", - areaName: "Lombiq.TrainingDemo", - template: "TrainingDemo/NotifyMe", - defaults: new { controller = "YourFirstOrchardCore", action = "NotifyMe" } - ); + // You can put service configuration here as you would do it in other ASP.NET Core applications. If you + // don't need it you can skip overriding it. } } } \ No newline at end of file diff --git a/ViewModels/BookViewModel.cs b/ViewModels/BookViewModel.cs deleted file mode 100644 index 9fbb7c55..00000000 --- a/ViewModels/BookViewModel.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Lombiq.TrainingDemo.ViewModels -{ - public class BookViewModel - { - [Required] - public string Title { get; set; } - - [Required] - public string Author { get; set; } - - public string Description { get; set; } - } -} \ No newline at end of file diff --git a/ViewModels/PersonPartViewModel.cs b/ViewModels/PersonPartViewModel.cs index c3870d7f..74f740b4 100644 --- a/ViewModels/PersonPartViewModel.cs +++ b/ViewModels/PersonPartViewModel.cs @@ -9,7 +9,7 @@ namespace Lombiq.TrainingDemo.ViewModels { - // IValidateObject is az ASP.NET Core feature to use on view models where the model binder will automatically + // IValidateObject is an ASP.NET Core feature to use on view models where the model binder will automatically // execute the Validate method which will return any validation error. public class PersonPartViewModel : IValidatableObject { From eb6e1fde82154a8f0ac5fa0019673d4c73cdfd62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Bartha?= Date: Thu, 10 Jan 2019 14:00:29 +0100 Subject: [PATCH 39/65] Updating comments and readme --HG-- branch : issue/OCORE-1 --- Manifest.cs | 6 ++++-- Migrations/PersonMigrations.cs | 6 ++++++ Readme.md | 26 +++++++++++++------------- StartLearningHere.md | 4 ++-- 4 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Manifest.cs b/Manifest.cs index 35a425e6..8fc7d561 100644 --- a/Manifest.cs +++ b/Manifest.cs @@ -6,7 +6,7 @@ // Your name, company or any name that identifies the developers working on the project. Author = "Lombiq", // Optionally you can add a website URL (e.g. your company's website, GitHub repository URL). - Website = "http://orchardproject.net", + Website = "https://github.com/Lombiq/Orchard-Training-Demo-Module", // Version of the module. Version = "2.0", // Short description of the module. It will be displayed on the Dashboard. @@ -17,7 +17,9 @@ Category = "Training", // Modules can have dependencies which are other module names (name of the project) or if these modules have // subfeatures then the name of the feature. If you use any service, taghelper etc. coming from an Orchard Core - // feature then you need to include them in this list. + // feature then you need to include them in this list. Orchard Core will make sure to enable all dependent modules + // when you enable a module that has dependencies. Without this some features would not work even if the assembly + // is referenced in the project. Dependencies = new[] { "OrchardCore.Contents", diff --git a/Migrations/PersonMigrations.cs b/Migrations/PersonMigrations.cs index 24039249..2853c807 100644 --- a/Migrations/PersonMigrations.cs +++ b/Migrations/PersonMigrations.cs @@ -34,6 +34,12 @@ public int Create() .WithSettings(new TextFieldSettings { Hint = "Person's biography" + }) + .WithSettings(new ContentPartFieldSettings + { + // This is an extension point for making multiple editor flavor for a content field or content + // part. We'll learn this feature later with the ContentFields. + Editor = "TextArea" }))); // We create a new content type. Note that there's only an alter method: this will create the type if it diff --git a/Readme.md b/Readme.md index 96f9725d..082c3407 100644 --- a/Readme.md +++ b/Readme.md @@ -6,31 +6,31 @@ Demo Orchard Core module for training purposes. -**If you are interested in Orchard 1.x training materials and Orchard trainings please visit [Orchard Dojo](https://orcharddojo.net/).** +**If you are interested in training materials and Orchard trainings please visit [Orchard Dojo](https://orcharddojo.net/).** ## How to Start -You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core Nuget packeges, however, it's harder to look under the hood of Orchard Core features. +You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core Nuget packages, however, it's harder to look under the hood of Orchard Core features. ### Using a full Orchard Core source -* Open an Orchard Core solution -* Add this project to the solution -* Add this project as a reference to OrchardCore.Application.Cms.Targets project (it's in the src/Targets solution folder) -* Run the OrchardCore.Cms.Web project (F5 or CTRL+F5) -* Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) +1. Open an Orchard Core solution +2. Add this project to the solution +3. Add this project as a reference to OrchardCore.Application.Cms.Targets project (it's in the src/Targets solution folder) +4. Run the OrchardCore.Cms.Web project (F5 or CTRL+F5) +5. Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) ### Using Nuget packages -* Open a web project that uses Orchard Core Nuget packages -* Add this project to the solution -* Add this project as a reference to web project -* Replace project references with Orchard Core Nuget package references with the same name as the project references -* Run the web project (F5 or CTRL+F5) -* Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) +1. Open a web project that uses Orchard Core Nuget packages +2. Add this project to the solution +3. Add this project as a reference to web project +4. Replace project references with Orchard Core Nuget package references with the same name as the project references +5. Run the web project (F5 or CTRL+F5) +6. Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) ## Using this module for training purposes diff --git a/StartLearningHere.md b/StartLearningHere.md index 7ab2d025..c76d4421 100644 --- a/StartLearningHere.md +++ b/StartLearningHere.md @@ -24,7 +24,7 @@ We've invested a lot of time creating this module. If you have ideas regarding i If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at Orchard Dojo's trainings: https://orcharddojo.net/orchard-training -After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules how they solve similar tasks. If you chose to use the simpler way to add this project to Orchard Core then you should try the other way as well to have the whole Orchard source at your hands: let it be your tutor :-). +After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules on how they solve similar tasks. If you choose to use the simpler way to add this project to Orchard Core then you should try the other way as well to have the whole Orchard source at your hands: let it be your tutor :-). Later on, you may want to take a look at *Map.cs* (remember, "X marks the spot!") in the project root for reminders regarding specific solutions. @@ -38,4 +38,4 @@ On the other hand the module manifest file is also required. So... **NEXT STATION**: Head over to Manifest.cs. That file is the module's manifest; a Manifest.cs is required for Orchard modules. -This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session (http://www.youtube.com/watch?v=MH9mcodTX-U) and brought to you by the Orchard Hungary team (http://english.orchardproject.hu/) and Lombiq (https://lombiq.com/). \ No newline at end of file +This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session (http://www.youtube.com/watch?v=MH9mcodTX-U) and brought to you by Lombiq (https://lombiq.com/). \ No newline at end of file From b0ce8bdd3a459c1b9abcce7bd5d225bd33b50a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Sat, 12 Jan 2019 18:49:27 +0100 Subject: [PATCH 40/65] Fixing StartLearningHere.md reference in Readme --HG-- branch : issue/OCORE-1 --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 082c3407..4eac078c 100644 --- a/Readme.md +++ b/Readme.md @@ -35,7 +35,7 @@ You can use this module as part of a vanilla Orchard Core source that including ## Using this module for training purposes -If your module compiles and you are able to enable this module on the dashboard then head over to the **StartHere.txt** file and start exploring all the goodies you can do in Orchard Core. +If your module compiles and you are able to enable this module on the dashboard then head over to the **[StartLearningHere.md](StartLearningHere.md)** file and start exploring all the goodies you can do in Orchard Core. Also if you are brave enough to not follow any guide or you want to start the guide from somewhere else then go to the **Map.cs** file and jump to any class you are interested in. From 75078cdc017445c803c065ec18dd45c6cfa14556 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Sat, 12 Jan 2019 21:09:56 +0100 Subject: [PATCH 41/65] A bit of housekeeping in the comments, code styling --HG-- branch : issue/OCORE-1 --- Controllers/DisplayManagementController.cs | 18 +++++----- Controllers/YourFirstOrchardCoreController.cs | 15 +++++--- Drivers/BookDisplayDriver.cs | 8 +++-- Gulpfile.js | 6 ++-- Map.cs | 2 +- Readme.md | 35 ++++++++++--------- StartLearningHere.md | 12 +++---- Startup.cs | 4 +-- Views/Book.cshtml | 6 ++-- Views/DisplayManagement/DisplayBook.cshtml | 2 +- Views/_ViewImports.cshtml | 2 +- 11 files changed, 60 insertions(+), 50 deletions(-) diff --git a/Controllers/DisplayManagementController.cs b/Controllers/DisplayManagementController.cs index f1271b39..6a571695 100644 --- a/Controllers/DisplayManagementController.cs +++ b/Controllers/DisplayManagementController.cs @@ -1,7 +1,7 @@ /* * In this section you will learn how Orchard Core deals with displaying various information on the UI using reusable - * components shapes. This is a very huge and powerful part of Orchard Core, here you will learn the basics of Display - * Management. + * components called shapes. This is a very huge and powerful part of Orchard Core, here you will learn the basics of + * Display Management. * * To demonstrate this basic functionality, we will create two slightly different pages for displaying information * about a book. @@ -15,14 +15,14 @@ namespace Lombiq.TrainingDemo.Controllers { - // Notice, that the controller implements the IUpdateModel interface. This interface encapsulates the properties - // and methods related to ASP.NET Core MVC model binding. Orchard Core needs this model binding functionality - // outside the controllers (you will see it later). + // Notice that the controller implements the IUpdateModel interface. This interface encapsulates the properties and + // methods related to ASP.NET Core MVC model binding. Orchard Core needs this model binding functionality outside + // the controllers (you will see it later). public class DisplayManagementController : Controller, IUpdateModel { - // The core display management features can be used by the IDisplayManagement service. The generic parameter - // will be the object that needs to be displayed on the UI somehow. Don't forget to register this generic class - // to the service provider (see: Startup.cs). + // The core display management features can be used via the IDisplayManager service. The generic parameter will + // be the object that needs to be displayed on the UI somehow. Don't forget to register this generic class with + // the service provider (see: Startup.cs). private readonly IDisplayManager _bookDisplayManager; @@ -33,6 +33,7 @@ public DisplayManagementController(IDisplayManager bookDisplayManager) // First, create a page that will display a summary and some additional data of the book. + // See it under /Lombiq.TrainingDemo/DisplayManagement/DisplayBook. public async Task DisplayBook() { // For demonstration purposes create a dummy book object. @@ -49,6 +50,7 @@ public async Task DisplayBook() } // Let's generate another Book display shape, but now with a display type. + // See it under /Lombiq.TrainingDemo/DisplayManagement/DisplayBookDescription. public async Task DisplayBookDescription() { // Generate another book object to be used for demonstration purposes. diff --git a/Controllers/YourFirstOrchardCoreController.cs b/Controllers/YourFirstOrchardCoreController.cs index 3e7f7674..74c6d7c2 100644 --- a/Controllers/YourFirstOrchardCoreController.cs +++ b/Controllers/YourFirstOrchardCoreController.cs @@ -42,17 +42,22 @@ public YourFirstOrchardCoreController( // in Orchard Core right after enabling the module. The route for this action will be // /Lombiq.TrainingDemo/YourFirstOrchardCore/Index. public ActionResult Index() => - // Simple texts can be localized using the IStringLocalizer service as you can see below. + // Simple texts can be localized using the IStringLocalizer service as you can see below. To learn more + // about how localization works in Orchard check out the docs: + // https://orchardcore.readthedocs.io/en/latest/OrchardCore.Modules/OrchardCore.Localization/README/ View(new { Message = T["Hello you!"] }); // Let's see some custom routing here. This attribute will override the default route and use this one. [Route("TrainingDemo/NotifyMe")] public ActionResult NotifyMe() { - // ILogger is an ASP.NET Core service that will write something in the specific log files. In Orchard Core - // NLog is used for logging and the error level is "Error" by default. You can find the error log in the - // /App_Data/logs/orchard-log-[date].log file. Logger can be configured in the NLog.config file in the web - // project (e.g. OrchardCore.Cms.Web). + // ILogger is an ASP.NET Core service that will write something into the specific log files. In Orchard + // Core NLog is used for logging and the error level is "Error" by default. You can find the error log in + // the /App_Data/logs/orchard-log-[date].log file. Logging can be configured in the NLog.config file in the + // web project (e.g. OrchardCore.Cms.Web). Oh, and one more thing: if you install the Lombiq Orchard Visual + // Studio Extension it'll provide you a handy Error Log Watcher which lights up if there's a new error! + // Check it out here: + // https://marketplace.visualstudio.com/items?itemName=LombiqVisualStudioExtension.LombiqOrchardVisualStudioExtension _logger.LogError("You have been notified about some error!"); // INotifier is an Orchard Core service to send messages to the user. This service can be used almost diff --git a/Drivers/BookDisplayDriver.cs b/Drivers/BookDisplayDriver.cs index 69cf910b..f896e3b0 100644 --- a/Drivers/BookDisplayDriver.cs +++ b/Drivers/BookDisplayDriver.cs @@ -23,7 +23,9 @@ public override IDisplayResult Display(Book model) => // from a driver method - won't necessarily be displayed all at once! Combine( // Here we define a shape for the Title. It's not necessary to split these to atomic pieces but it - // would make sense to make a reusable shape for the title. In the Location helper you define a + // would make sense to make a reusable shape for the title, and it also makes overriding just these + // pieces possible (like you hand this module over to somebody and they want to display the title + // differently on their site, without modifying your module). In the Location helper you define a // position for the shape. "Header" means that it will be displayed in the Header zone. "1" means that // it will be the first in the Header zone. Soon you will see what the zones are. View("Book_Display_Title", model) @@ -34,8 +36,8 @@ public override IDisplayResult Display(Book model) => // Create a separate shape for the cover photo. This will go to a different zone, the "Cover" zone. View("Book_Display_Cover", model) .Location("Cover: 1"), - // The shape for the description will be the first in the Content zone. Although, you can see another - // parameter here, this is the display type. It is used to differentiate circumstances of displaying a + // The shape for the description will be the first in the Content zone. However, you can see another + // parameter here, that is the display type. It is used to differentiate circumstances of displaying a // shape. Let's say you want to display Title, Author and Cover all the time (no shape type parameter), // but the description will be displayed only if the display type is "Description". You'll see an // example for that. diff --git a/Gulpfile.js b/Gulpfile.js index 577fc0f0..f186fbba 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -1,10 +1,10 @@ -// There are multiple ways of managing your resources (including scripts, stylesheets, images etc.). OrchardCore itself -// provide its own pipeline for it using an Assets.json file. We don't use it this time but check the +// There are multiple ways of managing your resources (including scripts, stylesheets, images etc.). Orchard Core +// itself provides its own pipeline for it using an Assets.json file. We don't use it this time but check the // http://docs.orchardproject.net/en/latest/Documentation/Processing-client-side-assets/ documentation for more // information. // Here you will see a standalone Gulpfile for copying third-party resources from the node_modules folder to wwwroot -// folder and also compiling our own resources (styles and scripts) and moving the resoults to the wwwroot folder as +// folder and also compiling our own resources (styles and scripts) and moving the results to the wwwroot folder as // well. const gulp = require("gulp"); diff --git a/Map.cs b/Map.cs index 21a0349a..a53fdd6a 100644 --- a/Map.cs +++ b/Map.cs @@ -19,7 +19,7 @@ namespace Lombiq.TrainingDemo { static class Map { - private static T Factory() => default(T); + private static T Factory() => default; private static void Treasure() { diff --git a/Readme.md b/Readme.md index 4eac078c..55fd54ea 100644 --- a/Readme.md +++ b/Readme.md @@ -4,38 +4,40 @@ ## Project Description -Demo Orchard Core module for training purposes. +Demo Orchard Core module for training purposes guiding you to become an Orchard developer. **If you are interested in training materials and Orchard trainings please visit [Orchard Dojo](https://orcharddojo.net/).** ## How to Start -You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core Nuget packages, however, it's harder to look under the hood of Orchard Core features. +You can use this module as part of a vanilla Orchard Core source that including the full source code - which is the recommended way. You can use it as part of a solution the uses Orchard Core NuGet packages, however, it's harder to look under the hood of Orchard Core features. + +The module assumes that you have a good understanding of basic Orchard concepts, and that you can get around the Orchard admin area (the [official documentation](https://orchardcore.readthedocs.io/en/latest/) may help you with that). You should also be familiar with how to use Visual Studio and write C#, as well as the concepts of ASP.NET Core MVC. ### Using a full Orchard Core source -1. Open an Orchard Core solution -2. Add this project to the solution -3. Add this project as a reference to OrchardCore.Application.Cms.Targets project (it's in the src/Targets solution folder) -4. Run the OrchardCore.Cms.Web project (F5 or CTRL+F5) -5. Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) +1. Open an Orchard Core solution. You can download or `git clone` Orchard from [GitHub](https://github.com/OrchardCMS/OrchardCore/). +2. Add this project to the solution (it doesn't matter which solution folder you use). +3. Add this project as a reference to `OrchardCore.Application.Cms.Targets` project (it's in the *src/Targets* solution folder). +4. Set the `OrchardCore.Cms.Web` project as the startup project if it isn't already and run it (F5 or CTRL+F5). +5. Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (*~/OrchardCore.Features/Admin/Features*). -### Using Nuget packages +### Using NuGet packages -1. Open a web project that uses Orchard Core Nuget packages -2. Add this project to the solution -3. Add this project as a reference to web project -4. Replace project references with Orchard Core Nuget package references with the same name as the project references -5. Run the web project (F5 or CTRL+F5) -6. Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (~/OrchardCore.Features/Admin/Features) +1. Open a web project that uses Orchard Core NuGet packages. +2. Add this project to the solution. +3. Add this project as a reference to web project. +4. Replace project references with Orchard Core NuGet package references with the same name as the project references. +5. Run the web project (F5 or CTRL+F5). +6. Setup the website using any recipe except "Blank", log in and enable this module on the Dashboard (*~/OrchardCore.Features/Admin/Features*) ## Using this module for training purposes -If your module compiles and you are able to enable this module on the dashboard then head over to the **[StartLearningHere.md](StartLearningHere.md)** file and start exploring all the goodies you can do in Orchard Core. +If your module compiles and you are able to enable this module on the dashboard then head over to the **[StartLearningHere.md](StartLearningHere.md)** file and start exploring all the great things you can do in Orchard Core. Also if you are brave enough to not follow any guide or you want to start the guide from somewhere else then go to the **Map.cs** file and jump to any class you are interested in. @@ -47,7 +49,6 @@ The module's source is available in two public source repositories, automaticall - [https://bitbucket.org/Lombiq/orchard-training-demo-module](https://bitbucket.org/Lombiq/orchard-training-demo-module) (Mercurial repository) - [https://github.com/Lombiq/Orchard-Training-Demo-Module](https://github.com/Lombiq/Orchard-Training-Demo-Module) (Git repository) -Bug reports, feature requests and comments are warmly welcome, **please do so via GitHub**. -Feel free to send pull requests too, no matter which source repository you choose for this purpose. +Bug reports, feature requests and comments are warmly welcome, **please do so via GitHub**. Feel free to send pull requests too, no matter which source repository you choose for this purpose. This project is developed by [Lombiq Technologies Ltd](https://lombiq.com/). Commercial-grade support is available through Lombiq. \ No newline at end of file diff --git a/StartLearningHere.md b/StartLearningHere.md index c76d4421..aedeea2b 100644 --- a/StartLearningHere.md +++ b/StartLearningHere.md @@ -11,7 +11,7 @@ We'll guide you on your journey to become an Orchard Core developer. Look for "N Before you dive deep into this module it'd be best if you made sure that you have done the following: -* You know how ASP.NET Core works. It's important that you understand how ASP.NET Core works or generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. +* You know how ASP.NET Core MVC works. It's important that you understand how ASP.NET Core MVC works or generally what MVC is about. If you are not familiar with the topic take a look at the tutorials at https://docs.microsoft.com/en-us/aspnet/core/tutorials/?view=aspnetcore-2.1. * You've read through the documentation at https://orchardcore.readthedocs.io (at least the "About Orchard Core" section, but it would be great if you'd read the whole documentation). * You know Orchard Core from a user's perspective and understand the concepts underlying the system. * If you want to be more familiar with Orchard Core fundamentals you can watch some of the following video about the beta2 capabilities here: https://www.youtube.com/watch?v=6ZaqWmq8Pog or simply pick some of the interesting Orchard CMS podcasts from this YouTube playlist: https://www.youtube.com/watch?v=Xu6S2XawyY4&list=PLuskKJW0FhJfOAN3dL0Y0KBMdG1pKESVn @@ -20,9 +20,9 @@ Before you dive deep into this module it'd be best if you made sure that you hav ## Moving forward -We've invested a lot of time creating this module. If you have ideas regarding it or have found mistakes, please let us know on the project page: https://github.com/Lombiq/Orchard-Training-Demo-Module +We've invested a lot of time creating this module. If you have ideas regarding it or have found mistakes, please let us know on [the project page on GitHub](https://github.com/Lombiq/Orchard-Training-Demo-Module). -If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at Orchard Dojo's trainings: https://orcharddojo.net/orchard-training +If you'd like to get trained instead of self-learning or you need help in form of mentoring sessions take a look at [Orchard Dojo's trainings](https://orcharddojo.net/orchard-training) After you complete this tutorial (or even during walking through it) you're encouraged to look at the built-in modules on how they solve similar tasks. If you choose to use the simpler way to add this project to Orchard Core then you should try the other way as well to have the whole Orchard source at your hands: let it be your tutor :-). @@ -32,10 +32,10 @@ Later on, you may want to take a look at *Map.cs* (remember, "X marks the spot!" ## Let's get started! -**FIRST STATION**: First of all, let's discuss how a .NET Standard library becomes an Orchard Module. If you look into the Dependencies of this project you will find either a NuGet reference for the OrchardCore.Module.Targets package or if you go with the full Orchard Core source code way you can add this particular project as a Project reference. +**FIRST STATION**: First of all, let's discuss how a .NET Standard library becomes an Orchard Module. If you look into the Dependencies of this project you will find either a NuGet reference for the `OrchardCore.Module.Targets` package or if you go with the full Orchard Core source code way you can add this particular project as a Project reference. On the other hand the module manifest file is also required. So... -**NEXT STATION**: Head over to Manifest.cs. That file is the module's manifest; a Manifest.cs is required for Orchard modules. +**NEXT STATION**: Head over to *Manifest.cs*. That file is the module's manifest; a *Manifest.cs* is required for Orchard modules. -This demo is heavily inspired by Sipke Schoorstra's Orchard Harvest session (http://www.youtube.com/watch?v=MH9mcodTX-U) and brought to you by Lombiq (https://lombiq.com/). \ No newline at end of file +This demo is heavily inspired by [Sipke Schoorstra's Orchard Harvest session](http://www.youtube.com/watch?v=MH9mcodTX-U) and brought to you by [Lombiq Technologies](https://lombiq.com/). \ No newline at end of file diff --git a/Startup.cs b/Startup.cs index 3d548403..dc7bcf06 100644 --- a/Startup.cs +++ b/Startup.cs @@ -28,8 +28,8 @@ public class Startup : StartupBase { static Startup() { - // Registering both field types and shape types are necessary as they can - // be accessed from inner properties. + // Registering both field types and shape types are necessary as they can be accessed from inner + // properties. TemplateContext.GlobalMemberAccessStrategy.Register(); TemplateContext.GlobalMemberAccessStrategy.Register(); diff --git a/Views/Book.cshtml b/Views/Book.cshtml index 33e33a82..cba8f876 100644 --- a/Views/Book.cshtml +++ b/Views/Book.cshtml @@ -1,6 +1,6 @@ -@* This is the display shape of any Book item if no display type given (actually the default display type is -"Details"). This is generated by Orchard Core and the model contains all the zones defined in any DisplayDrivers -where the zones will contain the rendered smaller shapes you've seen earlier. *@ +@* This is the display shape of any Book item if no display type is given (actually the default display type is +"Details"). This is generated by Orchard Core and the model contains all the zones defined in any DisplayDrivers where +the zones will contain the rendered smaller shapes you've seen earlier. *@
@* Display Cover zone if there is any shape placed in the zone. *@ diff --git a/Views/DisplayManagement/DisplayBook.cshtml b/Views/DisplayManagement/DisplayBook.cshtml index 50745b77..263e206c 100644 --- a/Views/DisplayManagement/DisplayBook.cshtml +++ b/Views/DisplayManagement/DisplayBook.cshtml @@ -1,6 +1,6 @@ @* We passed the generated display shape object to this view. To actually render any shapes generated in Orchard we use Display helpers. To use these Orchard Core-related helpers in any .cshtml files we need to add a few usings and tag -helpers to _ViewImports.cshtml file.*@ +helpers to a _ViewImports.cshtml file.*@ @await DisplayAsync(Model) diff --git a/Views/_ViewImports.cshtml b/Views/_ViewImports.cshtml index 8bd758c0..dbbb8c39 100644 --- a/Views/_ViewImports.cshtml +++ b/Views/_ViewImports.cshtml @@ -1,5 +1,5 @@ @* _ViewImports.cshtml is an ASP.NET Core MVC-related feature. What is interesting to us is the Orchard Core-related -usings and tag helpers that we will possibly use in most of our shapes (.cshtml files). *@ +usings and tag helpers that we will possibly use in most of our shape templates (.cshtml files). *@ @inherits OrchardCore.DisplayManagement.Razor.RazorPage From 0c5cc74c3b96ccf8ea9922cf42d2790cfd980a05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Sat, 12 Jan 2019 21:10:06 +0100 Subject: [PATCH 42/65] Removing .orig file --HG-- branch : issue/OCORE-1 --- .../YourFirstOrchardCoreController.cs.orig | 77 ------------------- 1 file changed, 77 deletions(-) delete mode 100644 Controllers/YourFirstOrchardCoreController.cs.orig diff --git a/Controllers/YourFirstOrchardCoreController.cs.orig b/Controllers/YourFirstOrchardCoreController.cs.orig deleted file mode 100644 index 36529e85..00000000 --- a/Controllers/YourFirstOrchardCoreController.cs.orig +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This is a controller you can find in any ASP.NET Core MVC application; Orchard is an MVC application, although - * much-much more than that. - * - * An Orchard module is basically an MVC area. You could create areas that don't interact with Orchard and you'd just - * use standard ASP.NET Core MVC skills. Of course we want more than that, so let's take a closer look. - * - * Here you will see how to use some simple ASP.NET Core and Orchard Core services. - */ - -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.Localization; -using Microsoft.Extensions.Localization; -using Microsoft.Extensions.Logging; -using OrchardCore.DisplayManagement.Notify; - -namespace Lombiq.TrainingDemo.Controllers -{ - public class YourFirstOrchardCoreController : Controller - { - private readonly INotifier _notifier; - private readonly IStringLocalizer T; - private readonly IHtmlLocalizer H; - private readonly ILogger _logger; - - - public YourFirstOrchardCoreController( - INotifier notifier, - IStringLocalizer stringLocalizer, - IHtmlLocalizer htmlLocalizer, - ILogger logger) - { - _notifier = notifier; - _logger = logger; - - T = stringLocalizer; - H = htmlLocalizer; - } - - - // Here's a simple action that will return some message. Nothing special here just demonstrates that this will work - // in Orchard Core right after enabling the module. The route for this action will be - // /Lombiq.TrainingDemo/YourFirstOrchardCore/Index. - public ActionResult Index() => -<<<<<<< dest - // For now we just return an empty view. This action is accessible from under - // Lombiq.TrainingDemo/YourFirstOrchardCore/Index route (appended to your site's root path; so using defaults - // it would look something like this: https://localhost:44300/Lombiq.TrainingDemo/YourFirstOrchardCore/Index). - // If you don't know how this path gets together take a second look at how ASP.NET Core MVC routing works! -======= - // Simple texts can be localized using the IStringLocalizer service as you can see below. ->>>>>>> source - View(new { Message = T["Hello you!"] }); - - // Let's see some custom routing here. This attribute will override the default route and use this one. - [Route("TrainingDemo/NotifyMe")] - public ActionResult NotifyMe() - { - // ILogger is an ASP.NET Core service that will write something in the specific log files. In Orchard Core - // NLog is used for logging and the error level is "Error" by default. You can find the error log in the - // /App_Data/logs/orchard-log-[date].log file. Logger can be configured in the NLog.config file in the web - // project (e.g. OrchardCore.Cms.Web). - _logger.LogError("You have been notified about some error!"); - - // INotifier is an Orchard Core service to send messages to the user. This service can be used almost - // everywhere in the code base not only in Controllers. This service requires a LocalizedHtmlString object - // so the IHtmlLocalizer service needs to be used for localization. - _notifier.Information(H["Congratulations! You have been notified! Check the error log too!"]); - - return View(); - } - } -} - -/* - * NEXT STATION: Controllers/DisplayManagementController - */ From e741193161b1c06dc7b58ea50c7d0c51801dee85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Leh=C3=B3czky?= Date: Sat, 12 Jan 2019 23:01:01 +0100 Subject: [PATCH 43/65] Some more comment updates and code styling --HG-- branch : issue/OCORE-1 --- Controllers/PersonListController.cs | 19 +++++++++-------- Controllers/StoreController.cs | 13 +++++++----- Drivers/ColorFieldDisplayDriver.cs | 14 ++++++------- Drivers/PersonPartDisplayDriver.cs | 24 ++++++++++++---------- Fields/ColorField.cs | 4 ++-- Indexes/BookIndex.cs | 2 +- Indexes/PersonPartIndex.cs | 4 ++-- Indexing/ColorFieldIndexHandler.cs | 4 ++-- Map.cs | 2 +- Migrations/BookMigrations.cs | 22 +++++++------------- Migrations/PersonMigrations.cs | 6 +++--- Models/PersonPart.cs | 20 ++++++++---------- ResourceManifest.cs | 8 ++++---- Settings/ColorFieldSettings.cs | 15 +++++++------- Settings/ColorFieldSettingsDriver.cs | 4 ++-- ViewModels/PersonPartViewModel.cs | 4 ++-- Views/Book.Description.cshtml | 3 ++- Views/ColorField-ColorPicker.Edit.cshtml | 2 +- Views/ColorField-ColorPicker.Option.cshtml | 2 +- Views/ColorField.Edit.cshtml | 6 +++--- Views/ColorField.Option.cshtml | 6 +++--- Views/ColorField.cshtml | 4 ++-- Views/PersonPart.Edit.cshtml | 2 +- Views/YourFirstOrchardCore/NotifyMe.cshtml | 1 + 24 files changed, 95 insertions(+), 96 deletions(-) diff --git a/Controllers/PersonListController.cs b/Controllers/PersonListController.cs index c8c9057a..337dbd69 100644 --- a/Controllers/PersonListController.cs +++ b/Controllers/PersonListController.cs @@ -1,11 +1,11 @@ /* - * In this Controller you will see again how to query items but this time it will be the newly created Person content - * type. It doesn't make too much difference but you need to keep in mind that the ContentItems are stored in the - * documents (which contains the parts and fields serialized) and can have multiple index records referencing a content - * item (e.g. the previously created PersonPartIndex that indexes data in from the PersonPart). + * In this controller you will see again how to query items but this time items will be of the newly created Person + * content type. It doesn't make too much difference but you need to keep in mind that the ContentItems are stored in + * the documents (which contain the parts and fields serialized) and can have multiple index records referencing a + * content item (e.g. the previously created PersonPartIndex that indexes data in from PersonPart). * - * Note, that there is no custom controller or action demonstrated for displaying the editor for the Person. Go to the - * administration page and create a few Person content item. + * Note that there is no custom controller or action demonstrated for displaying the editor for the Person. Go to the + * administration page (/Admin) and create a few Person content items, including ones with ages above 30. */ using System.Linq; @@ -38,11 +38,12 @@ public PersonListController( } + // See it under /Lombiq.TrainingDemo/PersonList/OlderThan30. public async Task OlderThan30() { var thresholdDate = _clock.UtcNow.AddYears(-30); var people = await _session - // It will query for content items where the related PersonPartIndex.BirthDateUtc is lower than the + // This will query for content items where the related PersonPartIndex.BirthDateUtc is lower than the // threshold date. Notice that there is no Where method. The Query method has an overload for that // which can be useful if you don't want to filter in multiple indexes. .Query(index => index.BirthDateUtc < thresholdDate) @@ -53,11 +54,11 @@ public async Task OlderThan30() // items. The reason we need that is that a ContentItem doesn't have a DisplayDriver but the ContentParts // and ContentFields attached to the ContentItem have. This service will handle generating all the drivers // created for these parts and fields. - // NEXT STATION: Drivers/PersonPartDriver + // NEXT STATION: Drivers/PersonPartDisplayDriver var shapes = await Task.WhenAll(people.Select(async person => await _contentItemDisplayManager.BuildDisplayAsync(person, this, "Summary"))); - // Now that assuming that you've already created a few Person content items on the dashboard and some of + // Now assuming that you've already created a few Person content items on the dashboard and some of // these persons are more than 30 years old then this query will contain items to display. // NEXT STATION: Views/PersonList/OlderThan30.cshtml diff --git a/Controllers/StoreController.cs b/Controllers/StoreController.cs index 78036b5c..46f9f72c 100644 --- a/Controllers/StoreController.cs +++ b/Controllers/StoreController.cs @@ -1,6 +1,6 @@ /* * Now it's time to save something to the database. Orchard Core uses YesSql to store data in database which is - * document database interface for relational databases. In simple, you need to plan your database as a document + * document database interface for relational databases. Simply put, you need to design your database as a document * database but it will be stored in your favorite SQL database. If you want to learn more go to * https://github.com/sebastienros/yessql and read the documentation. * @@ -47,14 +47,16 @@ public StoreController( // A page with a button that will call the CreateBooks POST action. + // See it under /Lombiq.TrainingDemo/Store/CreateBooks. [HttpGet] public ActionResult CreateBooks() => View(); [HttpPost, ActionName(nameof(CreateBooks))] public ActionResult CreateBooksPost() { - // For demonstration purposes it will create 3 books and store them in the database one-by-one using the - // ISession service. + // For demonstration purposes this will create 3 books and store them in the database one-by-one using the + // ISession service. Note that you can even go to the database directly, circumventing YesSql too, by + // injecting the IDbConnectionAccessor service and access the underlying connection. // Since storing them in the documents is not enough we need to index them to be able to // filter them in a query. @@ -71,6 +73,7 @@ public ActionResult CreateBooksPost() } // This page will display the books written by J.K. Rowling. + // See it under /Lombiq.TrainingDemo/Store/JKRowlingBooks. public async Task JKRowlingBooks() { // ISession service is used for querying items. @@ -80,8 +83,7 @@ public async Task JKRowlingBooks() .Query() // In the .Where() method you can describe a lambda where the object will be the index object. .Where(index => index.Author == "J.K. (Joanne) Rowling") - // When the query is built up you can call the ListAsync() to execute it. This will return a list of - // books. + // When the query is built up you can call ListAsync() to execute it. This will return a list of books. .ListAsync(); // Now this is what we possibly understand now, we will create a list of display shapes from the previously @@ -89,6 +91,7 @@ public async Task JKRowlingBooks() var bookShapes = await Task.WhenAll(jkRowlingBooks.Select(async book => await _bookDisplayManager.BuildDisplayAsync(book, this))); + // You can check out Views/Store/JKRowlingBooks.cshtml and come back here. return View(bookShapes); } diff --git a/Drivers/ColorFieldDisplayDriver.cs b/Drivers/ColorFieldDisplayDriver.cs index 34ce2f0d..7a73d748 100644 --- a/Drivers/ColorFieldDisplayDriver.cs +++ b/Drivers/ColorFieldDisplayDriver.cs @@ -27,12 +27,12 @@ public ColorFieldDisplayDriver(IStringLocalizer stringL public override IDisplayResult Display(ColorField field, BuildFieldDisplayContext context) { - // Same Display method for generating display shape but this time the Initialize shape helper is being + // Same Display method for generating display shapes but this time the Initialize shape helper is being // used. We've seen it in the PersonPartDisplayDriver.Edit method. For this we need a view model object - // that will be populated with the field data. The GetDisplayShapeType helper will generate a - // conventionally shape type for our content field which will be the name of our content field. Obviously, - // alternates can also be used - so if the content item is being displayed with a Custom display type then - // the ColorField.Custom.cshtml file name can be used, otherwise, the ColorField.cshtml will be active. + // which will be populated with the field data. The GetDisplayShapeType helper will generate a conventional + // shape type for our content field which will be the name the field. Obviously, alternates can also be + // used - so if the content item is being displayed with a display type named "Custom" then the + // ColorField.Custom.cshtml file will be used, otherwise, the ColorField.cshtml will be active. return Initialize(GetDisplayShapeType(context), model => { model.Field = field; @@ -65,8 +65,8 @@ public override async Task UpdateAsync(ColorField field, IUpdate { var viewModel = new EditColorFieldViewModel(); - // Using this overload of the model updater you can specifically say what properties need to be updated - // only. This way you make sure no other properties will be bound to the view model. + // Using this overload of the model updater you can specifically say what properties need to be updated. + // This way you make sure no other properties will be bound to the view model. if (await updater.TryUpdateModelAsync(viewModel, Prefix, f => f.Value, f => f.ColorName)) { // Use the settings are now let's use them for validation. diff --git a/Drivers/PersonPartDisplayDriver.cs b/Drivers/PersonPartDisplayDriver.cs index 2554ad2e..0ad7b40d 100644 --- a/Drivers/PersonPartDisplayDriver.cs +++ b/Drivers/PersonPartDisplayDriver.cs @@ -7,8 +7,9 @@ namespace Lombiq.TrainingDemo.Drivers { - // Drivers inherited from ContentPartDisplayDrivers have a similar functionality described in the BookDisplayDriver - // but these are for ContentParts. Don't forget to register this class to the service provider (see: Startup.cs). + // Drivers inherited from ContentPartDisplayDrivers have a functionality similar to the one described in + // BookDisplayDriver but these are for ContentParts. Don't forget to register this class to the service provider + // (see: Startup.cs). public class PersonPartDisplayDriver : ContentPartDisplayDriver { // A Display method that we already know. This time it's much simpler because we don't want to create multiple @@ -20,9 +21,9 @@ public override IDisplayResult Display(PersonPart part) => // editor shape for the PersonPart. public override IDisplayResult Edit(PersonPart personPart) { - // Similar happens to the Display, you have a shape helper with a shape name possibly and a factory. For - // editing the Initialize is the best idea. It will instantiate a view model from a type given as a generic - // parameter. In the factory you will map the content part properties to the view model. + // Something similar to the Display method happens: you have a shape helper with a shape name possibly and + // a factory. For editing using Initialize is the best idea. It will instantiate a view model from a type + // given as a generic parameter. In the factory you will map the content part properties to the view model. return Initialize("PersonPart_Edit", model => { model.PersonPart = personPart; @@ -41,11 +42,12 @@ public override async Task UpdateAsync(PersonPart model, IUpdate { var viewModel = new PersonPartViewModel(); - // Now it's where the IUpdateModel interface is really used. With this you will be able to use the - // Controller's model binding helpers here in the driver. The prefix property will be used to distinguish - // between similarly named input fields when building the editor form. By default Orchard Core will use the - // content part name but if you have multiple drivers for a content part you need to override it in the - // driver. + // Now it's where the IUpdateModel interface is really used (remember we first used it in + // DisplayManagementController?). With this you will be able to use the Controller's model binding helpers + // here in the driver. The prefix property will be used to distinguish between similarly named input fields + // when building the editor form (so e.g. two content parts composing a content item can have an input + // field called "Name"). By default Orchard Core will use the content part name but if you have multiple + // drivers with editors for a content part you need to override it in the driver. await updater.TryUpdateModelAsync(viewModel, Prefix); // Now you can do some validation if needed. One way to do it you can simply write your own validation here @@ -54,7 +56,7 @@ public override async Task UpdateAsync(PersonPart model, IUpdate // Go and check the ViewModels/PersonPartViewModel to see how to do it and then come back here. // Finally map the view model to the content part. By default these changes won't be persisted if there was - // a validation error. Otherwise, these will be automatically stored in the database. + // a validation error. Otherwise these will be automatically stored in the database. model.BirthDateUtc = viewModel.BirthDateUtc; model.Name = viewModel.Name; model.Handedness = viewModel.Handedness; diff --git a/Fields/ColorField.cs b/Fields/ColorField.cs index dfa2ea7b..b7cbfc2e 100644 --- a/Fields/ColorField.cs +++ b/Fields/ColorField.cs @@ -1,5 +1,5 @@ /* - * Now we will develop a content field. Just like with content part development, we'll start with creating a model + * Now we will develop a content field. Just like with content part development, we'll start by creating a model * class. We want to store a color name and the actual color in HEX so we need two strings for that. * * Conventionally we put these objects in the Fields folder. @@ -20,4 +20,4 @@ public class ColorField : ContentField } } -// NEXT STATION: Startup.cs and find the constructor \ No newline at end of file +// NEXT STATION: Startup.cs and find the static constructor. \ No newline at end of file diff --git a/Indexes/BookIndex.cs b/Indexes/BookIndex.cs index fb00df24..6880cc45 100644 --- a/Indexes/BookIndex.cs +++ b/Indexes/BookIndex.cs @@ -4,7 +4,7 @@ namespace Lombiq.TrainingDemo.Indexes { // The BookIndex objects will be stored in the database. Since this is actually a relational database these will be - // actual records in a table specifically created for this index. + // records in a table specifically created for this index. public class BookIndex : MapIndex { public string Author { get; set; } diff --git a/Indexes/PersonPartIndex.cs b/Indexes/PersonPartIndex.cs index eaae18a7..70705517 100644 --- a/Indexes/PersonPartIndex.cs +++ b/Indexes/PersonPartIndex.cs @@ -5,14 +5,14 @@ namespace Lombiq.TrainingDemo.Indexes { - // This is also very similar to the one we've seen in the BookIndex.cs. The difference is that we have ContentItems + // This is also very similar to the one we've seen in BookIndex.cs. The difference is that we have ContentItems // now instead of simple objects. public class PersonPartIndex : MapIndex { // Here we will reference the ContentItem ID. public string ContentItemId { get; set; } - // Store the birth date only for demonstration purposes. + // Store the birth date only for demonstration purposes so we can run queries on it. public DateTime? BirthDateUtc { get; set; } } diff --git a/Indexing/ColorFieldIndexHandler.cs b/Indexing/ColorFieldIndexHandler.cs index 6c5009c9..32b57d0c 100644 --- a/Indexing/ColorFieldIndexHandler.cs +++ b/Indexing/ColorFieldIndexHandler.cs @@ -1,7 +1,7 @@ /* * IndexHandlers are different from IndexProviders. While IndexProviders will store values in the SQL database to index - * documents these will use an actual index provider (e.g. Lucene) index data. This way no database query is required - * when you want to use a search widget on your website. + * documents these will use a text search index provider (e.g. Lucene) to index data. This way no database query is + * required when you want to use a search widget on your website. */ using System.Threading.Tasks; diff --git a/Map.cs b/Map.cs index a53fdd6a..1939ad6d 100644 --- a/Map.cs +++ b/Map.cs @@ -9,7 +9,7 @@ using Lombiq.TrainingDemo.ViewModels; /* - * In this file, you'll find the index of the whole (or at least most of the) module's classes for easier navigation + * In this file you'll find the index of the whole (or at least most of the) module's classes for easier navigation * between topics. You can navigate directly to classes and their methods by clicking on their names (enclosed in a * Factory() ) and pressing F12. * diff --git a/Migrations/BookMigrations.cs b/Migrations/BookMigrations.cs index 92897d3d..366940f4 100644 --- a/Migrations/BookMigrations.cs +++ b/Migrations/BookMigrations.cs @@ -13,15 +13,6 @@ namespace Lombiq.TrainingDemo.Migrations // Don't forget to register this class to the service provider (see: Startup.cs). public class BookMigrations : DataMigration { - IContentDefinitionManager _contentDefinitionManager; - - - public BookMigrations(IContentDefinitionManager contentDefinitionManager) - { - _contentDefinitionManager = contentDefinitionManager; - } - - // Migrations have Create() and UpdateFromX methods. When the module is first enabled the Create() is called so // it can set up DB tables. public int Create() @@ -31,15 +22,16 @@ public int Create() .Column(nameof(BookIndex.Title)) ); - // Here we return the number of the migration. If there were no update methods we'd return 1. But we have - // one, see it for more details. + // Here we return the version number of the migration. If there were no update methods we'd return 1. But + // we have one, see it for more details. return 2; } - // This is an update method. It is used to modify the existing schema. Update methods will be run when the - // module was already enabled before and the create method was run. The X in UpdateFromX is the number of the - // update (the method's name is conventional). It means: "run this update if the module's current migration - // version is X". This method will run if it's 1. + // This is an update method. It is used to modify an existing schema. Update methods will be run when the + // module was already enabled before and the create method was run (like when you update a module already + // running on an Orchard site). The X in UpdateFromX is the version number of the update (the method's name is + // conventional). It means: "run this update if the module's current migration version is X". This method will + // run if it's 1. public int UpdateFrom1() { // The initial version of our module did not store the book's title. We quickly fix the issue by pushing diff --git a/Migrations/PersonMigrations.cs b/Migrations/PersonMigrations.cs index 2853c807..ecb53ffd 100644 --- a/Migrations/PersonMigrations.cs +++ b/Migrations/PersonMigrations.cs @@ -26,7 +26,7 @@ public int Create() { // Now you can configure PersonPart. For example you can add content fields (as mentioned earlier) here. _contentDefinitionManager.AlterPartDefinition(nameof(PersonPart), part => part - // Each field has it's own configuration. Here you will give a display name for it and add some + // Each field has its own configuration. Here you will give a display name for it and add some // additional settings like a hint to be displayed in the editor. .WithField(nameof(PersonPart.Biography), field => field .OfType(nameof(TextField)) @@ -37,8 +37,8 @@ public int Create() }) .WithSettings(new ContentPartFieldSettings { - // This is an extension point for making multiple editor flavor for a content field or content - // part. We'll learn this feature later with the ContentFields. + // This is an extension point for providing multiple editor flavors for a content field or + // content part. We'll learn this feature later with the content fields. Editor = "TextArea" }))); diff --git a/Models/PersonPart.cs b/Models/PersonPart.cs index d45db9dd..9d08b1f0 100644 --- a/Models/PersonPart.cs +++ b/Models/PersonPart.cs @@ -1,8 +1,9 @@ /* - * Now let's see what practices Orchard Core provides when it stores data. Here you can see a ContentPart. Each - * ContentPart can be part of one or more content types. Using the content type you can create ContentItems that is the - * most important part of the Orchard Core content management. Here is a PersonPart containing some properties of a - * person. + * Now let's see what practices Orchard Core provides when it stores data. Here you can see a content part. Each + * content part can be attached to one or more content types. From the content type you can create content items (so + * you kind of "instantiate" content types as content items). This is the most important part of the Orchard Core's + * content management. Here is a PersonPart containing some properties of a person. You also need to register this + * class to the service provider (see: Startup.cs). */ using System; @@ -11,10 +12,6 @@ namespace Lombiq.TrainingDemo.Models { - // Now let's see what practices Orchard Core provides when it stores data. Here you can see a ContentPart. Each - // ContentPart can be part of one or more content types. Using the content type you can create ContentItems that is - // the most important part of the Orchard Core content management. Here is a PersonPart containing some properties - // of a person. You also need to register this class to the service provider (see: Startup.cs). public class PersonPart : ContentPart { // A ContentPart is serialized as a JSON object so you need to keep this in mind when creating properties. For @@ -24,9 +21,10 @@ public class PersonPart : ContentPart public Handedness Handedness { get; set; } public DateTime? BirthDateUtc { get; set; } - // This is a ContentField. ContentFields are similar to ContentParts, however, fields are a bit more smaller - // components encapsulating simple editor and display for a single data and ContentParts could have a more - // complex functionality and also can contain a set of fields. + // This is a content field. Content fields are similar to content parts, however, fields are a bit smaller + // components encapsulating a simple editor and display for a single piece of data. Content parts could provide + // more complex functionality and also can contain a set of fields. + // TextField is one of Orchard's many built-in fields. public TextField Biography { get; set; } } diff --git a/ResourceManifest.cs b/ResourceManifest.cs index 2c724603..090d20b2 100644 --- a/ResourceManifest.cs +++ b/ResourceManifest.cs @@ -17,12 +17,12 @@ public void BuildManifests(IResourceManifestBuilder builder) manifest // We're registering a script with DefineStyle and defining it's name. It's a global name, so choose - // wisely. There is no strict naming convention, but we can give you and advice how to choose a unique + // wisely. There is no strict naming convention, but we can give you an advice how to choose a unique // name: it should contain the module's full namespace followed by a meaningful name. Although if it's // a third-party library you can give a more general name like you see below. This script will be the // javascript plugin for the color picker. .DefineScript("Pickr") - // This is the actual stylesheet that will be assigned to the resource name. Please note that the + // This is the actual script file that will be assigned to the resource name. Please note that the // naming of the file itself is following similar rules as the resource name, with some modifications // applied as it's a file name. Since stylesheets and script are shapes, it's possible to override // them, so you should try to avoid name collisions: file names (not the full path, just the name!) @@ -36,13 +36,13 @@ public void BuildManifests(IResourceManifestBuilder builder) .SetUrl("/Lombiq.TrainingDemo/Pickr/pickr.min.css"); manifest - // Finally let's see an example for defining a resource for our custom work. You can see the naming is + // Finally let's see an example for defining a resource for our custom code. You can see the naming is // more specific and contains our namespace. .DefineStyle("Lombiq.TrainingDemo.ColorPicker") .SetUrl("/Lombiq.TrainingDemo/Styles/trainingdemo-colorpicker.min.css", "/Lombiq.TrainingDemo/Styles/trainingdemo-colorpicker.css") // You can give a list of resource names to SetDependencies to force the loading of other resources - // when a given resource is used. Here the Pickr is a dependency. + // when a given resource is used. Here Pickr is a dependency. .SetDependencies("Pickr"); // If you go back to the Views/ColorField-ColorPicker.Edit.cshtml you will understand why all these three diff --git a/Settings/ColorFieldSettings.cs b/Settings/ColorFieldSettings.cs index a81fc023..5bb04a49 100644 --- a/Settings/ColorFieldSettings.cs +++ b/Settings/ColorFieldSettings.cs @@ -1,7 +1,8 @@ /* - * Every content part and content field can have settings.If you have a PersonPart content part where you use - * ColorField these settings will be applied on every content item where the PersonPart is in present, however, if you - * have multiple ColorFields, each fields will have their own settings.In our case we have three settings. + * Every content part and content field can have settings. If you have a PersonPart content part where you use + * ColorField these settings will be applied on every content item where the PersonPart is present. However, if you + * have multiple ColorFields, each fields will have their own settings. In our case we have three settings for the + * field. */ namespace Lombiq.TrainingDemo.Settings @@ -19,9 +20,9 @@ public class ColorFieldSettings } } -// How can these settings be edited? If you attach a content field to a content part / content type you can set -// these values there (see: Migrations/PersonMigrations where the Biography field is being added to the -// PersonPart). If you attach the field on the dashboard yourself then Orchard Core will display its editor. Editor -// of an object like this? You know what you need to do... Create a DisplayDriver for this! +// How can these settings be edited? If you attach a content field to a content part / content type from a migration +// you can set these values there (see: Migrations/PersonMigrations where the Biography field is being added to the +// PersonPart). If you attach the field on the dashboard yourself then Orchard Core will display its editor. Editor of +// an object like this? You know what you need to do... Create a DisplayDriver for this! // NEXT STATION: Settings/ColorFieldSettingsDriver \ No newline at end of file diff --git a/Settings/ColorFieldSettingsDriver.cs b/Settings/ColorFieldSettingsDriver.cs index 11c8b55e..14614465 100644 --- a/Settings/ColorFieldSettingsDriver.cs +++ b/Settings/ColorFieldSettingsDriver.cs @@ -6,11 +6,11 @@ namespace Lombiq.TrainingDemo.Settings { - // It's in the Settings folder by convention but it's the same DisplayDriver as the others, except, it also has a + // It's in the Settings folder by convention but it's the same DisplayDriver as the others; except, it also has a // specific base class. Don't forget to register this class to the service provider (see: Startup.cs). public class ColorFieldSettingsDriver : ContentPartFieldDefinitionDisplayDriver { - // This won't have a Display override since it wouldn't make too much sense. + // This won't have a Display override since it wouldn't make too much sense, settings are just edited. public override IDisplayResult Edit(ContentPartFieldDefinition partFieldDefinition) => // Same old Initialize shape helper. Initialize("ColorFieldSettings_Edit", diff --git a/ViewModels/PersonPartViewModel.cs b/ViewModels/PersonPartViewModel.cs index 74f740b4..403bdce2 100644 --- a/ViewModels/PersonPartViewModel.cs +++ b/ViewModels/PersonPartViewModel.cs @@ -28,8 +28,8 @@ public class PersonPartViewModel : IValidatableObject public IEnumerable Validate(ValidationContext validationContext) { - // To use GetService overload you need to add the Microsoft.Extensions.DependencyInjection nuget package - // to your module. This way you can get any service you want as you've injected them in a constructor. + // To use GetService overload you need to add the Microsoft.Extensions.DependencyInjection NuGet package + // to your module. This way you can get any service you want just as you've injected them in a constructor. var T = validationContext.GetService>(); var clock = validationContext.GetService(); diff --git a/Views/Book.Description.cshtml b/Views/Book.Description.cshtml index c498dca8..81ace586 100644 --- a/Views/Book.Description.cshtml +++ b/Views/Book.Description.cshtml @@ -5,7 +5,8 @@ Description. The zone-related properties of the Model objects will be populated @* Display Header zone if there is any shape placed in the zone. Remember that since Title and Author shapes have no display type property given in the Driver these will also be rendered here. This way you can reuse any shapes you want in Orchard Core! *@ - @if (Model.Header != null) { + @if (Model.Header != null) + {
@await DisplayAsync(Model.Header)
diff --git a/Views/ColorField-ColorPicker.Edit.cshtml b/Views/ColorField-ColorPicker.Edit.cshtml index c2f35167..7cd7c42f 100644 --- a/Views/ColorField-ColorPicker.Edit.cshtml +++ b/Views/ColorField-ColorPicker.Edit.cshtml @@ -33,7 +33,7 @@ helpers all the necessary scripts and styles will be loaded.*@
@* The following script will contain the initialization for the color picker. The at="Foot" will make it rendered in -the end of the Body tag. *@ +the end of the body tag. *@