diff --git a/ITContentProvider/ChangeLog b/ITContentProvider/ChangeLog deleted file mode 100644 index c379f4d3..00000000 --- a/ITContentProvider/ChangeLog +++ /dev/null @@ -1,23 +0,0 @@ -2015-12-24 Paul Schneider - - * ITContentProvider.csproj: ajout d'une configuration de - debuggage pour Lua - -2015-12-23 Paul Schneider - - * packages.config: - * ITContentProvider.csproj: mise à niveau Npgsql - -2015-11-30 Paul Schneider - - * ITContentProvider.csproj: ... - -2015-11-26 Paul Schneider - - * ITContentProvider.csproj: nouvelles configurations de - déploiement - -2015-11-19 Paul Schneider - - * ITContentProvider.csproj: adds a build target named "Lua" - diff --git a/ITContentProvider/ITContentProvider.csproj b/ITContentProvider/ITContentProvider.csproj index 3ae6c52a..84c3fa79 100644 --- a/ITContentProvider/ITContentProvider.csproj +++ b/ITContentProvider/ITContentProvider.csproj @@ -9,7 +9,7 @@ Library ITContentProvider ITContentProvider - v4.5 + v4.5.1 true @@ -65,12 +65,9 @@ - - - - ..\packages\Npgsql.3.0.4\lib\net45\Npgsql.dll + ..\packages\Npgsql.3.0.5\lib\net45\Npgsql.dll diff --git a/ITContentProvider/packages.config b/ITContentProvider/packages.config index 7dcb0d3b..440f9cbc 100644 --- a/ITContentProvider/packages.config +++ b/ITContentProvider/packages.config @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/NpgsqlBlogProvider/ChangeLog b/NpgsqlBlogProvider/ChangeLog deleted file mode 100644 index c2e6c9aa..00000000 --- a/NpgsqlBlogProvider/ChangeLog +++ /dev/null @@ -1,57 +0,0 @@ -2015-12-24 Paul Schneider - - * NpgsqlBlogProvider.csproj: ajout d'une configuration de - debuggage pour Lua - -2015-12-23 Paul Schneider - - * packages.config: - * NpgsqlBlogProvider.csproj: mise à niveau Npgsql - -2015-12-09 Paul Schneider - - * NpgsqlBlogProvider.cs: Corrige la méthode pour enlever un - tag à un article ... - - * NpgsqlBlogProvider.csproj: . - -2015-11-30 Paul Schneider - - * NpgsqlBlogProvider.cs: implémente le compteur de billet en - base de données - - * NpgsqlBlogProvider.csproj: ... - -2015-11-28 Paul Schneider - - * NpgsqlBlogProvider.cs: xml doc - -2015-11-26 Paul Schneider - - * NpgsqlBlogProvider.csproj: nouvelles configurations de - déploiement - -2015-11-19 Paul Schneider - - * NpgsqlBlogProvider.csproj: adds a build target named "Lua" - -2015-11-14 Paul Schneider - - * NpgsqlBlogProvider.cs: Bill ranking, and delivering hidden - content to owner - -2015-11-11 Paul Schneider - - * NpgsqlBlogProvider.cs: refactoring - -2015-11-06 Paul Schneider - - * NpgsqlBlogProvider.cs: refactorisation, to render Tags and - Circles on each entry type. - Fixes the `Find` Method using the `MatchTag` search flag - - * NpgsqlBlogProvider.csproj: cleanning - - * ChangeLog: - * NpgsqlTagInfo.cs: - diff --git a/NpgsqlBlogProvider/NpgsqlBlogProvider.csproj b/NpgsqlBlogProvider/NpgsqlBlogProvider.csproj index da691ae1..16e9b85c 100644 --- a/NpgsqlBlogProvider/NpgsqlBlogProvider.csproj +++ b/NpgsqlBlogProvider/NpgsqlBlogProvider.csproj @@ -74,7 +74,7 @@ - ..\packages\Npgsql.3.0.4\lib\net45\Npgsql.dll + ..\packages\Npgsql.3.0.5\lib\net45\Npgsql.dll diff --git a/NpgsqlBlogProvider/packages.config b/NpgsqlBlogProvider/packages.config index 8ed80a18..440f9cbc 100644 --- a/NpgsqlBlogProvider/packages.config +++ b/NpgsqlBlogProvider/packages.config @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/NpgsqlContentProvider/ChangeLog b/NpgsqlContentProvider/ChangeLog deleted file mode 100644 index 6c2b672c..00000000 --- a/NpgsqlContentProvider/ChangeLog +++ /dev/null @@ -1,86 +0,0 @@ -2015-12-24 Paul Schneider - - * NpgsqlContentProvider.csproj: ajout d'une configuration de - debuggage pour Lua - -2015-12-23 Paul Schneider - - * NpgsqlContentProvider.cs: stocke la classe de commande - - * packages.config: - * NpgsqlContentProvider.csproj: mise à niveau Npgsql - -2015-12-15 Paul Schneider - - * NpgsqlContentProvider.cs: bug fix - -2015-12-09 Paul Schneider - - * NpgsqlCircleProvider.cs: liste les cercles auquels - appartient un utilisateur. - - * NpgsqlContentProvider.cs: Les commandes sont fortement - typée. - -2015-11-30 Paul Schneider - - * NpgsqlContentProvider.csproj: ... - -2015-11-30 Paul Schneider - - * NpgsqlContentProvider.cs: Renseigne le code APE et la côte - au profile préstataire - - * NpgsqlSkillProvider.cs: refabrication - -2015-11-28 Paul Schneider - - * NpgsqlContentProvider.cs: implemente un listing des - prestataire du code APE en base. - - * NpgsqlSkillProvider.cs: implemente un listing des domaines - de compétence du préstataire en base. - -2015-11-26 Paul Schneider - - * NpgsqlContentProvider.csproj: nouvelles configurations de - déploiement - -2015-11-26 Paul Schneider - - * NpgsqlContentProvider.cs: reccupère la photo activité en - base de données - -2015-11-25 Paul Schneider - - * NpgsqlContentProvider.cs: implemente la gestion des - activités côté base de donnée Npgsql - -2015-11-23 Paul Schneider - - * NpgsqlSkillProvider.cs: refactorisation (-Skill+SkillEntity) - -2015-11-19 Paul Schneider - - * NpgsqlContentProvider.csproj: adds a build target named - "Lua" - -2015-11-17 Paul Schneider - - * NpgsqlSkillProvider.cs: User's skills profile object now - implements an `Id` property, - in order to be rated, perhaps ranked in a near future. It's - implemented as the legay profile id. - -2015-11-17 Paul Schneider - - * NpgsqlSkillProvider.cs: implements a skill provider - - * NpgsqlContentProvider.csproj: Imports the - `NpgsqlSkillProvider` class - -2015-11-08 Paul Schneider - - * ChangeLog: this file should not be maintained as a git - respository legacy file - diff --git a/NpgsqlContentProvider/NpgsqlCircleProvider.cs b/NpgsqlContentProvider/NpgsqlCircleProvider.cs index 37346315..5908e526 100644 --- a/NpgsqlContentProvider/NpgsqlCircleProvider.cs +++ b/NpgsqlContentProvider/NpgsqlCircleProvider.cs @@ -22,7 +22,6 @@ using System; using System.Collections.Generic; using System.Collections.Specialized; using System.Configuration; -using System.Web.Mvc; using System.Web.Security; using Npgsql; using NpgsqlTypes; diff --git a/NpgsqlContentProvider/NpgsqlContentProvider.csproj b/NpgsqlContentProvider/NpgsqlContentProvider.csproj index 14035920..b57719b3 100644 --- a/NpgsqlContentProvider/NpgsqlContentProvider.csproj +++ b/NpgsqlContentProvider/NpgsqlContentProvider.csproj @@ -9,7 +9,7 @@ Library WorkFlowProvider NpgsqlContentProvider - v4.5 + v4.5.1 true @@ -64,14 +64,15 @@ - - - ..\packages\Npgsql.3.0.4\lib\net45\Npgsql.dll + ..\packages\Npgsql.3.0.5\lib\net45\Npgsql.dll + + + ..\packages\Newtonsoft.Json.8.0.1\lib\net45\Newtonsoft.Json.dll diff --git a/NpgsqlContentProvider/packages.config b/NpgsqlContentProvider/packages.config index 7dcb0d3b..60078080 100644 --- a/NpgsqlContentProvider/packages.config +++ b/NpgsqlContentProvider/packages.config @@ -1,4 +1,9 @@ - - - + + + + + + + + \ No newline at end of file diff --git a/NpgsqlMRPProviders/ChangeLog b/NpgsqlMRPProviders/ChangeLog deleted file mode 100644 index f7f94295..00000000 --- a/NpgsqlMRPProviders/ChangeLog +++ /dev/null @@ -1,70 +0,0 @@ -2015-12-30 Paul Schneider - - * NpgsqlMembershipProvider.cs: ne pas crasher à la lecture en - base de la question de - recupération du mot de passe quand elle est nulle. - -2015-12-24 Paul Schneider - - * NpgsqlMRPProviders.csproj: ajout d'une configuration de - debuggage pour Lua - -2015-11-30 Paul Schneider - - * NpgsqlMRPProviders.csproj: ... - -2015-11-26 Paul Schneider - - * NpgsqlMRPProviders.csproj: nouvelles configurations de - déploiement - -2015-11-23 Paul Schneider - - * NpgsqlProfileProvider.cs: Fixe un bug introduit avec - l'implementation des profiles anonymes. - -2015-11-19 Paul Schneider - - * NpgsqlMRPProviders.csproj: adds a build target named "Lua" - -2015-11-11 Paul Schneider - - * NpgsqlProfileProvider.cs: return the default value in the - targeted Type, in case of DBNull - -2015-11-06 Paul Schneider - - * NpgsqlProfileProvider.cs: nicer code - -2015-11-04 Paul Schneider - - * NpgsqlProfileProvider.cs: - * NpgsqlMembershipProvider.cs: - -2015-11-03 Paul Schneider - - * NpgsqlMembershipProvider.cs: Fixes the latest commit - concerning account creation and removal - -2015-11-03 Paul Schneider - - * NpgsqlMembershipProvider.cs: insert a profile record before - inserting the users record, - to ensure a new foreign key constraint - - * NpgsqlProfileProvider.cs: better comments - -2015-11-01 Paul Schneider - - * NpgsqlMembershipProvider.cs: xmldoc - - * NpgsqlProfileProvider.cs: use default values from - configuration - - * NpgsqlUserNameProvider.cs: Fixes the username detection - -2015-10-28 Paul Schneider - - * NpgsqlProfileProvider.cs: Fixes the defaultValue - specification from config file - diff --git a/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj b/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj index 874c192a..44c68f0e 100644 --- a/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj +++ b/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj @@ -9,7 +9,7 @@ Library Npgsql.Web NpgsqlMRPProviders - v4.5 + v4.5.1 true @@ -78,7 +78,7 @@ - ..\packages\Npgsql.3.0.3\lib\net45\Npgsql.dll + ..\packages\Npgsql.3.0.5\lib\net45\Npgsql.dll diff --git a/NpgsqlMRPProviders/packages.config b/NpgsqlMRPProviders/packages.config index ba123222..440f9cbc 100644 --- a/NpgsqlMRPProviders/packages.config +++ b/NpgsqlMRPProviders/packages.config @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/Presta/ChangeLog b/Presta/ChangeLog deleted file mode 100644 index 5af442f8..00000000 --- a/Presta/ChangeLog +++ /dev/null @@ -1,27 +0,0 @@ -2015-12-24 Paul Schneider - - * Presta.csproj: ajout d'une configuration de debuggage pour - Lua - -2015-11-30 Paul Schneider - - * Presta.csproj: ... - -2015-11-26 Paul Schneider - - * Presta.csproj: nouvelles configurations de déploiement - -2015-11-19 Paul Schneider - - * Presta.csproj: adds a build target named "Lua" - -2015-08-20 Paul Schneider - - * Presta.csproj: The new `Presta` project ... - -2015-08-20 Paul Schneider - - * Presta.csproj: A first class - - * AssemblyInfo.cs: initial commit - diff --git a/Presta/Presta.csproj b/Presta/Presta.csproj index 6e8e3f10..b14c92ac 100644 --- a/Presta/Presta.csproj +++ b/Presta/Presta.csproj @@ -9,7 +9,7 @@ Library Presta Presta - v4.5 + v4.5.1 true diff --git a/SalesCatalog/ChangeLog b/SalesCatalog/ChangeLog deleted file mode 100644 index edf80dad..00000000 --- a/SalesCatalog/ChangeLog +++ /dev/null @@ -1,43 +0,0 @@ -2015-12-24 Paul Schneider - - * SalesCatalog.csproj: ajout d'une configuration de debuggage - pour Lua - -2015-11-30 Paul Schneider - - * SalesCatalog.csproj: ... - -2015-11-28 Paul Schneider - - * XmlCatalogProvider.cs: Le catalogue de vente implémente - mainenant l'interface d'un fournisseur de donnée comme les - autres. - Il pourrait par exemple vouloir définir des activité et des - compétences. - Pour l'instant, il n'est pas activé par la configuration, et - reste le fournisseur du catalogue legacy (voir - ). - - -2015-11-26 Paul Schneider - - * SalesCatalog.csproj: nouvelles configurations de déploiement - -2015-11-19 Paul Schneider - - * SalesCatalog.csproj: adds a build target named "Lua" - -2015-11-04 Paul Schneider - - * TestCatalogInit.cs: - -2015-10-30 Paul Schneider - - * XmlCatalog.cs: - * XmlCatalogProvider.cs: refactoring: a dedicated name space - for the catalog - -2015-07-15 Paul Schneider - - * SalesCatalog.csproj: Moves to Mono framework - diff --git a/SalesCatalog/SalesCatalog.csproj b/SalesCatalog/SalesCatalog.csproj index 4235e085..dfc20dd9 100644 --- a/SalesCatalog/SalesCatalog.csproj +++ b/SalesCatalog/SalesCatalog.csproj @@ -9,7 +9,7 @@ Library SalesCatalog SalesCatalog - v4.5 + v4.5.1 true @@ -66,7 +66,27 @@ - + + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + + + ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + @@ -87,6 +107,7 @@ + diff --git a/SalesCatalog/packages.config b/SalesCatalog/packages.config new file mode 100644 index 00000000..4d690b0f --- /dev/null +++ b/SalesCatalog/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/TestAPI/AllTests.cs b/TestAPI/AllTests.cs index 35580461..34def7b7 100644 --- a/TestAPI/AllTests.cs +++ b/TestAPI/AllTests.cs @@ -23,7 +23,7 @@ using NUnit.Framework; using System; using Yavsc.Model.Blogs; using Yavsc.Controllers; -using System.Web.Mvc; +using System.Web.Mvc; using System.Web.Security; using System.Web.Configuration; using System.Configuration; @@ -39,7 +39,7 @@ namespace Yavsc { [Suite] public static IEnumerable Suite - { + { get { ArrayList suite = new ArrayList (); diff --git a/TestAPI/ChangeLog b/TestAPI/ChangeLog deleted file mode 100644 index 49fe0d88..00000000 --- a/TestAPI/ChangeLog +++ /dev/null @@ -1,46 +0,0 @@ -2015-12-24 Paul Schneider - - * TestAPI.csproj: ajout d'une configuration de debuggage pour - Lua - -2015-11-30 Paul Schneider - - * TestAPI.csproj: ... - -2015-11-26 Paul Schneider - - * TestAPI.csproj: nouvelles configurations de déploiement - -2015-11-25 Paul Schneider - - * TestAPI.csproj: ... une référence au framework 4.5.1 en - moins ... - -2015-11-19 Paul Schneider - - * TestAPI.csproj: adds a build target named "Lua" - -2015-11-14 Paul Schneider - - * TestAPI.csproj: nothing to view - -2015-11-04 Paul Schneider - - * test-domain-TestAPI.config: - -2015-11-01 Paul Schneider - - * test-domain-TestAPI.config: profile dates must be returned - as DateTime - -2015-10-17 Paul Schneider - - * AllTests.cs: - * HelloWorld.cs: - * DebugServer.cs: - * TestAPI.csproj: - * TestAutomate.cs: - * ServerTestCase.cs: - * BlogUnitTestCase.cs: - * test-domain-TestAPI.config: - diff --git a/TestAPI/TestAPI.csproj b/TestAPI/TestAPI.csproj index c7bbc861..017a5ee2 100644 --- a/TestAPI/TestAPI.csproj +++ b/TestAPI/TestAPI.csproj @@ -70,9 +70,6 @@ ..\packages\Machine.Specifications.Runner.Utility.0.9.0\lib\net45\Machine.Specifications.Runner.Utility.dll - - nunit - ..\packages\Machine.Specifications.Should.0.8.0\lib\net45\Machine.Specifications.Should.dll @@ -85,12 +82,10 @@ ..\packages\Spark.1.8.1.0\lib\NET45\Spark.dll - - @@ -100,27 +95,54 @@ ..\..\..\..\..\usr\lib\mono\4.5\xsp4.exe - - nunit - - - nunit - - - nunit - nuget-core + + ..\packages\NUnit.3.0.1\lib\net45\nunit.framework.dll + + + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + + + ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + + + ..\packages\Microsoft.AspNet.WebApi.Client.5.2.3\lib\net45\System.Net.Http.Formatting.dll + + + + ..\packages\Microsoft.AspNet.WebApi.Core.5.2.3\lib\net45\System.Web.Http.dll + + + ..\packages\Microsoft.AspNet.WebApi.WebHost.5.2.3\lib\net45\System.Web.Http.WebHost.dll + + + ..\packages\Newtonsoft.Json.8.0.1\lib\net45\Newtonsoft.Json.dll + - diff --git a/TestAPI/packages.config b/TestAPI/packages.config index 65aaccec..99346f07 100644 --- a/TestAPI/packages.config +++ b/TestAPI/packages.config @@ -1,8 +1,18 @@ - - - - - - - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebControls/ChangeLog b/WebControls/ChangeLog deleted file mode 100644 index 04af7e23..00000000 --- a/WebControls/ChangeLog +++ /dev/null @@ -1,80 +0,0 @@ -2015-12-24 Paul Schneider - - * WebControls.csproj: ajout d'une configuration de debuggage - pour Lua - -2015-11-30 Paul Schneider - - * WebControls.csproj: ... - -2015-11-30 Paul Schneider - - * ResultPages.cs: ajoute une classe css au bloc de liens vers - les autres pages de resultat - -2015-11-26 Paul Schneider - - * WebControls.csproj: nouvelles configurations de déploiement - -2015-11-19 Paul Schneider - - * WebControls.csproj: Lua config - -2015-11-17 Paul Schneider - - * RateControl.cs: refactorization - -2015-11-14 Paul Schneider - - * RateControl.cs: Uses its data model, and moves to the - general name space. - - * WebControls.csproj: Implements a server side rating control - -2015-10-13 Paul Schneider - - * ResultPages.cs: A multi-pages result meta info when one page - only - -2015-10-04 Paul Schneider - - * ResultPages.cs: . - -2015-09-23 Paul Schneider - - * InputUserName.cs: formatting - -2015-09-10 Paul Schneider - - * InputCircle.cs: using the new CircleBase class - - * ResultPages.cs: Using a new "None" attribute - -2015-08-22 Paul Schneider - - * InputCircle.cs: this class is about to be removed - -2015-08-20 Paul Schneider - - * InputCircle.cs: fixes the new CircleManager interface usage - -2015-07-15 Paul Schneider - - * WebControls.csproj: Moves to Mono framework - -2015-07-02 Paul Schneider - - * UserCard.cs: - * InputCircle.cs: - -2015-06-10 Paul Schneider - - * InputCircle.cs: An input control specialized for circle - selection - - * UserCard.cs: Displays user informations on a little div - - * InputUserName.cs: Fixes the ToolBoxData attribute - - * WebControls.csproj: - diff --git a/WebControls/WebControls.csproj b/WebControls/WebControls.csproj index ae3d9d53..2d204e82 100644 --- a/WebControls/WebControls.csproj +++ b/WebControls/WebControls.csproj @@ -9,7 +9,7 @@ Library WebControls Yavsc.WebControls - v4.5 + v4.5.1 true @@ -66,10 +66,30 @@ - - + + ..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll + + + ..\packages\Microsoft.AspNet.Razor.3.2.3\lib\net45\System.Web.Razor.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.Helpers.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Deployment.dll + + + ..\packages\Microsoft.AspNet.WebPages.3.2.3\lib\net45\System.Web.WebPages.Razor.dll + + + ..\packages\Microsoft.AspNet.Mvc.5.2.3\lib\net45\System.Web.Mvc.dll + False + @@ -86,4 +106,7 @@ YavscModel + + + \ No newline at end of file diff --git a/WebControls/packages.config b/WebControls/packages.config new file mode 100644 index 00000000..4d690b0f --- /dev/null +++ b/WebControls/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/plugins/fortune/ChangeLog b/plugins/fortune/ChangeLog deleted file mode 100644 index 0de51e68..00000000 --- a/plugins/fortune/ChangeLog +++ /dev/null @@ -1,25 +0,0 @@ -2015-12-24 Paul Schneider - - * fortune.csproj: ajout d'une configuration de debuggage pour - Lua - -2015-11-30 Paul Schneider - - * fortune.csproj: ... - -2015-11-26 Paul Schneider - - * fortune.csproj: nouvelles configurations de déploiement - -2015-11-19 Paul Schneider - - * fortune.csproj: adds a build target named "Lua" - -2015-08-04 Paul Schneider - - * MyClass.cs: refactoring from Yavsc.Model - -2015-07-15 Paul Schneider - - * fortune.csproj: Moves to Mono framework - diff --git a/plugins/fortune/fortune.csproj b/plugins/fortune/fortune.csproj index fdefd7d6..ced4d7f8 100644 --- a/plugins/fortune/fortune.csproj +++ b/plugins/fortune/fortune.csproj @@ -9,7 +9,7 @@ Library fortune fortune - v4.5 + v4.5.1 true @@ -63,7 +63,6 @@ - diff --git a/web/ApiControllers/AccountController.cs b/web/ApiControllers/AccountController.cs index a0d50d7f..9fff00b8 100644 --- a/web/ApiControllers/AccountController.cs +++ b/web/ApiControllers/AccountController.cs @@ -26,14 +26,493 @@ using System.Web.Security; using System.Web.Profile; using Yavsc.Helpers; using System.Collections.Specialized; +using Yavsc.App_Start; +using Microsoft.Owin.Security; +using Microsoft.AspNet.Identity; +using Yavsc.Models.Identity; +using Microsoft.Owin.Security.Cookies; +using Microsoft.AspNet.Identity.EntityFramework; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Security.Claims; +using Microsoft.Owin.Security.OAuth; +using Yavsc.Providers; +using System.Security.Cryptography; +using System.Web; +using Microsoft.AspNet.Identity.Owin; namespace Yavsc.ApiControllers { - /// - /// Account controller. - /// - public class AccountController : YavscController + [Authorize] + [RoutePrefix("api/Account")] + public class AccountController : ApiController { + private const string LocalLoginProvider = "Local"; + private ApplicationUserManager _userManager; + + public AccountController() + { + } + + public AccountController(ApplicationUserManager userManager, + ISecureDataFormat accessTokenFormat) + { + UserManager = userManager; + AccessTokenFormat = accessTokenFormat; + } + + public ApplicationUserManager UserManager + { + get + { + return _userManager ?? Request.GetOwinContext().GetUserManager(); + } + private set + { + _userManager = value; + } + } + + public ISecureDataFormat AccessTokenFormat { get; private set; } + + // GET api/Account/UserInfo + [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] + [Route("UserInfo")] + public UserInfoViewModel GetUserInfo() + { + ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity); + + return new UserInfoViewModel + { + Email = User.Identity.GetUserName(), + HasRegistered = externalLogin == null, + LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null + }; + } + + // POST api/Account/Logout + [Route("Logout")] + public IHttpActionResult Logout() + { + Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType); + return Ok(); + } + + // GET api/Account/ManageInfo?returnUrl=%2F&generateState=true + [Route("ManageInfo")] + public async Task GetManageInfo(string returnUrl, bool generateState = false) + { + IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId()); + + if (user == null) + { + return null; + } + + List logins = new List(); + + foreach (IdentityUserLogin linkedAccount in user.Logins) + { + logins.Add(new UserLoginInfoViewModel + { + LoginProvider = linkedAccount.LoginProvider, + ProviderKey = linkedAccount.ProviderKey + }); + } + + if (user.PasswordHash != null) + { + logins.Add(new UserLoginInfoViewModel + { + LoginProvider = LocalLoginProvider, + ProviderKey = user.UserName, + }); + } + + return new ManageInfoViewModel + { + LocalLoginProvider = LocalLoginProvider, + Email = user.UserName, + Logins = logins, + ExternalLoginProviders = GetExternalLogins(returnUrl, generateState) + }; + } + + // POST api/Account/ChangePassword + [Route("ChangePassword")] + public async Task ChangePassword(ChangePasswordBindingModel model) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, + model.NewPassword); + + if (!result.Succeeded) + { + return GetErrorResult(result); + } + + return Ok(); + } + + // POST api/Account/SetPassword + [Route("SetPassword")] + public async Task SetPassword(SetPasswordBindingModel model) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword); + + if (!result.Succeeded) + { + return GetErrorResult(result); + } + + return Ok(); + } + + // POST api/Account/AddExternalLogin + [Route("AddExternalLogin")] + public async Task AddExternalLogin(AddExternalLoginBindingModel model) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); + + AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken); + + if (ticket == null || ticket.Identity == null || (ticket.Properties != null + && ticket.Properties.ExpiresUtc.HasValue + && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow)) + { + return BadRequest("External login failure."); + } + + ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity); + + if (externalData == null) + { + return BadRequest("The external login is already associated with an account."); + } + + IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(), + new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey)); + + if (!result.Succeeded) + { + return GetErrorResult(result); + } + + return Ok(); + } + + // POST api/Account/RemoveLogin + [Route("RemoveLogin")] + public async Task RemoveLogin(RemoveLoginBindingModel model) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + IdentityResult result; + + if (model.LoginProvider == LocalLoginProvider) + { + result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId()); + } + else + { + result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(), + new UserLoginInfo(model.LoginProvider, model.ProviderKey)); + } + + if (!result.Succeeded) + { + return GetErrorResult(result); + } + + return Ok(); + } + + // GET api/Account/ExternalLogin + [OverrideAuthentication] + [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)] + [AllowAnonymous] + [Route("ExternalLogin", Name = "ExternalLogin")] + public async Task GetExternalLogin(string provider, string error = null) + { + if (error != null) + { + return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error)); + } + + if (!User.Identity.IsAuthenticated) + { + return new ChallengeResult(provider, this); + } + + ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity); + + if (externalLogin == null) + { + return InternalServerError(); + } + + if (externalLogin.LoginProvider != provider) + { + Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); + return new ChallengeResult(provider, this); + } + + ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider, + externalLogin.ProviderKey)); + + bool hasRegistered = user != null; + + if (hasRegistered) + { + Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie); + + ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager, + OAuthDefaults.AuthenticationType); + ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager, + CookieAuthenticationDefaults.AuthenticationType); + + AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName); + Authentication.SignIn(properties, oAuthIdentity, cookieIdentity); + } + else + { + IEnumerable claims = externalLogin.GetClaims(); + ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType); + Authentication.SignIn(identity); + } + + return Ok(); + } + + // GET api/Account/ExternalLogins?returnUrl=%2F&generateState=true + [AllowAnonymous] + [Route("ExternalLogins")] + public IEnumerable GetExternalLogins(string returnUrl, bool generateState = false) + { + IEnumerable descriptions = Authentication.GetExternalAuthenticationTypes(); + List logins = new List(); + + string state; + + if (generateState) + { + const int strengthInBits = 256; + state = RandomOAuthStateGenerator.Generate(strengthInBits); + } + else + { + state = null; + } + + foreach (AuthenticationDescription description in descriptions) + { + ExternalLoginViewModel login = new ExternalLoginViewModel + { + Name = description.Caption, + Url = Url.Route("ExternalLogin", new + { + provider = description.AuthenticationType, + response_type = "token", + client_id = Startup.PublicClientId, + redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri, + state = state + }), + State = state + }; + logins.Add(login); + } + + return logins; + } + + // POST api/Account/Register + [AllowAnonymous] + [Route("Register")] + public async Task Register(RegisterBindingModel model) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var user = new ApplicationUser() { UserName = model.Email, Email = model.Email }; + + IdentityResult result = await UserManager.CreateAsync(user, model.Password); + + if (!result.Succeeded) + { + return GetErrorResult(result); + } + + return Ok(); + } + + // POST api/Account/RegisterExternal + [OverrideAuthentication] + [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)] + [Route("RegisterExternal")] + public async Task RegisterExternal(RegisterExternalBindingModel model) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var info = await Authentication.GetExternalLoginInfoAsync(); + if (info == null) + { + return InternalServerError(); + } + + var user = new ApplicationUser() { UserName = model.Email, Email = model.Email }; + + IdentityResult result = await UserManager.CreateAsync(user); + if (!result.Succeeded) + { + return GetErrorResult(result); + } + + result = await UserManager.AddLoginAsync(user.Id, info.Login); + if (!result.Succeeded) + { + return GetErrorResult(result); + } + return Ok(); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + UserManager.Dispose(); + } + + base.Dispose(disposing); + } + + #region Helpers + + private IAuthenticationManager Authentication + { + get { return Request.GetOwinContext().Authentication; } + } + + private IHttpActionResult GetErrorResult(IdentityResult result) + { + if (result == null) + { + return InternalServerError(); + } + + if (!result.Succeeded) + { + if (result.Errors != null) + { + foreach (string error in result.Errors) + { + ModelState.AddModelError("", error); + } + } + + if (ModelState.IsValid) + { + // No ModelState errors are available to send, so just return an empty BadRequest. + return BadRequest(); + } + + return BadRequest(ModelState); + } + + return null; + } + + private class ExternalLoginData + { + public string LoginProvider { get; set; } + public string ProviderKey { get; set; } + public string UserName { get; set; } + + public IList GetClaims() + { + IList claims = new List(); + claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider)); + + if (UserName != null) + { + claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider)); + } + + return claims; + } + + public static ExternalLoginData FromIdentity(ClaimsIdentity identity) + { + if (identity == null) + { + return null; + } + + Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier); + + if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer) + || String.IsNullOrEmpty(providerKeyClaim.Value)) + { + return null; + } + + if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer) + { + return null; + } + + return new ExternalLoginData + { + LoginProvider = providerKeyClaim.Issuer, + ProviderKey = providerKeyClaim.Value, + UserName = identity.FindFirstValue(ClaimTypes.Name) + }; + } + } + + private static class RandomOAuthStateGenerator + { + private static RandomNumberGenerator _random = new RNGCryptoServiceProvider(); + + public static string Generate(int strengthInBits) + { + const int bitsPerByte = 8; + + if (strengthInBits % bitsPerByte != 0) + { + throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits"); + } + + int strengthInBytes = strengthInBits / bitsPerByte; + + byte[] data = new byte[strengthInBytes]; + _random.GetBytes(data); + return HttpServerUtility.UrlTokenEncode(data); + } + } + + #endregion /// /// Register the specified model. @@ -41,7 +520,7 @@ namespace Yavsc.ApiControllers /// Model. [Authorize ()] [ValidateAjaxAttribute] - public HttpResponseMessage Register ([FromBody] RegisterClientModel model) + public void Register ([FromBody] RegisterClientModel model) { if (ModelState.IsValid) { @@ -51,7 +530,7 @@ namespace Yavsc.ApiControllers ModelState.AddModelError ("Register", "Since you're not member of Admin or FrontOffice groups, " + "you cannot ask for a pre-approuved registration"); - return DefaultResponse (); + return ; } MembershipCreateStatus mcs; var user = Membership.CreateUser ( @@ -86,7 +565,6 @@ namespace Yavsc.ApiControllers break; } } - return DefaultResponse (); } /// @@ -96,7 +574,8 @@ namespace Yavsc.ApiControllers [ValidateAjax] public void ResetPassword (LostPasswordModel model) { - if (ModelState.IsValid) { + if (ModelState.IsValid) + { StringDictionary errors; MembershipUser user; YavscHelpers.ValidatePasswordReset (model, out errors, out user); @@ -107,6 +586,10 @@ namespace Yavsc.ApiControllers } } + /// + /// Login the specified model. + /// + /// Model. [ValidateAjax] public void Login(LoginModel model) { diff --git a/web/ApiControllers/AuthorizationDenied.cs b/web/ApiControllers/AuthorizationDenied.cs index 2193e6aa..fa4b33ff 100644 --- a/web/ApiControllers/AuthorizationDenied.cs +++ b/web/ApiControllers/AuthorizationDenied.cs @@ -41,14 +41,15 @@ namespace Yavsc.ApiControllers /// /// Authorization denied. /// - public class AuthorizationDenied : HttpRequestException { + public class AuthorizationDenied : HttpResponseException { /// /// Initializes a new instance of the Yavsc.ApiControllers.AuthorizationDenied class. /// /// Message. - public AuthorizationDenied(string msg) : base(msg) + public AuthorizationDenied() : base(HttpStatusCode.Forbidden) { + } } diff --git a/web/ApiControllers/BlogsController.cs b/web/ApiControllers/BlogsController.cs index f9aa0ea5..414a2b2a 100644 --- a/web/ApiControllers/BlogsController.cs +++ b/web/ApiControllers/BlogsController.cs @@ -66,7 +66,7 @@ namespace Yavsc.ApiControllers public void RemoveTitle(string user, string title) { if (Membership.GetUser ().UserName != user) if (!Roles.IsUserInRole("Admin")) - throw new AuthorizationDenied (user); + throw new AuthorizationDenied (); BlogManager.RemoveTitle (user, title); } @@ -103,9 +103,13 @@ namespace Yavsc.ApiControllers public async Task PostFile(long id) { if (!(Request.Content.Headers.ContentType.MediaType=="multipart/form-data")) throw new HttpRequestException ("not a multipart/form-data request"); + if (id == 0) { + throw new NotImplementedException (); + } + BlogEntry be = BlogManager.GetPost (id); if (be.Author != Membership.GetUser ().UserName) - throw new AuthorizationDenied ("b"+id); + throw new AuthorizationDenied (); string root = HttpContext.Current.Server.MapPath("~/bfiles/"+id); DirectoryInfo di = new DirectoryInfo (root); if (!di.Exists) di.Create (); @@ -116,14 +120,11 @@ namespace Yavsc.ApiControllers // Read the form data. await Request.Content.ReadAsMultipartAsync(provider) ; var invalidChars = Path.GetInvalidFileNameChars(); - foreach (string fkey in provider.BodyPartFileNames.Keys) + foreach (var file in provider.FileData) { - string filename = provider.BodyPartFileNames[fkey]; + string filename = file.LocalFileName; Trace.WriteLine(filename); - - string nicename = HttpUtility.UrlDecode(fkey) ; - if (fkey.StartsWith("\"") && fkey.EndsWith("\"") && fkey.Length > 2) - nicename = fkey.Substring(1,fkey.Length-2); + string nicename = file.Headers.ContentDisposition.FileName ; nicename = new string (nicename.Where( x=> !invalidChars.Contains(x)).ToArray()); nicename = nicename.Replace(' ','_'); var dest = Path.Combine(root,nicename); @@ -217,7 +218,7 @@ namespace Yavsc.ApiControllers throw new HttpRequestException ("not a multipart/form-data request"); BlogEntry be = BlogManager.GetPost (id); if (be.Author != Membership.GetUser ().UserName) - throw new AuthorizationDenied ("post: "+id); + throw new AuthorizationDenied (); string root = HttpContext.Current.Server.MapPath("~/bfiles/"+id); DirectoryInfo di = new DirectoryInfo (root); if (!di.Exists) di.Create (); @@ -231,11 +232,11 @@ namespace Yavsc.ApiControllers var invalidChars = Path.GetInvalidFileNameChars(); List bodies = new List(); - foreach (string fkey in provider.BodyPartFileNames.Keys) + foreach (var file in provider.FileData) { - string filename = provider.BodyPartFileNames[fkey]; + string filename = file.LocalFileName; - string nicename=fkey; + string nicename= file.Headers.ContentDisposition.FileName; var filtered = new string (nicename.Where( x=> !invalidChars.Contains(x)).ToArray()); FileInfo fi = new FileInfo(filtered); diff --git a/web/ApiControllers/CalendarController.cs b/web/ApiControllers/CalendarController.cs index 3cf74e57..fefc771d 100644 --- a/web/ApiControllers/CalendarController.cs +++ b/web/ApiControllers/CalendarController.cs @@ -29,6 +29,7 @@ using Yavsc.Model.Circles; using Yavsc.Model.Calendar; using System.Web.Http.Routing; using System.Collections.Generic; +using Yavsc.Model.Maps; namespace Yavsc.ApiControllers @@ -44,7 +45,8 @@ namespace Yavsc.ApiControllers new YaEvent () { Description = "Test Descr", Title = "Night club special bubble party", - Location = new Position () { + Location = new Location () { + Address = "2 bd A Bri", Longitude = 0, Latitude = 0 } @@ -52,7 +54,7 @@ namespace Yavsc.ApiControllers new YaEvent () { Title = "Test2", Photo = "http://bla/im.png", - Location = new Position () { + Location = new Location () { Longitude = 0, Latitude = 0 } @@ -60,7 +62,7 @@ namespace Yavsc.ApiControllers new YaEvent () { Description = "Test Descr", Title = "Night club special bubble party", - Location = new Position () { + Location = new Location () { Longitude = 0, Latitude = 0 } @@ -68,7 +70,7 @@ namespace Yavsc.ApiControllers new YaEvent () { Title = "Test2", Photo = "http://bla/im.png", - Location = new Position () { + Location = new Location () { Longitude = 0, Latitude = 0 } diff --git a/web/ApiControllers/ChallengeResult.cs b/web/ApiControllers/ChallengeResult.cs new file mode 100644 index 00000000..39f2cf56 --- /dev/null +++ b/web/ApiControllers/ChallengeResult.cs @@ -0,0 +1,53 @@ +// +// AccountController.cs +// +// Author: +// Paul Schneider +// +// Copyright (c) 2015 GNU GPL +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +using System; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Web.Http; +using Owin; +using Microsoft.Owin.Extensions; + +namespace Yavsc.ApiControllers +{ + public class ChallengeResult : IHttpActionResult + { + public ChallengeResult(string loginProvider, ApiController controller) + { + LoginProvider = loginProvider; + Request = controller.Request; + } + + public string LoginProvider { get; set; } + public HttpRequestMessage Request { get; set; } + + public Task ExecuteAsync(CancellationToken cancellationToken) + { + Request.GetOwinContext().Authentication.Challenge(LoginProvider); + + HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized); + response.RequestMessage = Request; + return Task.FromResult(response); + } + } + +} diff --git a/web/ApiControllers/CircleController.cs b/web/ApiControllers/CircleController.cs index 6b12bfa8..26b852b0 100644 --- a/web/ApiControllers/CircleController.cs +++ b/web/ApiControllers/CircleController.cs @@ -129,7 +129,7 @@ namespace Yavsc.ApiControllers string user = Membership.GetUser ().UserName; CircleBase current = CircleManager.DefaultProvider.Get (circle.Id); if (current.Owner != user) - throw new AuthorizationDenied ("Your not owner of circle at id "+circle.Id); + throw new AuthorizationDenied (); CircleManager.DefaultProvider.UpdateCircle (circle); } diff --git a/web/ApiControllers/FrontOfficeController.cs b/web/ApiControllers/FrontOfficeController.cs index f3f05158..38a0dbd3 100644 --- a/web/ApiControllers/FrontOfficeController.cs +++ b/web/ApiControllers/FrontOfficeController.cs @@ -84,10 +84,7 @@ namespace Yavsc.ApiControllers if (est.Client != username) if (!Roles.IsUserInRole("Admin")) if (!Roles.IsUserInRole("FrontOffice")) - throw new AuthorizationDenied ( - string.Format ( - "Auth denied to eid {1} for:{2}", - id, username)); + throw new AuthorizationDenied (); return est; } diff --git a/web/ApiControllers/YavscController.cs b/web/ApiControllers/YavscController.cs index 76b9b471..a6788117 100644 --- a/web/ApiControllers/YavscController.cs +++ b/web/ApiControllers/YavscController.cs @@ -55,17 +55,6 @@ namespace Yavsc.ApiControllers pr.Save (); } } - /// - /// Defaults the response. - /// - /// The response. - protected HttpResponseMessage DefaultResponse() - { - return ModelState.IsValid ? - Request.CreateResponse (System.Net.HttpStatusCode.OK) : - Request.CreateResponse (System.Net.HttpStatusCode.BadRequest, - ValidateAjaxAttribute.GetErrorModelObject (ModelState)); - } } } diff --git a/web/App_Code/Global.asax.cs b/web/App_Code/Global.asax.cs index 835aeb21..1a686a70 100644 --- a/web/App_Code/Global.asax.cs +++ b/web/App_Code/Global.asax.cs @@ -106,7 +106,7 @@ namespace Yavsc protected void Application_Start () { AreaRegistration.RegisterAllAreas (); - WebApiConfig.Register (GlobalConfiguration.Configuration); + GlobalConfiguration.Configure (WebApiConfig.Register); RegisterRoutes (RouteTable.Routes); AjaxHelper.GlobalizationScriptPath = "~/Scripts/globalize"; diff --git a/web/App_Start/IdentityConfig.cs b/web/App_Start/IdentityConfig.cs new file mode 100644 index 00000000..a3c13ecc --- /dev/null +++ b/web/App_Start/IdentityConfig.cs @@ -0,0 +1,45 @@ +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.EntityFramework; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin; +using Yavsc.Models.Identity; + +namespace Yavsc.App_Start +{ + // Configure the application user manager used in this application. UserManager is defined in ASP.NET Identity and is used by the application. + + public class ApplicationUserManager : UserManager + { + public ApplicationUserManager(IUserStore store) + : base(store) + { + } + + public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context) + { + var manager = new ApplicationUserManager(new UserStore(context.Get())); + // Configure validation logic for usernames + manager.UserValidator = new UserValidator(manager) + { + AllowOnlyAlphanumericUserNames = false, + RequireUniqueEmail = true + }; + // Configure validation logic for passwords + manager.PasswordValidator = new PasswordValidator + { + RequiredLength = 6, + RequireNonLetterOrDigit = true, + RequireDigit = true, + RequireLowercase = true, + RequireUppercase = true, + }; + var dataProtectionProvider = options.DataProtectionProvider; + if (dataProtectionProvider != null) + { + manager.UserTokenProvider = new DataProtectorTokenProvider(dataProtectionProvider.Create("ASP.NET Identity")); + } + return manager; + } + } +} diff --git a/web/App_Start/Startup.Auth.cs b/web/App_Start/Startup.Auth.cs new file mode 100644 index 00000000..adecebe9 --- /dev/null +++ b/web/App_Start/Startup.Auth.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.EntityFramework; +using Microsoft.Owin; +using Microsoft.Owin.Security.Cookies; +using Microsoft.Owin.Security.Google; +using Microsoft.Owin.Security.OAuth; +using Owin; +using Yavsc.Models.Identity; +using Yavsc.Providers; + +namespace Yavsc.App_Start +{ + public partial class Startup + { + public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; } + + public static string PublicClientId { get; private set; } + + // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864 + public void ConfigureAuth(IAppBuilder app) + { + // Configure the db context and user manager to use a single instance per request + app.CreatePerOwinContext(ApplicationDbContext.Create); + app.CreatePerOwinContext(ApplicationUserManager.Create); + + // Enable the application to use a cookie to store information for the signed in user + // and to use a cookie to temporarily store information about a user logging in with a third party login provider + app.UseCookieAuthentication(new CookieAuthenticationOptions()); + app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); + + // Configure the application for OAuth based flow + PublicClientId = "self"; + OAuthOptions = new OAuthAuthorizationServerOptions + { + TokenEndpointPath = new PathString("/Token"), + Provider = new ApplicationOAuthProvider(PublicClientId), + AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"), + AccessTokenExpireTimeSpan = TimeSpan.FromDays(14), + AllowInsecureHttp = true + }; + + // Enable the application to use bearer tokens to authenticate users + app.UseOAuthBearerTokens(OAuthOptions); + + // Uncomment the following lines to enable logging in with third party login providers + //app.UseMicrosoftAccountAuthentication( + // clientId: "", + // clientSecret: ""); + + //app.UseTwitterAuthentication( + // consumerKey: "", + // consumerSecret: ""); + + //app.UseFacebookAuthentication( + // appId: "", + // appSecret: ""); + + //app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() + //{ + // ClientId = "", + // ClientSecret = "" + //}); + } + } +} \ No newline at end of file diff --git a/web/App_Start/Startup.cs b/web/App_Start/Startup.cs new file mode 100644 index 00000000..e34f32e5 --- /dev/null +++ b/web/App_Start/Startup.cs @@ -0,0 +1,38 @@ +// +// Startup.cs +// +// Author: +// Paul Schneider +// +// Copyright (c) 2015 GNU GPL +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see . +using System; +using Microsoft.Owin; +using Owin; + + +[assembly: OwinStartup(typeof(Yavsc.App_Start.Startup))] +namespace Yavsc.App_Start +{ + public partial class Startup + { + public void Configuration(IAppBuilder app) + { + ConfigureAuth (app); + + } + } +} + diff --git a/web/ChangeLog b/web/ChangeLog deleted file mode 100644 index d4d9708b..00000000 --- a/web/ChangeLog +++ /dev/null @@ -1,1927 +0,0 @@ -2015-12-30 Paul Schneider - - * Web.config: l'entité nbsp n'est plus supportée - - * Yavsc.csproj: mise à niveau de Newtownsoft.Json - - * packages.config: mise à jour des paquets nuget - -2015-12-30 Paul Schneider - - * Sent.aspx: Vue de confirmation du messag envoyé - - * Global.asax.cs: ajout d'une route /to/ - - * style.css: rien - - * style.css: forme du pointeur de liens - - * FrontOfficeController.cs: implémente l'envoi d'un e-mail au - préstataire - - * YavscHelpers.cs: - * HomeController.cs: l'e-mail admin est obtenu du helper - global - - * App.master: Corrige les guillemets autour de notifications - web - - * yavsc.js: la class des liens est "link", pas "actionlink" - - * Contact.aspx: mise en forme du formulaire de contact - - * Performer.ascx: lien vers le contact préstataire - - * Yavsc.csproj: ajout de la vue du message envoyé - -2015-12-30 Paul Schneider - - * ResetPassword.txt: Un message pour le mot de passe oublié - - * style.css: fixe un 404 - - * UpdatePassword.aspx: Implémente le formulaire de mise à jour - du mot de passe, - accessible depuis l'e-mail. - - * Contact.aspx: implémente la page de contact préstataire - - * BasketController.cs: renvoie l'objet décrivant la prise de - commande - - * Global.asax.cs: ignorer les routes vers App_Data et App_Code - - * instdbws.sql: passage du type json à jsonb pour les - paramètres de la commande - - * RegistrationMail.txt: un piti message à l'enregistrement - - * AccountController.cs: Envoi du message du mot de passe - oublié, - methode de changemnet du mot de passe. - - * AdminController.cs: xmldoc + refabrication helper Notify - - * HomeController.cs: - * BlogsController.cs: - * GoogleController.cs: refabrication helper Notify - - * FrontOfficeController.cs: Refabrication: Utilisation du - nouvel enregistrement de commande. - + refabrication helper Notify - - * YavscHelpers.cs: implémente la methode d'envoi du message de - mot de passe oublié - + refabrication helper Notify - - * App.master: Corrige la notification Html - - * AppAdmin.master: Le lien vers la page de contact était - associé - à tort à la classe css "thanks" - - * yavsc.js: message plus parlant en cas de requête Ajax mal - formée. - - * Login.aspx: Implémente le lien vers le formulaire de - recupération du mot de passe - - * UserPost.aspx: . - - * Booking.aspx: format du code - - * Performer.ascx: l'e-mail préstataire ne sera jamais fourni - par l'application, - aussi, on parlera de "prendre contact", d'échanger ... mais - pas de donner l'adresse e-mail. - L'information "son email" n'est donc pas disponible meme à - l'utilisateur autorisé. - La prise de contact, ou autre fux de comunication le sont. - - * Performers.aspx: affiche la notification à l'envoi de la - demande de devis - - * Product.aspx: - * Service.aspx: les periodes du catalogue et du calendrier - sont fondue. - - * Contact.aspx: traduction en français - - * Web.config: * la procédure de recupération du mot de passe - est activée - * l'e-message envoyé est construit à partir d'un modèle, un - fichier texte trouvé dans /App_Data, et indiqué à - l'application - par le paramêtre applicatif "LostPasswordMessage" - - * Yavsc.csproj: reference les nouveaux fichiers - - * OtherWebException.aspx: page obsolete - -2015-12-24 Paul Schneider - - * App.master: traductions - - * EventPub.aspx: debug sur page encore inutilisée - - * Yavsc.csproj: ajout d'une configuration de debuggage pour - Lua - -2015-12-23 Paul Schneider - - * Web.config: Ajoute le paramètre obligatoire "Themes" au - fichier de configuration - - * YavscHelpers.cs: fixe l'absence de configuration des thèmes - disponibles - -2015-12-23 Paul Schneider - - * blanc.png: - * logo-white.png: - * musician-923526_1280.jpg: - * musician-923526_1.nb.jpg: - * musician-923526_1.nbb.jpg: - * musician-923526_1280.s.jpg: - * musician-923526_1.nbbi.jpg: - * musician-923526_1.nb.xs.jpg: - * live-concert-388160_1280.jpg: - * musician-923526_1280.xxs.jpg: - * musician-923526_1.nbb.xs.jpg: - * musician-923526_1.nb.xxs.jpg: - * musician-923526_1.nbbi.xs.jpg: - * musician-923526_1.nbb.xxs.jpg: - * musician-923526_1.nbbi.xxs.jpg: - * live-concert-388160_1280.s.jpg: - * live-concert-388160_1280.xxs.jpg: - - * BackOfficeController.cs: - * FrontOfficeController.cs: - * BackOfficeController.cs: refabrication - -2015-12-23 Paul Schneider - - * AccountController.cs: implémente la methode de login de - l'API - - * BasketController.cs: implémente la methode de recupération - du panier - - * AccountController.cs: enléve un commaentaire obsolète - - * YavscHelpers.cs: - * FrontOfficeController.cs: refabrication de l'ajout au panier - - * yavsc.user.js: enlève un message de debuggage js - - * Performer.ascx: formattage - - * Performers.aspx: implémente le bouton de demande de - reservation - - * Yavsc.csproj: validate unobtrusive - - * packages.config: référence M$ Owin - - * Web.config: retour à une version d'équère - -2015-12-16 Paul Schneider - - * input.css: - * style.css: une feuille pour les champs de formulaire thème - sombre - - * style.css: une feuille pour un nouveau thème clair "IT" - - * style.css: une feuille pour un nouveau thème sombre "IT" - - * AccountController.cs: renseigne le combobox des thèmes - disponibles - - * YavscHelpers.cs: Prendre la liste des thème dans un - paramètre de configuration - - * Profile.aspx: Selectionner le thème avec un combo à partir - de la page du profile - - * Web.config: le thème par défaut devient "clear", - le paramètre "Themes" contient la liste des thèmes autorisés. - - * Yavsc.csproj: référencer les nouveaux thèmes - -2015-12-15 Paul Schneider - - * input.css: refabrication des feuilles de style : la feuille - des champs de formulaire. - - * AccountController.cs: implémente une méthode de l'API pour - ajouter un utilisateur au cercle - - * links.css: Corrige la couleur du boutton de validation des - formulaire de classe `ActionLink` - - * style.css: refabrication: importe la nouvelle feuille de - style des champs de formulaires - - * style.css: nettoyage du thème sombre - - * style.css: nettoyage + section principale (`main`) centré - - * FrontOfficeController.cs: Repositionne la route vers le - devis à do/Estimate - - - * YavscHelpers.cs: corrige ma ré-écriture des helpers html - ActionLink - - * App.master: formattage du code source - - * AppAdmin.master: synchronisation avec la page maître, - beaucoup de changements dans cette page maître pour les - administrateurs: - * prend en charge les côtes d'article - * utilise les fontes de caractère de la page pour les lien - action - * prend en charge les zones de formulaire masquable. - - * NoLogin.master: synchronisation avec la page maître - - * Performer.ascx: WIP permet d'ajouter un préstataire à un de - ses cercles. - - * YourEstimates.aspx: corrige un lien cassé - - * Yavsc.csproj: mise à niveau Npgsql, - renommage Estimate - - * packages.config: mise à niveau de la bibliothèque Npgsql - (pilote d'accès à la base de donnée) - - - * Estimate.aspx: refabrication - -2015-12-09 Paul Schneider - - * animate.css: animations css - - * links.css: liens avec le fond blanc qui se déroule - - * links.css: WIP liens thème sombre - - * GitHub.ico: un petit merci à GitHub - - * live-concert-fg.png: image de plan rapproché : les fans - - * live-concert-scene.jpg: Image de fond : la scene - - * splash-image-2.jpg: image de fond : photo colorée, public de - concert, vient de totemproduction.fr - - - * links.css: ficher de définitions globales du style des - bouttons (encore inutilisé) - - * yavsc.user.js: WIP implémente le widget "utilisateur", - permettant - l'affichage des liens rapides pour tout nom d'ulitisateur, le - cas échéant, vers l'ajout à un cercle, - vers son blog, vers des methodes choisies d'administateur, - vers ses réseaux sociaux, voir plus. - - * About.aspx: Implémente une page "à propos" - - * Test.aspx: Page de test: désolé pour le bruit, elle n'est - compilée qu'en mode `Debug` (elle n'est pas accessible en - production) - - * BasketController.cs: Les commandes sont fortement typée. - - * style.css: réécriture du thème clair - - * style.css: * implémente un classe css `clickme` pour attirer - l'oeil - sur le boutton de validation après la modification d'un champ - de formulaire. - * enlève tous les coins arrondis - * modifie la chasse de caractères (une seule utilisée pour le - moment) - * - - * style.css: * integre la référence à la feuille de style des - [animations](https://daneden.github.io/animate.css/) - * corrige des marges, alignements - * supprime ce qui reste de coin arrondi - * néttoye les définitions obsolètes - * définit la classe `username` - * corrige le survol à la suppression de tag - - - * FrontOfficeController.cs: renomme des methodes, refabriqué - pour s'adapter aux changements de l'API du workflow, - WIP propose les cercles utilisateurs pour l'ajout des profiles - préstataires aux cercles. - - * HomeController.cs: implémente une page "à propos" - - * T.cs: re-autorise le titre vide de page, au cas où ... car - ce n'est pas un véritable - défaut fonctionnel. - - * YavscHelpers.cs: Implemente un outil de presentation des - liens action traduits. Tous les liens action utilisent - maintenant cette nouvelle methode, - au profile de celle du framework `HtmlHelpers.ActionLink` - - * App.master: corrige l'usage du contrôle utilisateur des - cotes dans le cadre des cotes de billet. - - * AppAdmin.master: - * Index.aspx: - * Service.aspx: - * ProductCategory.aspx: traduction des liens action - - * NoLogin.master: * traduction des liens action - * suppression des liens de remerciement dans le bas de page, - cette information a été déplacée dans la page `/Home/Credits` - - * to-markdown.js: transforme maintenant les noeuds Html `div` - en paragraphes Markdown. - - * yavsc.hidefieldset.js: Le script règle la forme de la souris - au survol du bouton, - le cas échéant. - - * yavsc.js: nouvelle fonction javascript pour logger un objet - arbitraire. - - * yavsc.rate.js: Fixe la possibilité de mettre des cotes très - basses ou très hautes (reste encore un mieux à faire), - Affiche au survol des descriptions optionnelles de la cote. - - - * Title.aspx: - * UserPost.aspx: - * Edit.aspx: - * Index.aspx: - * Brand.aspx: - * Index.aspx: - * PostActions.ascx: - * TitleNotFound.aspx: - * Booking.aspx: - * Command.aspx: - * ChangePasswordSuccess.aspx: Traduction des liens action - - * Login.aspx: * Traduction des liens actionTraduction des - liens action - - * Profile.aspx: * Traduction des liens actionTraduction des - liens action - * utilisation de la classe css `mayhide` qui autorise - maintenant un champ d'entrées de formulaire à être plié/déplié - au click sur sa légende. - - * Admin.aspx: Traduction des liens actionTraduction des liens - actionTraduction des liens actionTraduction des liens - actionTraduction des liens actionTraduction des liens action - - * Backups.aspx: - * RoleList.aspx: - * UserList.aspx: - * Index.aspx: Traduction des liens actionTraduction des liens - action - - * Edit.aspx: * refabrication de la structure Html - * Traduction des liens actionTraduction des liens action - - - * Index.aspx: Simlpification des apperçus de blog - - * TagControl.ascx: refabrication pour simplifier - l'implémentation du contrôle utilisateur des tags - - * UserPosts.aspx: Traduction des liens action, et - simplification du listing de blog - - * Basket.aspx: Affiche les articles du panier de commandes - avec leur vue - dédiée à leur type (les commande sont maintenant fortement - typées) - - * Catalog.aspx: Traduction des liens action, correctin du lien - vers le produit - (cassé depuis une vielle refabrication des routes) - - * DoAnEstimate.aspx: refabrication de la vue de création du - devis: renommée depuis `Estimate` - - - * Performer.ascx: * un message supplementaire à l'absence de - compétence affichée par un préstataire - * des guillemets autour du commentaire du préstataire sur sa - compétence - * ajout du préstataire au cercles - - - * Performers.aspx: Décrit en détail les informations sur la - disponibilité d'un préstataire, - à la date demandée. - - * YourEstimates.aspx: renomage de cette page, pour préciser sa - fonction : Vos devis. - - * Contact.aspx: structure Html de la page de contact - - * Credits.aspx: Ajoute les remerciements aux communauté du - libre - - * Index.aspx: ne fait rien - - * Web.config: * import de `System.Transactions` - * mise à jour des credits libres - - * WebDeploy.targets: utilise les séparateurs de chemin vers - ficher à la POSIX, ne change rien pour ma config ... (TODO - tester sous WoinDose) - - * Yavsc.csproj: déploie des pages des scripts Javascript et - des images et feuilles de style en plus. - - * SiteSkills.aspx: renomage de cette page, pour préciser sa - fonction : les compétences sur ce site. - -2015-12-03 Paul Schneider - - * AccountController.cs: doc xml - - * CircleController.cs: renommage - - * style.css: nettoyage - - * FrontOfficeController.cs: alerte à l'edition de compétence - sans avoir choisi d'activité - - * UserList.aspx: Un titre à la liste des utilisateurs - -2015-12-03 Paul Schneider - - * Yavsc.csproj: - * jquery.mobile-1.4.5.js: - * ajax-loader.gif: - * jquery.mobile-1.4.5.css: - * jquery.mobile-1.4.5.min.js: - * jquery.mobile-1.4.5.min.map: - * jquery.mobile-1.4.5.min.css: - * FrontOfficeController.cs: - * jquery.mobile.icons-1.4.5.css: - * jquery.mobile.theme-1.4.5.css: - * tag-black.svg: - * tag-white.svg: - * eye-white.png: - * eye-black.png: - * tag-black.png: - * eye-black.svg: - * eye-white.svg: - * tag-white.png: - * mail-white.png: - * shop-white.png: - * edit-black.png: - * star-black.png: - * lock-white.png: - * mail-black.png: - * info-black.svg: - * home-black.svg: - * home-white.svg: - * edit-white.png: - * grid-white.png: - * user-black.png: - * home-black.png: - * home-white.png: - * info-black.png: - * info-white.png: - * grid-black.png: - * star-white.png: - * plus-white.svg: - * plus-black.svg: - * user-white.png: - * gear-black.png: - * gear-white.png: - * grid-white.svg: - * bars-black.svg: - * back-white.svg: - * user-white.svg: - * back-black.svg: - * info-white.svg: - * back-black.png: - * bars-white.svg: - * mail-black.svg: - * plus-white.png: - * plus-black.png: - * lock-white.svg: - * lock-black.svg: - * mail-white.svg: - * back-white.png: - * shop-white.svg: - * shop-black.svg: - * lock-black.png: - * gear-black.svg: - * gear-white.svg: - * grid-black.svg: - * star-black.svg: - * bars-black.png: - * bars-white.png: - * user-black.svg: - * star-white.svg: - * shop-black.png: - * edit-black.svg: - * edit-white.svg: - * cloud-white.svg: - * cloud-black.svg: - * clock-white.svg: - * clock-black.svg: - * check-white.svg: - * check-black.svg: - * audio-white.svg: - * video-black.png: - * video-white.png: - * alert-black.svg: - * alert-white.svg: - * heart-white.svg: - * heart-black.svg: - * audio-black.svg: - * power-white.png: - * clock-black.png: - * clock-white.png: - * cloud-black.png: - * cloud-white.png: - * power-white.svg: - * power-black.svg: - * check-white.png: - * alert-white.png: - * video-white.svg: - * video-black.svg: - * audio-black.png: - * audio-white.png: - * check-black.png: - * phone-white.svg: - * phone-black.svg: - * minus-white.svg: - * alert-black.png: - * phone-white.png: - * minus-black.png: - * minus-white.png: - * phone-black.png: - * heart-white.png: - * minus-black.svg: - * heart-black.png: - * power-black.png: - * jquery.mobile.icons-1.4.5.min.css: - * camera-black.png: - * search-black.png: - * delete-white.svg: - * action-black.png: - * jquery.mobile.theme-1.4.5.min.css: - * jquery.mobile.structure-1.4.5.css: - * camera-white.svg: - * camera-black.svg: - * delete-black.svg: - * camera-white.png: - * search-white.png: - * delete-black.png: - * action-white.svg: - * action-black.svg: - * search-white.svg: - * action-white.png: - * search-black.svg: - * delete-white.png: - * jquery.mobile.inline-png-1.4.5.css: - * recycle-black.svg: - * jquery.mobile.inline-svg-1.4.5.css: - * refresh-white.svg: - * forward-black.svg: - * forward-white.svg: - * refresh-black.svg: - * recycle-white.svg: - * comment-white.svg: - * comment-black.svg: - * carat-u-white.svg: - * recycle-white.png: - * refresh-black.png: - * carat-d-black.png: - * refresh-white.png: - * arrow-d-black.svg: - * bullets-white.png: - * bullets-black.png: - * arrow-d-white.svg: - * arrow-l-black.svg: - * recycle-black.png: - * comment-black.png: - * carat-u-white.png: - * forward-black.png: - * forward-white.png: - * carat-u-black.png: - * carat-r-white.png: - * carat-r-black.png: - * carat-l-white.png: - * carat-l-black.png: - * carat-d-white.png: - * arrow-l-white.svg: - * bullets-black.svg: - * bullets-white.svg: - * arrow-d-white.png: - * arrow-d-black.png: - * carat-d-black.svg: - * carat-d-white.svg: - * carat-l-black.svg: - * carat-l-white.svg: - * carat-r-black.svg: - * carat-r-white.svg: - * carat-u-black.svg: - * arrow-u-white.svg: - * arrow-r-black.svg: - * arrow-r-white.svg: - * arrow-u-black.svg: - * arrow-u-white.png: - * arrow-u-black.png: - * comment-white.png: - * arrow-r-white.png: - * arrow-r-black.png: - * arrow-l-white.png: - * arrow-l-black.png: - * calendar-white.png: - * calendar-black.png: - * location-black.svg: - * location-white.svg: - * calendar-black.svg: - * location-white.png: - * location-black.png: - * calendar-white.svg: - * arrow-u-l-white.svg: - * forbidden-black.svg: - * arrow-d-r-black.png: - * forbidden-white.svg: - * jquery.mobile.external-png-1.4.5.css: - * arrow-u-r-black.svg: - * arrow-u-r-white.svg: - * arrow-d-l-black.png: - * arrow-d-r-white.png: - * arrow-d-l-white.png: - * arrow-u-l-black.png: - * forbidden-black.png: - * forbidden-white.png: - * arrow-d-l-black.svg: - * arrow-d-r-white.svg: - * arrow-d-l-white.svg: - * arrow-d-r-black.svg: - * arrow-u-r-black.png: - * arrow-u-r-white.png: - * arrow-u-l-black.svg: - * arrow-u-l-white.png: - * navigation-white.svg: - * navigation-black.svg: - * navigation-black.png: - * navigation-white.png: - * jquery.mobile.structure-1.4.5.min.css: - * jquery.mobile.inline-png-1.4.5.min.css: - * jquery.mobile.inline-svg-1.4.5.min.css: - * jquery.mobile.external-png-1.4.5.min.css: - - * style.css: donne une couleur au fond des panneaux de classes - "spanel", "xspanel" et "xxspanel" - - * style.css: autorise de la largeur aux groupes de champs de - formulaire - - * T.cs: Lève une exception à la demande de traduction d'une - chaine vide. - Celà permet entre autres de s'assurer que toutes les pages ont - un titre (sans quoi, on ne peut plus les visiter). - - * yavsc.skills.js: La création d'une compétence demande - maintenant un code APE. - - * Activities.aspx: Lien vers l'edition des compétences gérées - par le site - - * ActivitySkills.aspx: Implemente la nouvelle creation des - compétences - - * packages.config: Ajout du paquetage "jQuery.Mobile" - - -2015-12-02 Paul Schneider - - * Skills.aspx: Précise la fonction de la methode par un titre - plus révélateur - - * Index.aspx: Alimente l'index du front office - -2015-12-02 Paul Schneider - - * hangouts.xml: WIP Hangouts - - * yavsc.rate.js: Fixe l'usage de la souris pour positionner - les étoiles de 0 à 5. - WIP labels - - * Performer.ascx: Prive les utilisateur anonymes de l'e-mail - des préstataires - - * Yavsc.csproj: ajoute l'Xml Hangouts - -2015-12-01 Paul Schneider - - * Yavsc.csproj: references en plus ... - -2015-12-01 Paul Schneider - - * style.css: ajoute une classe "bigavatar" (l'avatar affiché - en gros) - - * yavsc.hidefieldset.js: pas d'initialisation par défaut de - tous les fieldset - - * Profile.aspx: fieldset cachable dans cette page uniquement - - * Performer.ascx: un gros avatar ici - -2015-12-01 Paul Schneider - - * yavsc.hidefieldset.js: Creation d'un nouveau module jQuery - pour afficher/cacher les champ de formulaire en cliquant sur - le titre des groupes de champ. - - * style.css: style plus compact pour les fieldset - - * App.master: appelle l'initialisation des widget hidefieldset - - * Profile.aspx: mettre tous les elements fils d'un groupe - champ dans des noeud cachable. - - * Yavsc.csproj: referencer le nouveau script dans le projet - -2015-12-01 Paul Schneider - - * Global.asax.cs: Fixe un 404 Not Found sur le script - d'internationalisation. - - * YavscAjaxHelper.cs: Fixe un 404 Not Found sur le script - d'internationalisation: - Implementation d'une alternative à Ajax.GlobalisationScript() - de Mono System.Web.MVC - - - * App.master: utilise la nouvelle methode pour construire les - references aux scripts d'internationalisation - -2015-11-30 Paul Schneider - - * p8-av4.jpg: - * p8-av4.l.jpg: - * p8-av4.xs.jpg: p8-av4 - - * Performer.ascx: Implémente la fiche préstataire, avec son - éventuel lien vers le blog - -2015-11-30 Paul Schneider - - * SkillController.cs: - * FrontOfficeController.cs: refabrication - - * style.css: mise en forme du code - - * style.css: du style - - * Booking.aspx: - * FrontOfficeController.cs: Modifie la recherche des - prestataire, pour qu'un resultat soit donné dès qu'un - utilisateur est déclaré prestataire. - - * Title.aspx: - * YavscHelpers.cs: ajoute une classe css au bloc de liens vers - les autres pages de resultat - -2015-11-28 Paul Schneider - - * p8-av4.xxs.jpg: - * p8-av4.xxs.png: inutile - - * NoLogin.master: - * Entity.cs: - * OAuth2.cs: - * ApiClient.cs: - * PeopleApi.cs: - * MapTracks.cs: - * Skills.aspx: - * CalendarApi.cs: - * EntityQuery.cs: - * GoogleHelpers.cs: - * EventPub.aspx: - * GoogleController.cs: - * SimpleJsonPostMethod.cs: - * UserSkills.aspx: - * BackOfficeController.cs: - * BackOfficeController.cs: refabrication - - * FrontOfficeController.cs: format du code - - * Global.asax.cs: Une route customisée pour le Front Office : - /do (genre, ici, ça bouge.) - - - * activity.sql: implémente en base de donnée le modèle des - activités et compétences, - ajoute aussi deux activités : l'edition logicielle et - "Artiste" - - - * style.css: changement de mes images de fond ... tombées du - camion de Xavier et onlinehome.us - - * p8-av4.s.jpg: changement de taille - - * AccountController.cs: Met le code MEA à "none" quand il est - spécifié non disponible. - - * BlogsController.cs: fixe un bug de l'edition d'un billet - - * FrontOfficeController.cs: implemente le contrôle booking - simple - - * HomeController.cs: ajoute l'assemblage du catalog dans le - listing dédié - - * YavscAjaxHelper.cs: Implemente un outil de representation - JSon des objets côté serveur - - * parallax.js: deux fois plus de mouvement autout de x dans le - parallax - - * yavsc.rate.js: imlemente un callback JS pour le rating - - * Activities.aspx: Des labels au formulaire de déclaration des - activités - - * Activity.ascx: un panneau activité descent - - * Booking.aspx: implemente l'UI web du booking simple. - - * EavyBooking.aspx: refabrication du booking lourd - - * Index.aspx: supprime le panneau du tag Accueil, affiche les - activités en cours du site (avec au moins un préstataire - valide pour cette activité) - - * Web.config: Implemente une cote utilisateur, par une - nouvelle valeur de son profile (Rate). - - - * Yavsc.csproj: refabrique du code API Google, qui part dans - le model. - - * MarkdownDeep.dll: le tag

ne convenait pas, le remplacer - par le tag non plus. - Maintenant ça devrait être correct, c'est un div, mais que en - cas de tag englobant non défini. - - * Skills.sql: vient de passer dans activity.Sql - - * T.cs: la traduction est faite plus simple à appeler (sans - cast vers `string`). - -2015-11-26 Paul Schneider - - * Yavsc.csproj: nouvelles configurations de - déploiementnouvelles configurations de déploiement - -2015-11-26 Paul Schneider - - * BackOfficeController.cs: Impléménte un accès à l'API back - office pour l'envoi d'une notification aux mobiles des cercles - séléctionné de l'utilisateur - - * NotifyEvent.aspx: Implemente un formulaire d'envoi d'une - notification mobile - - * NotifyEventResponse.aspx: initie une page de resultat à la - notification mobile - - * BlogsController.cs: En attendant mieux, les billets de blog - sont noté par leur auteur, ou un admin. - - * CalendarController.cs: Les fontions de notification GCM et - de declaration d'enregistrement GCM - partent dans le controlleur back office. - - * activity.sql: ajoute la photo activité dans la definition du - modèle de données Npgsql - - * style.css: La fonte de caractère "Open Sans" (Google fonts) - pour le thème "clear" - - * style.css: La fonte de caractère "Open Sans" (Google fonts) - pour le thème "dark" aussi - - * style.css: pas de fonte de caractère dans la feuille de - style basique. - - * BackOfficeController.cs: Impléménte un accès web back office - pour l'envoi d'une notification aux mobiles des cercles - séléctionné de l'utilisateur - - * BlogsController.cs: Fixe la page de garde du blogspot en cas - d'absence - de billet à publier publiquement. - - * FrontOfficeController.cs: la fontion booking est maintenant - censée conerner uniquement une activité, - dont le code APE est donné en dernière partie de la route de - l'Url, ou en argument `id`. - - - * HomeController.cs: La page d'accueil présente maintenant les - activités mises en oeuvre par au moins un utilisateur - enregistré, validé et non vérouillé. - Le titre de l'activité est un lien vers la methode de - reservation simple. - - * GoogleHelpers.cs: recoit l'implementation de la methode de - notification mobile - - * SimpleJsonPostMethod.cs: Fixe l'envoi en UTF-8 - - * App.master: fonte de caractère pour le lien vers "Vos - billets" - - * parallax.js: fixe la différence de traitement entre - l'horizontale et la verticale - - * Profile.aspx: ajoute le sommaire de la validation - - * Index.aspx: initie un index pour le back office - - * Activities.aspx: nettoye la console de log javascript - - * Booking.aspx: ajoute le champ caché au formulaire de resa - - * Index.aspx: affiche les services fournis sur le site, par - des utilisateur enregistrés validés non bloqué. - - * Web.config: rends l'id Google d'enregistrement GCM - accessible au utilisateurs anonymes, - qui voudraient commander ou interagir avec l'application, sans - avoir à créer de compte sur le site. - - * Web.csproj: ajoute le contrôleur du back office, et le - formulaire de notification mobile - -2015-11-25 Paul Schneider - - * Activities.aspx: implémente la vue Html de la liste éditable - des activités - - * Activity.ascx: implémente la vue Html d'une activité - - * FrontOfficeController.cs: Le contrôleur du FrontOffice gére - les activités - - * Global.asax.cs: nettoyage du code - - * activity.sql: Typo corrigée sur le terme "MEACode" - - * style.css: enlève des images qui n'ont plus rien à faire - ici, tant ce fichier - concerne maintenant uniquement la disposition ou les éléments - de base. - - - * AccountController.cs: implémente le contrôle par - l'utilisateur du paramêtre de l'activité principale - associé à son profile. - - * FrontOfficeController.cs: Implemente le contrôle de la page - des activités, - et simplifie le contrôle de la page des compétences. - - * HomeController.cs: formattage du code - - * ModuleController.cs: inutilisé - - * App.master: Theming explicite en page maître - - * Profile.aspx: Propose maintenant l'édition de l'activité - principalement éxercée - - * Skills.aspx: supprime une ligne de log - - * Index.aspx: RAZ en home page - - * MarkdownDeep.dll: remplace le tag englobant les - transformations, - il était un "

", il est maintenant un "". - - - * Web.csproj: reference les nouveaux éléments du projet - relatifs au activités - - * Web.config: references manquante en cas d'utilisation du - paramértrage global du thème via la section system.web/pages - du fichier de configuration. - -2015-11-23 Paul Schneider - - * activity.sql: definit les activités en base de données. - - * Web.csproj: ajoute la definition de la donnée `activité`. - -2015-11-23 Paul Schneider - - * style.css: - * style.css: Ne contient plus que ce qui concerne les couleurs - et images - - * font-awesome.css: Il parait plus sage de spécifier des Url - absolues vers les polices de caractère. - - * style.css: Réccupère du thème sombre tout ce qui ne concerne - pas la couleur, pour en faire profiter tous les thèmes. - - * Web.csproj: Ajoute le style du thème clair au projet. - - * style.tablesorter.css: ce fichier est obsolete et va - disparaitre. - -2015-11-23 Paul Schneider - - * ErrorHtmlFormatter.cs: Pour note: conception à revoir - -2015-11-23 Paul Schneider - - * FrontOfficeController.cs: Démarre l'implementation des - methodes de réservation - -2015-11-23 Paul Schneider - - * MEA.sql: définit la valeur MEA du profile (Main Exerted - Activity) dans la base de donnée - - * Booking.aspx: Imlémente la vue du formulaire de reservation - simple, - c'etait avant la reservation classique, sur une période plutôt - qu'un jour. - La reservation classique est renomée `EavyBooking`. - - * FrontOfficeController.cs: definit l'interface de cotation - des compétences attendues - - * Skills.aspx: - * SkillController.cs: - * UserSkills.aspx: refactorisation (-Skill+SkillEntity) - - * UserCard.ascx: Imlémente une carte utilisateur. - - * Web.config: déclare le code activité principale exercée - parmis les valeurs du profile authentifié. - - * Web.csproj: ajoute les nouveaux formulaire de reservation au - projet. - - * EavyBooking.aspx: Implémente la reservation lourde - -2015-11-22 Paul Schneider - - * BasketController.cs: - * WorkFlowController.cs: - * FrontOfficeController.cs: - * FrontOfficeController.cs: Le manager de flux de travaux est - devient un objet statique. - - * FileSystemController.cs: refactorisation du code, en vue de - la mise en place - de la commande sans enregistrement du client sur le site. - - - * Web.csproj: ajoute les références au déployement des sites - * Totem prod - * Totem pré - Leur configuration n'est pas maintenue sous Git. - -2015-11-21 Paul Schneider - - * Microsoft.Web.XmlTransform.dll: Copié de l'import Nuget de - Mono.Web.Xdt (transformations de fichiers de configuration) - - * yavsc.admin.js: Implémente les méthodes Javascript de - l'interface utilisateur de suppression et d'ajout d'un - utilisateur à un groupe: - un widget jQuery pour la suppression, l'accès à l'API - - * RestrictedArea.aspx: Page vue par l'utilisateur si par - malheur il suivait un lien vers un contenu d'accès restreint, - à la place d'un code Http 404 ou autre. - Si cet utilisateur est administrateur, la page lui affiche les - rôles ou utilisateurs autorisés à accèder au contenu. - - - * RestrictedArea.aspx: - * RestrictedArea.aspx: - * RestrictedArea.aspx: - * RestrictedArea.aspx: - * RestrictedArea.aspx: - * RestrictedArea.aspx: - * RestrictedArea.aspx: Page vue par l'utilisateur si par - malheur il suivait un lien vers un contenu d'accès restreint, - à la place d'un code Http 404 ou autre. - Si cet utilisateur est administrateur, la page lui affiche les - rôles ou utilisateurs autorisés à accèder au contenu. - - * AccountController.cs: Evite de mettre à jour un mot de passe - avec des valeures non attendues - - * style.css: corrige un mouvement de la disposition au survol - de la souris - - * AuthorizeAttribute.cs: enlève la redirection à l'accès - restreint, et fixe pas la même la transmission des données - `Roles` et `Users` de la vue - - - * AdminController.cs: Evite de supprimer un utilisateur d'un - groupe avec des valeures non attendues - - * HomeController.cs: Il n'y avait pas à créer de methode pour - la vue publique de l'accès restreint. - - * YavscAjaxHelper.cs: évite d'avoir à convertir en chaine les - valeurs de la vue. - - - * App.master: Cette page maître affiche encore beaucoup de - billets de blog, on y installe le coteur, de base. Ça changera - quand les blogs auront (enfin) leur page maître dédiée. - - - * AppAdmin.master: synchronisation avec la page maître - principale (thémes) - - * NoLogin.master: synchronisation avec la page maître - principale.(thémes) - - * yavsc.rate.js: supprime l'initialisation de tous les type de - cotes depuis le script global. - C'est fait sur les pages qui en ont besoin, et seulement pour - les types de cotes concernés. - - * AddUserToRole.ascx: Ce formulaire est maintenant à la fois - opérationel depuis une interface web sans javascript, et à la - Ajax quand Javascript activé. - - - * UsersInRole.aspx: implémente l'interface utilisateur pour - l'ajout et la suppression d'un utilisateur à un groupe - - * Skills.aspx: initialise le coteur js des compétences site - - * UserSkills.aspx: initialise le coteur js de compétences - utilisateur - - * Web.csproj: un script et des pages d'erreur d'accès, il en - faut une par controlleur - qui restreint quelque de ses accès. - - -2015-11-19 Paul Schneider - - * PayPalController.cs: implements a Paypal controller - - * Abort.aspx: Paypal paiement aborting page - - * Commit.aspx: Paypal paiement commit page - - * IPN.aspx: Paypal paiement notification page - - * Index.aspx: Paypal paiement form page - - * WebTasks.dll: thanks to he Marcelo Zabani's coding blog: - - - - * yavsc.rate.js: refactoring, still needs a cleanning - - * RateSkillControl.ascx: give it the `rate-site-skill` - `data-type` html attribute - - * RateUserSkillControl.ascx: cleans an obsolete code chunk - - * Web.csproj: Fixes the missing RateSkillControl at deploy - time, - adds my deployment config - -2015-11-18 Paul Schneider - - * style.css: this floating breaks my dark style - - * Global.asax: the application object is now compiled at - runtime, - its code is in App_Code - - * YavscHelpers.cs: Implements a method helping to refer on - themed stylesheets, - presenting the "alternate" stylesheet usage. - - * App.master: Uses the new Helper function to refer on the - main style sheet `style.css` - - * Web.config: * no more default controller, instead, modify - the app code - * the client side javascript validation is custommized, and we - do not need the M$ js for now - - - * Web.csproj: Global.asax.cs becomes a content, compiled at - runtime, found in ~/App_Code - - * Global.asax.cs: Now compiles at runtime. - -2015-11-18 Paul Schneider - - * style.css: - * style.css: - * UsersInRole.aspx: refactoring - - * HomeController.cs: Fixes the restricted area error page - - * PostActions.ascx: html structure - - * TagControl.ascx: Tags reside in a list here, treat it as an - Html one - - * RestrictedArea.aspx: Shows allowed users or/and roles in the - error page - - * Web.csproj: cleaning - -2015-11-17 Paul Schneider - - * RateControl.ascx: A rate control for the Front Office - - * UserCard.ascx: WIP UserCard - - * FrontOfficeController.cs: restricts the Skills view to - Admins, - uses the new PerformerProfile object - - * Edit.aspx: - * Title.aspx: - * Profile.aspx: - * Skills.aspx: - * Estimate.aspx: the `aside` html node is better placed at the - top of the content, - overall when it's floating. - - * PostActions.ascx: code formatting - - * UserSkills.aspx: Uses the new `PerformerProfile` object - - - * Web.csproj: adds a skill view, - WIP UserCard - -2015-11-17 Paul Schneider - - * yavsc.skills.js: Implements skills Ajax methods - - * RateControl.ascx: - * RateSkillControl.ascx: - * RateUserSkillControl.ascx: refactorization - - * UserSkills.aspx: Implements a site user's skills view - - * BlogsController.cs: Refactorization, with skill and - userskills ratings - - * GCMController.cs: xml doc - - * SkillController.cs: implements a skill controller - - * Skills.sql: defines the skill data model - - * style.css: mainly adds the `rate` css class - - * style.css: adds rate & skill name style - - * AuthorizeAttribute.cs: - * OAuth2.cs: - * FormatterException.cs: xmldoc - - * FrontOfficeController.cs: implements an user's skills method - - * App.master: code formatting - - * yavsc.rate.js: Makes it a JQuery module - - * EventPub.aspx: no more ImgLocator ... I don't remember why. - - * Skills.aspx: Implements a site wize skills view - - * Web.config: imports the skill model name space - - * Web.config: SkillProvider section and code formatting - -2015-11-14 Paul Schneider - - * SkillController.cs: WIP Skill interface - - * Skills.sql: WIP skills - - * star.gif: - * rateit.css: - * delete.gif: - * AuthorizeAttribute.cs: - * AddRole.aspx: - * jquery.rateit.js: - * jquery.validate.js: - * jquery.rateit.min.js: - * HomeController.cs: - * jquery.validate.min.js: - * BlogsController.cs: - * GoogleHelpers.cs: - * GoogleController.cs: - * jquery.validate-vsdoc.js: - * jquery.rateit.min.js.map: - * FrontOfficeController.cs: - - * Skills.aspx: - * RateControl.ascx: WIP lists skils - - * Contact.template.aspx: a default contact page - - * Contact.totem.aspx: the totem contact page - - * BlogsController.cs: Uniformize the creation/modificaton - action profiles: - * no more `Create` action - * The Post action creates or updates. - - * FrontOfficeController.cs: The FE controller is a Yavsc one. - - * instdbws.sql: - * RateControl.ascx: refactoring - - * yavsc.rate.js: the default treatment in case of error is the - same. - - * Circles.aspx: - * Index.aspx: - * UsersInRole.aspx: MAS disapeared - - * Index.aspx: - * Basket.aspx: - * Command.aspx: - * Estimate.aspx: MAS disparition - - * Contact.aspx: My information - - * Index.aspx: This site could talk about Yavsc - - * RestrictedArea.aspx: A customized restricted area wall, with - a security hole? - - * Web.csproj: fixes the `Deploy` compilation target - - * WebDeploy.targets: My `DirectorySepartionChar` is a slash - ... It's prettier to me. - - * packages.config: We don't need jQuery.RateIt ... it's - perhaps awesome, I not yet know nor for a while. - -2015-11-11 Paul Schneider - - * App.master: - * NoLogin.master: - * AppAdmin.master: master pages sync - -2015-11-11 Paul Schneider - - * style.css: - * style.css: removes the themable code, - it goes to the dark theme. - - * yavsc.rate.js: rates using the web API - - * UserCard.ascx: WIP UserCard - - * RateControl.ascx: - * RateControl.ascx.cs: implements a rate control - - * BlogsController.cs: implements a rating API on Blog spot - - * AccountController.cs: Saves the user's theme at profile - edition - - * AdminController.cs: Enrols users - - * HomeController.cs: there's still no artiste here. - - * App.master: Uses a page theme - - * yavsc.circles.js: cleaning - - * yavsc.js: some enhancement - - * yavsc.tags.js: adds a new line :-) - - * Profile.aspx: offers the theme choice - - * AddUserToRole.ascx: Implements the enrolment - - * Admin.aspx: code formatting - - * UserList.aspx: lists user's roles and link to enrol - - * UsersInRole.aspx: a more relevant title, and a list as html - `UL` node - - * PostActions.ascx: adds on control on rate - - * Index.aspx: Fixes the latest merge - - * Web.csproj: references the rating control - - * ChooseMedia.aspx: useless - - * Web.config: configures the `UITheme` profile property - -2015-11-08 Paul Schneider - - * helix-nebula.l.jpg: - * helix-nebula.s.jpg: - * helix-nebula.xs.jpg: helix nebula in new sizes - - * Web.config: hides my info on Google - - * facebook.png: a facebook icon, in case of - -2015-11-06 Paul Schneider - - * ChangeLog: - * Web.csproj: - * Web.config: - * pgsql.xcf: - * p8-av4.png: - * pgsql.jpeg: - * logo-1.jpg: - * App.master: - * logoDev.png: - * logoDev.xcf: - * datepair.js: - * debian-pb.gif: - * apache_pb.gif: - * apache_pbw.gif: - * apache_pby.gif: - * Index.aspx: - * Index.aspx: - * Title.aspx: - * Book.aspx: - * Auth.aspx: - * AppAdmin.master: - * datepair.min.js: - * Index.aspx: - * Book.aspx: - * TagPanel.ascx: - * CalAuth.aspx: - * instdbws.sql: - * date.js: - * TagPanel.ascx: - * debian-powered.png: - * YavscAjaxHelper.cs: - * logo.jpg: - * UserPosts.aspx: - * jquery.datepair.js: - * FhHRx.gif: - * number.js: - * plural.js: - * pgsql.png: - * totem.jpg: - * TagControl.ascx: - * RemoveRole.aspx: - * twiter.png: - * logo.s.png: - * jquery-1.11.3.min.js: - * UsersInRole.aspx: - * logo-1.png: - * PostActions.ascx: - * message.js: - * logo.xs.png: - * currency.js: - * ChooseADate.aspx: - * facebook.png: - * noavatar.png: - * logo.xxs.png: - * p8-av4.s.jpg: - * jquery.datepair.min.js: - * globalize.js: - * totemprod.png: - * p8-av4.xxs.png: - * apache_pbw.png: - * AddMemberToRole.ascx: - * p8-av4.xxs.jpg: - * ChooseCalendar.aspx: - * YavscController.cs: - * debian-logo.png: - * relative-time.js: - * totem-banner.png: - * Mono-powered.png: - * OtherWebException.aspx: - * concert.clear.jpg: - * helix-nebula-1400x1400.l.jpg: - * totem-banner.xs.jpg: - * star-939235_1280.jpg: - * totem-banner.xxs.jpg: - * star-939235_1280.s.jpg: - * drummer-652345_1280.jpg: - * sign-in-with-google.png: - * star-939235_1280.xs.jpg: - * musician-923526_1280.jpg: - * musician-923526_1.nb.jpg: - * star-939235_1280.xxs.jpg: - * sign-in-with-google-s.png: - * an-pierle-876094_1280.jpg: - * musician-923526_1.nbb.jpg: - * drummer-652345_1280.s.jpg: - * helix-nebula-1400x1400.jpg: - * musician-923526_1280.s.jpg: - * drummer-652345_1280.xxs.jpg: - * musician-923526_1.nb.xs.jpg: - * helix-nebula-1400x1400.s.jpg: - * live-concert-388160_1280.jpg: - * musician-923526_1.nb.xxs.jpg: - * musician-923526_1.nbb.xs.jpg: - * musician-923526_1280.xxs.jpg: - * musician-923526_1.nbb.xxs.jpg: - * globalize.cultures.js: - * helix-nebula-1400x1400.xxs.jpg: - * live-concert-388160_1280.s.jpg: - * globalize.culture.nl.js: - * globalize.culture.ko.js: - * globalize.culture.zh.js: - * globalize.culture.hr.js: - * globalize.culture.th.js: - * globalize.culture.ml.js: - * globalize.culture.mk.js: - * globalize.culture.id.js: - * globalize.culture.pl.js: - * globalize.culture.hy.js: - * globalize.culture.tk.js: - * globalize.culture.hu.js: - * globalize.culture.zu.js: - * globalize.culture.lo.js: - * globalize.culture.no.js: - * globalize.culture.lb.js: - * globalize.culture.tt.js: - * globalize.culture.ha.js: - * globalize.culture.ky.js: - * globalize.culture.sr.js: - * globalize.culture.hi.js: - * globalize.culture.nn.js: - * globalize.culture.ps.js: - * globalize.culture.lt.js: - * globalize.culture.he.js: - * globalize.culture.ig.js: - * globalize.culture.ug.js: - * globalize.culture.ja.js: - * globalize.culture.uz.js: - * globalize.culture.ka.js: - * globalize.culture.kn.js: - * globalize.culture.lv.js: - * globalize.culture.ur.js: - * globalize.culture.kk.js: - * globalize.culture.sq.js: - * globalize.culture.kl.js: - * globalize.culture.uk.js: - * globalize.culture.km.js: - * globalize.culture.oc.js: - * globalize.culture.pa.js: - * globalize.culture.ii.js: - * globalize.culture.yo.js: - * globalize.culture.is.js: - * globalize.culture.mi.js: - * globalize.culture.xh.js: - * globalize.culture.iu.js: - * globalize.culture.vi.js: - * globalize.culture.tn.js: - * globalize.culture.wo.js: - * globalize.culture.or.js: - * globalize.culture.it.js: - * globalize.culture.gu.js: - * globalize.culture.nb.js: - * globalize.culture.dv.js: - * globalize.culture.el.js: - * live-concert-388160_1280.xxs.jpg: - * globalize.culture.sa.js: - * globalize.culture.af.js: - * globalize.culture.ro.js: - * globalize.culture.ru.js: - * globalize.culture.mt.js: - * globalize.culture.rw.js: - * globalize.culture.am.js: - * globalize.culture.sw.js: - * globalize.culture.de.js: - * globalize.culture.bo.js: - * globalize.culture.bn.js: - * globalize.culture.bg.js: - * globalize.culture.be.js: - * globalize.culture.ba.js: - * globalize.culture.az.js: - * globalize.culture.br.js: - * globalize.culture.da.js: - * globalize.culture.cy.js: - * globalize.culture.cs.js: - * globalize.culture.co.js: - * globalize.culture.ca.js: - * globalize.culture.bs.js: - * globalize.culture.ms.js: - * globalize.culture.fr.js: - * globalize.culture.mn.js: - * globalize.culture.ar.js: - * globalize.culture.te.js: - * globalize.culture.pt.js: - * globalize.culture.fo.js: - * globalize.culture.fy.js: - * globalize.culture.as.js: - * globalize.culture.tg.js: - * globalize.culture.gl.js: - * globalize.culture.gd.js: - * globalize.culture.sl.js: - * globalize.culture.ga.js: - * globalize.culture.sk.js: - * globalize.culture.ta.js: - * globalize.culture.et.js: - * globalize.culture.ne.js: - * globalize.culture.es.js: - * globalize.culture.se.js: - * globalize.culture.rm.js: - * globalize.culture.eu.js: - * globalize.culture.tr.js: - * globalize.culture.sv.js: - * globalize.culture.fi.js: - * globalize.culture.mr.js: - * globalize.culture.fa.js: - * globalize.culture.si.js: - * globalize.culture.syr.js: - * globalize.culture.moh.js: - * globalize.culture.sma.js: - * globalize.culture.gsw.js: - * globalize.culture.arn.js: - * globalize.culture.fil.js: - * globalize.culture.qut.js: - * globalize.culture.quz.js: - * globalize.culture.sah.js: - * globalize.culture.dsb.js: - * globalize.culture.hsb.js: - * globalize.culture.sms.js: - * globalize.culture.kok.js: - * globalize.culture.smn.js: - * globalize.culture.prs.js: - * globalize.culture.nso.js: - * globalize.culture.smj.js: - * globalize.culture.tzm.js: - * globalize.culture.se-NO.js: - * globalize.culture.se-SE.js: - * globalize.culture.se-FI.js: - * globalize.culture.sv-SE.js: - * globalize.culture.sv-FI.js: - * globalize.culture.sl-SI.js: - * globalize.culture.sq-AL.js: - * globalize.culture.sk-SK.js: - * globalize.culture.si-LK.js: - * globalize.culture.sw-KE.js: - * globalize.culture.ar-LY.js: - * globalize.culture.ar-MA.js: - * globalize.culture.ar-OM.js: - * globalize.culture.ar-QA.js: - * globalize.culture.ar-SA.js: - * globalize.culture.ar-SY.js: - * globalize.culture.ar-TN.js: - * globalize.culture.ar-YE.js: - * globalize.culture.as-IN.js: - * globalize.culture.ar-LB.js: - * globalize.culture.af-ZA.js: - * globalize.culture.am-ET.js: - * globalize.culture.ar-AE.js: - * globalize.culture.ar-BH.js: - * globalize.culture.ar-DZ.js: - * globalize.culture.ar-EG.js: - * globalize.culture.ar-IQ.js: - * globalize.culture.ar-JO.js: - * globalize.culture.ar-KW.js: - * globalize.culture.pa-IN.js: - * globalize.culture.uk-UA.js: - * globalize.culture.ug-CN.js: - * globalize.culture.tt-RU.js: - * globalize.culture.tr-TR.js: - * globalize.culture.tn-ZA.js: - * globalize.culture.tk-TM.js: - * globalize.culture.th-TH.js: - * globalize.culture.te-IN.js: - * globalize.culture.ta-IN.js: - * globalize.culture.ur-PK.js: - * globalize.culture.zu-ZA.js: - * globalize.culture.zh-TW.js: - * globalize.culture.zh-SG.js: - * globalize.culture.zh-MO.js: - * globalize.culture.zh-HK.js: - * globalize.culture.zh-CN.js: - * globalize.culture.yo-NG.js: - * globalize.culture.xh-ZA.js: - * globalize.culture.wo-SN.js: - * globalize.culture.vi-VN.js: - * globalize.culture.hu-HU.js: - * globalize.culture.es-DO.js: - * globalize.culture.is-IS.js: - * globalize.culture.it-CH.js: - * globalize.culture.it-IT.js: - * globalize.culture.es-CR.js: - * globalize.culture.es-CO.js: - * globalize.culture.es-EC.js: - * globalize.culture.hy-AM.js: - * globalize.culture.id-ID.js: - * globalize.culture.es-GT.js: - * globalize.culture.es-ES.js: - * globalize.culture.ig-NG.js: - * globalize.culture.ii-CN.js: - * globalize.culture.es-CL.js: - * globalize.culture.kl-GL.js: - * globalize.culture.km-KH.js: - * globalize.culture.kn-IN.js: - * globalize.culture.ko-KR.js: - * globalize.culture.en-TT.js: - * globalize.culture.ky-KG.js: - * globalize.culture.kk-KZ.js: - * globalize.culture.es-BO.js: - * globalize.culture.ja-JP.js: - * globalize.culture.ka-GE.js: - * globalize.culture.es-AR.js: - * globalize.culture.en-ZW.js: - * globalize.culture.en-ZA.js: - * globalize.culture.en-US.js: - * globalize.culture.es-HN.js: - * globalize.culture.fr-CA.js: - * globalize.culture.fr-CH.js: - * globalize.culture.fr-FR.js: - * globalize.culture.es-SV.js: - * globalize.culture.fr-LU.js: - * globalize.culture.fr-MC.js: - * globalize.culture.fr-BE.js: - * globalize.culture.es-VE.js: - * globalize.culture.et-EE.js: - * globalize.culture.eu-ES.js: - * globalize.culture.fa-IR.js: - * globalize.culture.fi-FI.js: - * globalize.culture.es-US.js: - * globalize.culture.fo-FO.js: - * globalize.culture.fy-NL.js: - * globalize.culture.es-NI.js: - * globalize.culture.he-IL.js: - * globalize.culture.hi-IN.js: - * globalize.culture.hr-BA.js: - * globalize.culture.hr-HR.js: - * globalize.culture.es-MX.js: - * globalize.culture.es-PA.js: - * globalize.culture.ga-IE.js: - * globalize.culture.gd-GB.js: - * globalize.culture.gl-ES.js: - * globalize.culture.es-PY.js: - * globalize.culture.gu-IN.js: - * globalize.culture.es-PR.js: - * globalize.culture.es-PE.js: - * globalize.culture.en-SG.js: - * globalize.culture.ms-MY.js: - * globalize.culture.cy-GB.js: - * globalize.culture.pl-PL.js: - * globalize.culture.cs-CZ.js: - * globalize.culture.co-FR.js: - * globalize.culture.ca-ES.js: - * globalize.culture.or-IN.js: - * globalize.culture.de-LU.js: - * globalize.culture.de-LI.js: - * globalize.culture.de-DE.js: - * globalize.culture.de-CH.js: - * globalize.culture.de-AT.js: - * globalize.culture.da-DK.js: - * globalize.culture.oc-FR.js: - * globalize.culture.br-FR.js: - * globalize.culture.ba-RU.js: - * globalize.culture.rm-CH.js: - * globalize.culture.ro-RO.js: - * globalize.culture.ru-RU.js: - * globalize.culture.rw-RW.js: - * globalize.culture.sa-IN.js: - * globalize.culture.be-BY.js: - * globalize.culture.ps-AF.js: - * globalize.culture.bo-CN.js: - * globalize.culture.bn-IN.js: - * globalize.culture.pt-BR.js: - * globalize.culture.pt-PT.js: - * globalize.culture.bn-BD.js: - * globalize.culture.bg-BG.js: - * globalize.culture.es-UY.js: - * globalize.culture.en-NZ.js: - * globalize.culture.mn-MN.js: - * globalize.culture.en-MY.js: - * globalize.culture.en-JM.js: - * globalize.culture.en-IN.js: - * globalize.culture.en-IE.js: - * globalize.culture.ml-IN.js: - * globalize.culture.en-PH.js: - * globalize.culture.lb-LU.js: - * globalize.culture.lo-LA.js: - * globalize.culture.lt-LT.js: - * globalize.culture.lv-LV.js: - * globalize.culture.mi-NZ.js: - * globalize.culture.mk-MK.js: - * globalize.culture.en-GB.js: - * globalize.culture.nl-BE.js: - * globalize.culture.nl-NL.js: - * globalize.culture.nn-NO.js: - * globalize.culture.en-AU.js: - * globalize.culture.el-GR.js: - * globalize.culture.dv-MV.js: - * globalize.culture.ne-NP.js: - * globalize.culture.mr-IN.js: - * globalize.culture.ms-BN.js: - * globalize.culture.en-CA.js: - * globalize.culture.mt-MT.js: - * globalize.culture.en-BZ.js: - * globalize.culture.nb-NO.js: - * globalize.culture.en-029.js: - * globalize.culture.dsb-DE.js: - * globalize.culture.zh-CHS.js: - * globalize.culture.smj-NO.js: - * globalize.culture.smj-SE.js: - * globalize.culture.prs-AF.js: - * globalize.culture.smn-FI.js: - * globalize.culture.sms-FI.js: - * globalize.culture.kok-IN.js: - * globalize.culture.nso-ZA.js: - * globalize.culture.syr-SY.js: - * globalize.culture.moh-CA.js: - * globalize.culture.zh-CHT.js: - * globalize.culture.quz-BO.js: - * globalize.culture.quz-EC.js: - * globalize.culture.quz-PE.js: - * globalize.culture.gsw-FR.js: - * globalize.culture.arn-CL.js: - * globalize.culture.fil-PH.js: - * globalize.culture.qut-GT.js: - * globalize.culture.hsb-DE.js: - * globalize.culture.sma-SE.js: - * globalize.culture.sma-NO.js: - * globalize.culture.sah-RU.js: - * globalize.culture.az-Latn.js: - * globalize.culture.sr-Latn.js: - * globalize.culture.bs-Cyrl.js: - * globalize.culture.sr-Cyrl.js: - * globalize.culture.bs-Latn.js: - * globalize.culture.tg-Cyrl.js: - * globalize.culture.uz-Cyrl.js: - * globalize.culture.iu-Latn.js: - * globalize.culture.iu-Cans.js: - * globalize.culture.zh-Hans.js: - * globalize.culture.zh-Hant.js: - * globalize.culture.az-Cyrl.js: - * globalize.culture.mn-Mong.js: - * globalize.culture.uz-Latn.js: - * globalize.culture.mn-Cyrl.js: - * globalize.culture.ha-Latn.js: - * globalize.culture.tzm-Latn.js: - * globalize.culture.az-Cyrl-AZ.js: - * globalize.culture.iu-Latn-CA.js: - * globalize.culture.bs-Latn-BA.js: - * globalize.culture.ha-Latn-NG.js: - * globalize.culture.iu-Cans-CA.js: - * globalize.culture.bs-Cyrl-BA.js: - * globalize.culture.mn-Mong-CN.js: - * globalize.culture.az-Latn-AZ.js: - * globalize.culture.sr-Latn-RS.js: - * globalize.culture.sr-Latn-ME.js: - * globalize.culture.sr-Latn-CS.js: - * globalize.culture.sr-Latn-BA.js: - * globalize.culture.uz-Latn-UZ.js: - * globalize.culture.sr-Cyrl-BA.js: - * globalize.culture.sr-Cyrl-CS.js: - * globalize.culture.sr-Cyrl-ME.js: - * globalize.culture.sr-Cyrl-RS.js: - * globalize.culture.uz-Cyrl-UZ.js: - * globalize.culture.tg-Cyrl-TJ.js: - * globalize.culture.tzm-Latn-DZ.js: - - * style.css: nothing to see - - * BlogsController.cs: Removes the `ValidateEdit` method, - and gives Admins the Blogger role ... a commit to blame in a - near future - - * yavsc.js: comes from yavsc - - * Edit.aspx: refactoring `ValidateEdit` - diff --git a/web/Controllers/BlogsController.cs b/web/Controllers/BlogsController.cs index 816e02f4..bbfcc0ff 100644 --- a/web/Controllers/BlogsController.cs +++ b/web/Controllers/BlogsController.cs @@ -373,7 +373,7 @@ namespace Yavsc.Controllers if (Membership.GetUser ().UserName != user) if (!Roles.IsUserInRole("Admin")) - throw new AuthorizationDenied (user); + throw new AuthorizationDenied (); if (!confirm) return View ("RemoveTitle"); BlogManager.RemoveTitle (user, title); diff --git a/web/Formatters/ErrorHtmlFormatter.cs b/web/Formatters/ErrorHtmlFormatter.cs index 13d9bcb2..50120926 100644 --- a/web/Formatters/ErrorHtmlFormatter.cs +++ b/web/Formatters/ErrorHtmlFormatter.cs @@ -71,7 +71,7 @@ namespace Yavsc.Formatters /// Value. /// Stream. /// Content headers. - public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders) + public override void WriteToStream (Type type, object value, Stream stream, HttpContent contentHeaders) { // TODO create a type containing T4 parameters, and generate from them using (var writer = new StreamWriter(stream)) diff --git a/web/Formatters/EstimToPdfFormatter.cs b/web/Formatters/EstimToPdfFormatter.cs index 72637b7d..a78ce361 100644 --- a/web/Formatters/EstimToPdfFormatter.cs +++ b/web/Formatters/EstimToPdfFormatter.cs @@ -70,7 +70,6 @@ namespace Yavsc.Formatters return enumerableType.IsAssignableFrom(type); } } - ///

/// Writes synchronously to the buffered stream. /// @@ -78,7 +77,7 @@ namespace Yavsc.Formatters /// Value. /// Stream. /// Content headers. - public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders) + public override void WriteToStream (Type type, object value, Stream stream, HttpContent contentHeaders) { // TODO create a type containing generation parameters, including a template path, and generate from them diff --git a/web/Formatters/RssFeedsFormatter.cs b/web/Formatters/RssFeedsFormatter.cs index 04f63e3f..57680bbd 100644 --- a/web/Formatters/RssFeedsFormatter.cs +++ b/web/Formatters/RssFeedsFormatter.cs @@ -54,7 +54,7 @@ namespace Yavsc.Formatters /// Value. /// Stream. /// Content headers. - public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders) + public override void WriteToStream (Type type, object value, Stream stream, HttpContent contentHeaders) { RssFeedsChannel feeds = value as RssFeedsChannel; using (var writer = new StreamWriter (stream)) { diff --git a/web/Formatters/SimpleFormatter.cs b/web/Formatters/SimpleFormatter.cs index 132c60c2..55e181ee 100644 --- a/web/Formatters/SimpleFormatter.cs +++ b/web/Formatters/SimpleFormatter.cs @@ -75,7 +75,7 @@ namespace Yavsc.Formatters /// Value. /// Stream. /// Content headers. - public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders) + public override void WriteToStream (Type type, object value, Stream stream, HttpContent contentHeaders) { // TODO create a type containing T4 parameters, and generate from them using (var writer = new StreamWriter(stream)) diff --git a/web/Formatters/TexToPdfFormatter.cs b/web/Formatters/TexToPdfFormatter.cs index fe5c6ad4..b96d1379 100644 --- a/web/Formatters/TexToPdfFormatter.cs +++ b/web/Formatters/TexToPdfFormatter.cs @@ -75,7 +75,7 @@ namespace Yavsc.Formatters /// Value. /// Stream. /// Content headers. - public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders) + public override void WriteToStream (Type type, object value, Stream stream, HttpContent contentHeaders) { string temp = Path.GetTempPath (); string cntStr = value as string; @@ -126,8 +126,8 @@ namespace Yavsc.Formatters ///
/// Content headers. /// Basename. - public static void SetFileName(HttpContentHeaders contentHeaders, string basename) { - contentHeaders.ContentDisposition = new ContentDispositionHeaderValue ("attachment") { + public static void SetFileName(HttpContent contentHeaders, string basename) { + contentHeaders.Headers.ContentDisposition = new ContentDispositionHeaderValue ("attachment") { FileName = "doc-" + basename + ".pdf" }; } diff --git a/web/Helpers/YavscHelpers.cs b/web/Helpers/YavscHelpers.cs index d62609c2..5e33c1b4 100644 --- a/web/Helpers/YavscHelpers.cs +++ b/web/Helpers/YavscHelpers.cs @@ -12,7 +12,6 @@ using Yavsc.Model.Circles; using System.Web.UI; using System.Linq.Expressions; using System.Web.Profile; -using System.Web.Script.Serialization; using System.Web.Mvc; using System.Text.RegularExpressions; using Yavsc.Model.Messaging; @@ -21,6 +20,7 @@ using System.Reflection; using System.Web.Routing; using Yavsc.Model.FrontOffice; using Yavsc.Model.WorkFlow; +using System.Web.Script.Serialization; namespace Yavsc.Helpers { @@ -571,15 +571,8 @@ namespace Yavsc.Helpers writer.Write (text); writer.RenderEndTag (); return new MvcHtmlString(strwr.ToString()); - } - - - - - - } } diff --git a/web/Models/Identity/AccountBindingModels.cs b/web/Models/Identity/AccountBindingModels.cs new file mode 100644 index 00000000..9e4e1484 --- /dev/null +++ b/web/Models/Identity/AccountBindingModels.cs @@ -0,0 +1,84 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Newtonsoft.Json; + +namespace Yavsc.Models.Identity +{ + // Models used as parameters to AccountController actions. + + public class AddExternalLoginBindingModel + { + [Required] + [Display(Name = "External access token")] + public string ExternalAccessToken { get; set; } + } + + public class ChangePasswordBindingModel + { + [Required] + [DataType(DataType.Password)] + [Display(Name = "Current password")] + public string OldPassword { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } + + public class RegisterBindingModel + { + [Required] + [Display(Name = "Email")] + public string Email { get; set; } + + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "Password")] + public string Password { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm password")] + [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } + + public class RegisterExternalBindingModel + { + [Required] + [Display(Name = "Email")] + public string Email { get; set; } + } + + public class RemoveLoginBindingModel + { + [Required] + [Display(Name = "Login provider")] + public string LoginProvider { get; set; } + + [Required] + [Display(Name = "Provider key")] + public string ProviderKey { get; set; } + } + + public class SetPasswordBindingModel + { + [Required] + [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] + [DataType(DataType.Password)] + [Display(Name = "New password")] + public string NewPassword { get; set; } + + [DataType(DataType.Password)] + [Display(Name = "Confirm new password")] + [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] + public string ConfirmPassword { get; set; } + } +} diff --git a/web/Models/Identity/AccountViewModels.cs b/web/Models/Identity/AccountViewModels.cs new file mode 100644 index 00000000..82f3f14f --- /dev/null +++ b/web/Models/Identity/AccountViewModels.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; + +namespace Yavsc.Models.Identity +{ + // Models returned by AccountController actions. + + public class ExternalLoginViewModel + { + public string Name { get; set; } + + public string Url { get; set; } + + public string State { get; set; } + } + + public class ManageInfoViewModel + { + public string LocalLoginProvider { get; set; } + + public string Email { get; set; } + + public IEnumerable Logins { get; set; } + + public IEnumerable ExternalLoginProviders { get; set; } + } + + public class UserInfoViewModel + { + public string Email { get; set; } + + public bool HasRegistered { get; set; } + + public string LoginProvider { get; set; } + } + + public class UserLoginInfoViewModel + { + public string LoginProvider { get; set; } + + public string ProviderKey { get; set; } + } +} diff --git a/web/Models/Identity/IdentityModels.cs b/web/Models/Identity/IdentityModels.cs new file mode 100644 index 00000000..1bc1e898 --- /dev/null +++ b/web/Models/Identity/IdentityModels.cs @@ -0,0 +1,33 @@ +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.EntityFramework; +using Microsoft.AspNet.Identity.Owin; + +namespace Yavsc.Models.Identity +{ + // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. + public class ApplicationUser : IdentityUser + { + public async Task GenerateUserIdentityAsync(UserManager manager, string authenticationType) + { + // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType + var userIdentity = await manager.CreateIdentityAsync(this, authenticationType); + // Add custom user claims here + return userIdentity; + } + } + + public class ApplicationDbContext : IdentityDbContext + { + public ApplicationDbContext() + : base("DefaultConnection", throwIfV1Schema: false) + { + } + + public static ApplicationDbContext Create() + { + return new ApplicationDbContext(); + } + } +} \ No newline at end of file diff --git a/web/Providers/ApplicationOAuthProvider.cs b/web/Providers/ApplicationOAuthProvider.cs new file mode 100644 index 00000000..88f09377 --- /dev/null +++ b/web/Providers/ApplicationOAuthProvider.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNet.Identity; +using Microsoft.AspNet.Identity.EntityFramework; +using Microsoft.AspNet.Identity.Owin; +using Microsoft.Owin.Security; +using Microsoft.Owin.Security.Cookies; +using Microsoft.Owin.Security.OAuth; +using Yavsc.App_Start; +using Yavsc.Models.Identity; + +namespace Yavsc.Providers +{ + public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider + { + private readonly string _publicClientId; + + public ApplicationOAuthProvider(string publicClientId) + { + if (publicClientId == null) + { + throw new ArgumentNullException("publicClientId"); + } + + _publicClientId = publicClientId; + } + + public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) + { + var userManager = context.OwinContext.GetUserManager(); + + ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password); + + if (user == null) + { + context.SetError("invalid_grant", "The user name or password is incorrect."); + return; + } + + ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, + OAuthDefaults.AuthenticationType); + ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager, + CookieAuthenticationDefaults.AuthenticationType); + + AuthenticationProperties properties = CreateProperties(user.UserName); + AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); + context.Validated(ticket); + context.Request.Context.Authentication.SignIn(cookiesIdentity); + } + + public override Task TokenEndpoint(OAuthTokenEndpointContext context) + { + foreach (KeyValuePair property in context.Properties.Dictionary) + { + context.AdditionalResponseParameters.Add(property.Key, property.Value); + } + + return Task.FromResult(null); + } + + public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) + { + // Resource owner password credentials does not provide a client ID. + if (context.ClientId == null) + { + context.Validated(); + } + + return Task.FromResult(null); + } + + public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context) + { + if (context.ClientId == _publicClientId) + { + Uri expectedRootUri = new Uri(context.Request.Uri, "/"); + + if (expectedRootUri.AbsoluteUri == context.RedirectUri) + { + context.Validated(); + } + } + + return Task.FromResult(null); + } + + public static AuthenticationProperties CreateProperties(string userName) + { + IDictionary data = new Dictionary + { + { "userName", userName } + }; + return new AuthenticationProperties(data); + } + } +} \ No newline at end of file diff --git a/web/Scripts/globalize/currency.js b/web/Scripts/globalize/currency.js deleted file mode 100644 index 5c8f1fe1..00000000 --- a/web/Scripts/globalize/currency.js +++ /dev/null @@ -1,413 +0,0 @@ -/*! - * Globalize v1.0.0 - * - * http://github.com/jquery/globalize - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2015-04-23T12:02Z - */ -(function( root, factory ) { - - // UMD returnExports - if ( typeof define === "function" && define.amd ) { - - // AMD - define([ - "cldr", - "../globalize", - "./number", - "cldr/event", - "cldr/supplemental" - ], factory ); - } else if ( typeof exports === "object" ) { - - // Node, CommonJS - module.exports = factory( require( "cldrjs" ), require( "globalize" ) ); - } else { - - // Global - factory( root.Cldr, root.Globalize ); - } -}(this, function( Cldr, Globalize ) { - -var alwaysArray = Globalize._alwaysArray, - formatMessage = Globalize._formatMessage, - numberNumberingSystem = Globalize._numberNumberingSystem, - numberPattern = Globalize._numberPattern, - stringPad = Globalize._stringPad, - validate = Globalize._validate, - validateCldr = Globalize._validateCldr, - validateDefaultLocale = Globalize._validateDefaultLocale, - validateParameterPresence = Globalize._validateParameterPresence, - validateParameterType = Globalize._validateParameterType, - validateParameterTypeNumber = Globalize._validateParameterTypeNumber, - validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject; - - -var validateParameterTypeCurrency = function( value, name ) { - validateParameterType( - value, - name, - value === undefined || typeof value === "string" && ( /^[A-Za-z]{3}$/ ).test( value ), - "3-letter currency code string as defined by ISO 4217" - ); -}; - - - - -var validatePluralModulePresence = function() { - validate( "E_MISSING_PLURAL_MODULE", "Plural module not loaded.", - Globalize.plural !== undefined, {} ); -}; - - - - -/** - * supplementalOverride( currency, pattern, cldr ) - * - * Return pattern with fraction digits overriden by supplemental currency data. - */ -var currencySupplementalOverride = function( currency, pattern, cldr ) { - var digits, - fraction = cldr.supplemental([ "currencyData/fractions", currency ]) || - cldr.supplemental( "currencyData/fractions/DEFAULT" ); - - digits = +fraction._digits; - - if ( digits ) { - fraction = "." + stringPad( "0", digits ).slice( 0, -1 ) + fraction._rounding; - } else { - fraction = ""; - } - - return pattern.replace( /\.(#+|0*[0-9]|0+[0-9]?)/g, fraction ); -}; - - - - -var objectFilter = function( object, testRe ) { - var key, - copy = {}; - - for ( key in object ) { - if ( testRe.test( key ) ) { - copy[ key ] = object[ key ]; - } - } - - return copy; -}; - - - - -var currencyUnitPatterns = function( cldr ) { - return objectFilter( cldr.main([ - "numbers", - "currencyFormats-numberSystem-" + numberNumberingSystem( cldr ) - ]), /^unitPattern/ ); -}; - - - - -/** - * codeProperties( currency, cldr ) - * - * Return number pattern with the appropriate currency code in as literal. - */ -var currencyCodeProperties = function( currency, cldr ) { - var pattern = numberPattern( "decimal", cldr ); - - // The number of decimal places and the rounding for each currency is not locale-specific. Those - // values overridden by Supplemental Currency Data. - pattern = currencySupplementalOverride( currency, pattern, cldr ); - - return { - currency: currency, - pattern: pattern, - unitPatterns: currencyUnitPatterns( cldr ) - }; -}; - - - - -/** - * nameFormat( formattedNumber, pluralForm, properties ) - * - * Return the appropriate name form currency format. - */ -var currencyNameFormat = function( formattedNumber, pluralForm, properties ) { - var displayName, unitPattern, - displayNames = properties.displayNames || {}, - unitPatterns = properties.unitPatterns; - - displayName = displayNames[ "displayName-count-" + pluralForm ] || - displayNames[ "displayName-count-other" ] || - displayNames.displayName || - properties.currency; - unitPattern = unitPatterns[ "unitPattern-count-" + pluralForm ] || - unitPatterns[ "unitPattern-count-other" ]; - - return formatMessage( unitPattern, [ formattedNumber, displayName ]); -}; - - - - -/** - * nameProperties( currency, cldr ) - * - * Return number pattern with the appropriate currency code in as literal. - */ -var currencyNameProperties = function( currency, cldr ) { - var properties = currencyCodeProperties( currency, cldr ); - - properties.displayNames = objectFilter( cldr.main([ - "numbers/currencies", - currency - ]), /^displayName/ ); - - return properties; -}; - - - - -/** - * Unicode regular expression for: everything except math symbols, currency signs, dingbats, and - * box-drawing characters. - * - * Generated by: - * - * regenerate() - * .addRange( 0x0, 0x10FFFF ) - * .remove( require( "unicode-7.0.0/categories/S/symbols" ) ).toString(); - * - * https://github.com/mathiasbynens/regenerate - * https://github.com/mathiasbynens/unicode-7.0.0 - */ -var regexpNotS = /[\0-#%-\*,-;\?-\]_a-\{\}\x7F-\xA1\xA7\xAA\xAB\xAD\xB2\xB3\xB5-\xB7\xB9-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376-\u0383\u0386-\u03F5\u03F7-\u0481\u0483-\u058C\u0590-\u0605\u0609\u060A\u060C\u060D\u0610-\u06DD\u06DF-\u06E8\u06EA-\u06FC\u06FF-\u07F5\u07F7-\u09F1\u09F4-\u09F9\u09FC-\u0AF0\u0AF2-\u0B6F\u0B71-\u0BF2\u0BFB-\u0C7E\u0C80-\u0D78\u0D7A-\u0E3E\u0E40-\u0F00\u0F04-\u0F12\u0F14\u0F18\u0F19\u0F20-\u0F33\u0F35\u0F37\u0F39-\u0FBD\u0FC6\u0FCD\u0FD0-\u0FD4\u0FD9-\u109D\u10A0-\u138F\u139A-\u17DA\u17DC-\u193F\u1941-\u19DD\u1A00-\u1B60\u1B6B-\u1B73\u1B7D-\u1FBC\u1FBE\u1FC2-\u1FCC\u1FD0-\u1FDC\u1FE0-\u1FEC\u1FF0-\u1FFC\u1FFF-\u2043\u2045-\u2051\u2053-\u2079\u207D-\u2089\u208D-\u209F\u20BE-\u20FF\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u218F\u2308-\u230B\u2329\u232A\u23FB-\u23FF\u2427-\u243F\u244B-\u249B\u24EA-\u24FF\u2768-\u2793\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2B74\u2B75\u2B96\u2B97\u2BBA-\u2BBC\u2BC9\u2BD2-\u2CE4\u2CEB-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u3003\u3005-\u3011\u3014-\u301F\u3021-\u3035\u3038-\u303D\u3040-\u309A\u309D-\u318F\u3192-\u3195\u31A0-\u31BF\u31E4-\u31FF\u321F-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u32FF\u3400-\u4DBF\u4E00-\uA48F\uA4C7-\uA6FF\uA717-\uA71F\uA722-\uA788\uA78B-\uA827\uA82C-\uA835\uA83A-\uAA76\uAA7A-\uAB5A\uAB5C-\uD7FF\uDC00-\uFB28\uFB2A-\uFBB1\uFBC2-\uFDFB\uFDFE-\uFE61\uFE63\uFE67\uFE68\uFE6A-\uFF03\uFF05-\uFF0A\uFF0C-\uFF1B\uFF1F-\uFF3D\uFF3F\uFF41-\uFF5B\uFF5D\uFF5F-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF]|\uD800[\uDC00-\uDD36\uDD40-\uDD78\uDD8A\uDD8B\uDD8D-\uDD8F\uDD9C-\uDD9F\uDDA1-\uDDCF\uDDFD-\uDFFF]|[\uD801\uD803-\uD819\uD81B-\uD82E\uD830-\uD833\uD836-\uD83A\uD83F-\uDBFF][\uDC00-\uDFFF]|\uD802[\uDC00-\uDC76\uDC79-\uDEC7\uDEC9-\uDFFF]|\uD81A[\uDC00-\uDF3B\uDF40-\uDF44\uDF46-\uDFFF]|\uD82F[\uDC00-\uDC9B\uDC9D-\uDFFF]|\uD834[\uDCF6-\uDCFF\uDD27\uDD28\uDD65-\uDD69\uDD6D-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDDDE-\uDDFF\uDE42-\uDE44\uDE46-\uDEFF\uDF57-\uDFFF]|\uD835[\uDC00-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFFF]|\uD83B[\uDC00-\uDEEF\uDEF2-\uDFFF]|\uD83C[\uDC2C-\uDC2F\uDC94-\uDC9F\uDCAF\uDCB0\uDCC0\uDCD0\uDCF6-\uDD0F\uDD2F\uDD6C-\uDD6F\uDD9B-\uDDE5\uDE03-\uDE0F\uDE3B-\uDE3F\uDE49-\uDE4F\uDE52-\uDEFF\uDF2D-\uDF2F\uDF7E\uDF7F\uDFCF-\uDFD3\uDFF8-\uDFFF]|\uD83D[\uDCFF\uDD4B-\uDD4F\uDD7A\uDDA4\uDE43\uDE44\uDED0-\uDEDF\uDEED-\uDEEF\uDEF4-\uDEFF\uDF74-\uDF7F\uDFD5-\uDFFF]|\uD83E[\uDC0C-\uDC0F\uDC48-\uDC4F\uDC5A-\uDC5F\uDC88-\uDC8F\uDCAE-\uDFFF]|[\uD800-\uDBFF]/; - - - - -/** - * symbolProperties( currency, cldr ) - * - * Return pattern replacing `¤` with the appropriate currency symbol literal. - */ -var currencySymbolProperties = function( currency, cldr, options ) { - var currencySpacing, pattern, - regexp = { - "[:digit:]": /\d/, - "[:^S:]": regexpNotS - }, - symbol = cldr.main([ - "numbers/currencies", - currency, - "symbol" - ]); - - currencySpacing = [ "beforeCurrency", "afterCurrency" ].map(function( position ) { - return cldr.main([ - "numbers", - "currencyFormats-numberSystem-" + numberNumberingSystem( cldr ), - "currencySpacing", - position - ]); - }); - - pattern = cldr.main([ - "numbers", - "currencyFormats-numberSystem-" + numberNumberingSystem( cldr ), - options.style === "accounting" ? "accounting" : "standard" - ]); - - pattern = - - // The number of decimal places and the rounding for each currency is not locale-specific. - // Those values are overridden by Supplemental Currency Data. - currencySupplementalOverride( currency, pattern, cldr ) - - // Replace "¤" (\u00A4) with the appropriate symbol literal. - .split( ";" ).map(function( pattern ) { - - return pattern.split( "\u00A4" ).map(function( part, i ) { - var currencyMatch = regexp[ currencySpacing[ i ].currencyMatch ], - surroundingMatch = regexp[ currencySpacing[ i ].surroundingMatch ], - insertBetween = ""; - - // For currencyMatch and surroundingMatch definitions, read [1]. - // When i === 0, beforeCurrency is being handled. Otherwise, afterCurrency. - // 1: http://www.unicode.org/reports/tr35/tr35-numbers.html#Currencies - currencyMatch = currencyMatch.test( symbol.charAt( i ? symbol.length - 1 : 0 ) ); - surroundingMatch = surroundingMatch.test( - part.charAt( i ? 0 : part.length - 1 ).replace( /[#@,.]/g, "0" ) - ); - - if ( currencyMatch && part && surroundingMatch ) { - insertBetween = currencySpacing[ i ].insertBetween; - } - - return ( i ? insertBetween : "" ) + part + ( i ? "" : insertBetween ); - }).join( "'" + symbol + "'" ); - }).join( ";" ); - - return { - pattern: pattern - }; -}; - - - - -/** - * objectOmit( object, keys ) - * - * Return a copy of the object, filtered to omit the blacklisted key or array of keys. - */ -var objectOmit = function( object, keys ) { - var key, - copy = {}; - - keys = alwaysArray( keys ); - - for ( key in object ) { - if ( keys.indexOf( key ) === -1 ) { - copy[ key ] = object[ key ]; - } - } - - return copy; -}; - - - - -function validateRequiredCldr( path, value ) { - validateCldr( path, value, { - skip: [ /supplemental\/currencyData\/fractions\/[A-Za-z]{3}$/ ] - }); -} - -/** - * .currencyFormatter( currency [, options] ) - * - * @currency [String] 3-letter currency code as defined by ISO 4217. - * - * @options [Object]: - * - style: [String] "symbol" (default), "accounting", "code" or "name". - * - see also number/format options. - * - * Return a function that formats a currency according to the given options and default/instance - * locale. - */ -Globalize.currencyFormatter = -Globalize.prototype.currencyFormatter = function( currency, options ) { - var cldr, numberFormatter, plural, properties, style; - - validateParameterPresence( currency, "currency" ); - validateParameterTypeCurrency( currency, "currency" ); - - validateParameterTypePlainObject( options, "options" ); - - options = options || {}; - style = options.style || "symbol"; - cldr = this.cldr; - - validateDefaultLocale( cldr ); - - // Get properties given style ("symbol" default, "code" or "name"). - cldr.on( "get", validateRequiredCldr ); - properties = ({ - accounting: currencySymbolProperties, - code: currencyCodeProperties, - name: currencyNameProperties, - symbol: currencySymbolProperties - }[ style ] )( currency, cldr, options ); - cldr.off( "get", validateRequiredCldr ); - - // options = options minus style, plus raw pattern. - options = objectOmit( options, "style" ); - options.raw = properties.pattern; - - // Return formatter when style is "symbol" or "accounting". - if ( style === "symbol" || style === "accounting" ) { - return this.numberFormatter( options ); - } - - // Return formatter when style is "code" or "name". - validatePluralModulePresence(); - numberFormatter = this.numberFormatter( options ); - plural = this.pluralGenerator(); - return function( value ) { - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - return currencyNameFormat( numberFormatter( value ), plural( value ), properties ); - }; -}; - -/** - * .currencyParser( currency [, options] ) - * - * @currency [String] 3-letter currency code as defined by ISO 4217. - * - * @options [Object] see currencyFormatter. - * - * Return the currency parser according to the given options and the default/instance locale. - */ -Globalize.currencyParser = -Globalize.prototype.currencyParser = function( /* currency, options */ ) { - - // TODO implement parser. - -}; - -/** - * .formatCurrency( value, currency [, options] ) - * - * @value [Number] number to be formatted. - * - * @currency [String] 3-letter currency code as defined by ISO 4217. - * - * @options [Object] see currencyFormatter. - * - * Format a currency according to the given options and the default/instance locale. - */ -Globalize.formatCurrency = -Globalize.prototype.formatCurrency = function( value, currency, options ) { - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - - return this.currencyFormatter( currency, options )( value ); -}; - -/** - * .parseCurrency( value, currency [, options] ) - * - * @value [String] - * - * @currency [String] 3-letter currency code as defined by ISO 4217. - * - * @options [Object]: See currencyFormatter. - * - * Return the parsed currency or NaN when value is invalid. - */ -Globalize.parseCurrency = -Globalize.prototype.parseCurrency = function( /* value, currency, options */ ) { -}; - -return Globalize; - - - - -})); diff --git a/web/Scripts/globalize/date.js b/web/Scripts/globalize/date.js deleted file mode 100644 index 9f26a105..00000000 --- a/web/Scripts/globalize/date.js +++ /dev/null @@ -1,1845 +0,0 @@ -/** - * Globalize v1.0.0 - * - * http://github.com/jquery/globalize - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2015-04-23T12:02Z - */ -/*! - * Globalize v1.0.0 2015-04-23T12:02Z Released under the MIT license - * http://git.io/TrdQbw - */ -(function( root, factory ) { - - // UMD returnExports - if ( typeof define === "function" && define.amd ) { - - // AMD - define([ - "cldr", - "../globalize", - "./number", - "cldr/event", - "cldr/supplemental" - ], factory ); - } else if ( typeof exports === "object" ) { - - // Node, CommonJS - module.exports = factory( require( "cldrjs" ), require( "globalize" ) ); - } else { - - // Extend global - factory( root.Cldr, root.Globalize ); - } -}(this, function( Cldr, Globalize ) { - -var createError = Globalize._createError, - createErrorUnsupportedFeature = Globalize._createErrorUnsupportedFeature, - formatMessage = Globalize._formatMessage, - numberSymbol = Globalize._numberSymbol, - regexpEscape = Globalize._regexpEscape, - stringPad = Globalize._stringPad, - validateCldr = Globalize._validateCldr, - validateDefaultLocale = Globalize._validateDefaultLocale, - validateParameterPresence = Globalize._validateParameterPresence, - validateParameterType = Globalize._validateParameterType, - validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject, - validateParameterTypeString = Globalize._validateParameterTypeString; - - -var validateParameterTypeDate = function( value, name ) { - validateParameterType( value, name, value === undefined || value instanceof Date, "Date" ); -}; - - - - -var createErrorInvalidParameterValue = function( name, value ) { - return createError( "E_INVALID_PAR_VALUE", "Invalid `{name}` value ({value}).", { - name: name, - value: value - }); -}; - - - - -/** - * expandPattern( options, cldr ) - * - * @options [Object] if String, it's considered a skeleton. Object accepts: - * - skeleton: [String] lookup availableFormat; - * - date: [String] ( "full" | "long" | "medium" | "short" ); - * - time: [String] ( "full" | "long" | "medium" | "short" ); - * - datetime: [String] ( "full" | "long" | "medium" | "short" ); - * - raw: [String] For more info see datetime/format.js. - * - * @cldr [Cldr instance]. - * - * Return the corresponding pattern. - * Eg for "en": - * - "GyMMMd" returns "MMM d, y G"; - * - { skeleton: "GyMMMd" } returns "MMM d, y G"; - * - { date: "full" } returns "EEEE, MMMM d, y"; - * - { time: "full" } returns "h:mm:ss a zzzz"; - * - { datetime: "full" } returns "EEEE, MMMM d, y 'at' h:mm:ss a zzzz"; - * - { raw: "dd/mm" } returns "dd/mm"; - */ - -var dateExpandPattern = function( options, cldr ) { - var dateSkeleton, result, skeleton, timeSkeleton, type; - - function combineDateTime( type, datePattern, timePattern ) { - return formatMessage( - cldr.main([ - "dates/calendars/gregorian/dateTimeFormats", - type - ]), - [ timePattern, datePattern ] - ); - } - - switch ( true ) { - case "skeleton" in options: - skeleton = options.skeleton; - result = cldr.main([ - "dates/calendars/gregorian/dateTimeFormats/availableFormats", - skeleton - ]); - if ( !result ) { - timeSkeleton = skeleton.split( /[^hHKkmsSAzZOvVXx]/ ).slice( -1 )[ 0 ]; - dateSkeleton = skeleton.split( /[^GyYuUrQqMLlwWdDFgEec]/ )[ 0 ]; - if ( /(MMMM|LLLL).*[Ec]/.test( dateSkeleton ) ) { - type = "full"; - } else if ( /MMMM/g.test( dateSkeleton ) ) { - type = "long"; - } else if ( /MMM/g.test( dateSkeleton ) || /LLL/g.test( dateSkeleton ) ) { - type = "medium"; - } else { - type = "short"; - } - result = combineDateTime( type, - cldr.main([ - "dates/calendars/gregorian/dateTimeFormats/availableFormats", - dateSkeleton - ]), - cldr.main([ - "dates/calendars/gregorian/dateTimeFormats/availableFormats", - timeSkeleton - ]) - ); - } - break; - - case "date" in options: - case "time" in options: - result = cldr.main([ - "dates/calendars/gregorian", - "date" in options ? "dateFormats" : "timeFormats", - ( options.date || options.time ) - ]); - break; - - case "datetime" in options: - result = combineDateTime( options.datetime, - cldr.main([ "dates/calendars/gregorian/dateFormats", options.datetime ]), - cldr.main([ "dates/calendars/gregorian/timeFormats", options.datetime ]) - ); - break; - - case "raw" in options: - result = options.raw; - break; - - default: - throw createErrorInvalidParameterValue({ - name: "options", - value: options - }); - } - - return result; -}; - - - - -/** - * dayOfWeek( date, firstDay ) - * - * @date - * - * @firstDay the result of `dateFirstDayOfWeek( cldr )` - * - * Return the day of the week normalized by the territory's firstDay [0-6]. - * Eg for "mon": - * - return 0 if territory is GB, or BR, or DE, or FR (week starts on "mon"); - * - return 1 if territory is US (week starts on "sun"); - * - return 2 if territory is EG (week starts on "sat"); - */ -var dateDayOfWeek = function( date, firstDay ) { - return ( date.getDay() - firstDay + 7 ) % 7; -}; - - - - -/** - * distanceInDays( from, to ) - * - * Return the distance in days between from and to Dates. - */ -var dateDistanceInDays = function( from, to ) { - var inDays = 864e5; - return ( to.getTime() - from.getTime() ) / inDays; -}; - - - - -/** - * startOf changes the input to the beginning of the given unit. - * - * For example, starting at the start of a day, resets hours, minutes - * seconds and milliseconds to 0. Starting at the month does the same, but - * also sets the date to 1. - * - * Returns the modified date - */ -var dateStartOf = function( date, unit ) { - date = new Date( date.getTime() ); - switch ( unit ) { - case "year": - date.setMonth( 0 ); - /* falls through */ - case "month": - date.setDate( 1 ); - /* falls through */ - case "day": - date.setHours( 0 ); - /* falls through */ - case "hour": - date.setMinutes( 0 ); - /* falls through */ - case "minute": - date.setSeconds( 0 ); - /* falls through */ - case "second": - date.setMilliseconds( 0 ); - } - return date; -}; - - - - -/** - * dayOfYear - * - * Return the distance in days of the date to the begin of the year [0-d]. - */ -var dateDayOfYear = function( date ) { - return Math.floor( dateDistanceInDays( dateStartOf( date, "year" ), date ) ); -}; - - - - -var dateWeekDays = [ "sun", "mon", "tue", "wed", "thu", "fri", "sat" ]; - - - - -/** - * firstDayOfWeek - */ -var dateFirstDayOfWeek = function( cldr ) { - return dateWeekDays.indexOf( cldr.supplemental.weekData.firstDay() ); -}; - - - - -/** - * millisecondsInDay - */ -var dateMillisecondsInDay = function( date ) { - // TODO Handle daylight savings discontinuities - return date - dateStartOf( date, "day" ); -}; - - - - -var datePatternRe = (/([a-z])\1*|'([^']|'')+'|''|./ig); - - - - -/** - * hourFormat( date, format, timeSeparator, formatNumber ) - * - * Return date's timezone offset according to the format passed. - * Eg for format when timezone offset is 180: - * - "+H;-H": -3 - * - "+HHmm;-HHmm": -0300 - * - "+HH:mm;-HH:mm": -03:00 - */ -var dateTimezoneHourFormat = function( date, format, timeSeparator, formatNumber ) { - var absOffset, - offset = date.getTimezoneOffset(); - - absOffset = Math.abs( offset ); - formatNumber = formatNumber || { - 1: function( value ) { - return stringPad( value, 1 ); - }, - 2: function( value ) { - return stringPad( value, 2 ); - } - }; - - return format - - // Pick the correct sign side (+ or -). - .split( ";" )[ offset > 0 ? 1 : 0 ] - - // Localize time separator - .replace( ":", timeSeparator ) - - // Update hours offset. - .replace( /HH?/, function( match ) { - return formatNumber[ match.length ]( Math.floor( absOffset / 60 ) ); - }) - - // Update minutes offset and return. - .replace( /mm/, function() { - return formatNumber[ 2 ]( absOffset % 60 ); - }); -}; - - - - -/** - * format( date, properties ) - * - * @date [Date instance]. - * - * @properties - * - * TODO Support other calendar types. - * - * Disclosure: this function borrows excerpts of dojo/date/locale. - */ -var dateFormat = function( date, numberFormatters, properties ) { - var timeSeparator = properties.timeSeparator; - - return properties.pattern.replace( datePatternRe, function( current ) { - var ret, - chr = current.charAt( 0 ), - length = current.length; - - if ( chr === "j" ) { - // Locale preferred hHKk. - // http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data - chr = properties.preferredTime; - } - - if ( chr === "Z" ) { - // Z..ZZZ: same as "xxxx". - if ( length < 4 ) { - chr = "x"; - length = 4; - - // ZZZZ: same as "OOOO". - } else if ( length < 5 ) { - chr = "O"; - length = 4; - - // ZZZZZ: same as "XXXXX" - } else { - chr = "X"; - length = 5; - } - } - - switch ( chr ) { - - // Era - case "G": - ret = properties.eras[ date.getFullYear() < 0 ? 0 : 1 ]; - break; - - // Year - case "y": - // Plain year. - // The length specifies the padding, but for two letters it also specifies the - // maximum length. - ret = date.getFullYear(); - if ( length === 2 ) { - ret = String( ret ); - ret = +ret.substr( ret.length - 2 ); - } - break; - - case "Y": - // Year in "Week of Year" - // The length specifies the padding, but for two letters it also specifies the - // maximum length. - // yearInWeekofYear = date + DaysInAWeek - (dayOfWeek - firstDay) - minDays - ret = new Date( date.getTime() ); - ret.setDate( - ret.getDate() + 7 - - dateDayOfWeek( date, properties.firstDay ) - - properties.firstDay - - properties.minDays - ); - ret = ret.getFullYear(); - if ( length === 2 ) { - ret = String( ret ); - ret = +ret.substr( ret.length - 2 ); - } - break; - - // Quarter - case "Q": - case "q": - ret = Math.ceil( ( date.getMonth() + 1 ) / 3 ); - if ( length > 2 ) { - ret = properties.quarters[ chr ][ length ][ ret ]; - } - break; - - // Month - case "M": - case "L": - ret = date.getMonth() + 1; - if ( length > 2 ) { - ret = properties.months[ chr ][ length ][ ret ]; - } - break; - - // Week - case "w": - // Week of Year. - // woy = ceil( ( doy + dow of 1/1 ) / 7 ) - minDaysStuff ? 1 : 0. - // TODO should pad on ww? Not documented, but I guess so. - ret = dateDayOfWeek( dateStartOf( date, "year" ), properties.firstDay ); - ret = Math.ceil( ( dateDayOfYear( date ) + ret ) / 7 ) - - ( 7 - ret >= properties.minDays ? 0 : 1 ); - break; - - case "W": - // Week of Month. - // wom = ceil( ( dom + dow of `1/month` ) / 7 ) - minDaysStuff ? 1 : 0. - ret = dateDayOfWeek( dateStartOf( date, "month" ), properties.firstDay ); - ret = Math.ceil( ( date.getDate() + ret ) / 7 ) - - ( 7 - ret >= properties.minDays ? 0 : 1 ); - break; - - // Day - case "d": - ret = date.getDate(); - break; - - case "D": - ret = dateDayOfYear( date ) + 1; - break; - - case "F": - // Day of Week in month. eg. 2nd Wed in July. - ret = Math.floor( date.getDate() / 7 ) + 1; - break; - - // Week day - case "e": - case "c": - if ( length <= 2 ) { - // Range is [1-7] (deduced by example provided on documentation) - // TODO Should pad with zeros (not specified in the docs)? - ret = dateDayOfWeek( date, properties.firstDay ) + 1; - break; - } - - /* falls through */ - case "E": - ret = dateWeekDays[ date.getDay() ]; - ret = properties.days[ chr ][ length ][ ret ]; - break; - - // Period (AM or PM) - case "a": - ret = properties.dayPeriods[ date.getHours() < 12 ? "am" : "pm" ]; - break; - - // Hour - case "h": // 1-12 - ret = ( date.getHours() % 12 ) || 12; - break; - - case "H": // 0-23 - ret = date.getHours(); - break; - - case "K": // 0-11 - ret = date.getHours() % 12; - break; - - case "k": // 1-24 - ret = date.getHours() || 24; - break; - - // Minute - case "m": - ret = date.getMinutes(); - break; - - // Second - case "s": - ret = date.getSeconds(); - break; - - case "S": - ret = Math.round( date.getMilliseconds() * Math.pow( 10, length - 3 ) ); - break; - - case "A": - ret = Math.round( dateMillisecondsInDay( date ) * Math.pow( 10, length - 3 ) ); - break; - - // Zone - case "z": - case "O": - // O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT". - // OOOO: "{gmtFormat}{hourFormat}" or "{gmtZeroFormat}", eg. "GMT-08:00" or "GMT". - if ( date.getTimezoneOffset() === 0 ) { - ret = properties.gmtZeroFormat; - } else { - ret = dateTimezoneHourFormat( - date, - length < 4 ? "+H;-H" : properties.tzLongHourFormat, - timeSeparator, - numberFormatters - ); - ret = properties.gmtFormat.replace( /\{0\}/, ret ); - } - break; - - case "X": - // Same as x*, except it uses "Z" for zero offset. - if ( date.getTimezoneOffset() === 0 ) { - ret = "Z"; - break; - } - - /* falls through */ - case "x": - // x: hourFormat("+HH;-HH") - // xx or xxxx: hourFormat("+HHmm;-HHmm") - // xxx or xxxxx: hourFormat("+HH:mm;-HH:mm") - ret = length === 1 ? "+HH;-HH" : ( length % 2 ? "+HH:mm;-HH:mm" : "+HHmm;-HHmm" ); - ret = dateTimezoneHourFormat( date, ret, ":" ); - break; - - // timeSeparator - case ":": - ret = timeSeparator; - break; - - // ' literals. - case "'": - current = current.replace( /''/, "'" ); - if ( length > 2 ) { - current = current.slice( 1, -1 ); - } - ret = current; - break; - - // Anything else is considered a literal, including [ ,:/.@#], chinese, japonese, and - // arabic characters. - default: - ret = current; - } - if ( typeof ret === "number" ) { - ret = numberFormatters[ length ]( ret ); - } - return ret; - }); -}; - - - - -/** - * properties( pattern, cldr ) - * - * @pattern [String] raw pattern. - * ref: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns - * - * @cldr [Cldr instance]. - * - * Return the properties given the pattern and cldr. - * - * TODO Support other calendar types. - */ -var dateFormatProperties = function( pattern, cldr ) { - var properties = { - pattern: pattern, - timeSeparator: numberSymbol( "timeSeparator", cldr ) - }, - widths = [ "abbreviated", "wide", "narrow" ]; - - function setNumberFormatterPattern( pad ) { - if ( !properties.numberFormatters ) { - properties.numberFormatters = {}; - } - properties.numberFormatters[ pad ] = stringPad( "", pad ); - } - - pattern.replace( datePatternRe, function( current ) { - var formatNumber, - chr = current.charAt( 0 ), - length = current.length; - - if ( chr === "j" ) { - // Locale preferred hHKk. - // http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data - properties.preferredTime = chr = cldr.supplemental.timeData.preferred(); - } - - // ZZZZ: same as "OOOO". - if ( chr === "Z" && length === 4 ) { - chr = "O"; - length = 4; - } - - switch ( chr ) { - - // Era - case "G": - properties.eras = cldr.main([ - "dates/calendars/gregorian/eras", - length <= 3 ? "eraAbbr" : ( length === 4 ? "eraNames" : "eraNarrow" ) - ]); - break; - - // Year - case "y": - // Plain year. - formatNumber = true; - break; - - case "Y": - // Year in "Week of Year" - properties.firstDay = dateFirstDayOfWeek( cldr ); - properties.minDays = cldr.supplemental.weekData.minDays(); - formatNumber = true; - break; - - case "u": // Extended year. Need to be implemented. - case "U": // Cyclic year name. Need to be implemented. - throw createErrorUnsupportedFeature({ - feature: "year pattern `" + chr + "`" - }); - - // Quarter - case "Q": - case "q": - if ( length > 2 ) { - if ( !properties.quarters ) { - properties.quarters = {}; - } - if ( !properties.quarters[ chr ] ) { - properties.quarters[ chr ] = {}; - } - properties.quarters[ chr ][ length ] = cldr.main([ - "dates/calendars/gregorian/quarters", - chr === "Q" ? "format" : "stand-alone", - widths[ length - 3 ] - ]); - } else { - formatNumber = true; - } - break; - - // Month - case "M": - case "L": - if ( length > 2 ) { - if ( !properties.months ) { - properties.months = {}; - } - if ( !properties.months[ chr ] ) { - properties.months[ chr ] = {}; - } - properties.months[ chr ][ length ] = cldr.main([ - "dates/calendars/gregorian/months", - chr === "M" ? "format" : "stand-alone", - widths[ length - 3 ] - ]); - } else { - formatNumber = true; - } - break; - - // Week - Week of Year (w) or Week of Month (W). - case "w": - case "W": - properties.firstDay = dateFirstDayOfWeek( cldr ); - properties.minDays = cldr.supplemental.weekData.minDays(); - formatNumber = true; - break; - - // Day - case "d": - case "D": - case "F": - formatNumber = true; - break; - - case "g": - // Modified Julian day. Need to be implemented. - throw createErrorUnsupportedFeature({ - feature: "Julian day pattern `g`" - }); - - // Week day - case "e": - case "c": - if ( length <= 2 ) { - properties.firstDay = dateFirstDayOfWeek( cldr ); - formatNumber = true; - break; - } - - /* falls through */ - case "E": - if ( !properties.days ) { - properties.days = {}; - } - if ( !properties.days[ chr ] ) { - properties.days[ chr ] = {}; - } - if ( length === 6 ) { - - // If short day names are not explicitly specified, abbreviated day names are - // used instead. - // http://www.unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras - // http://unicode.org/cldr/trac/ticket/6790 - properties.days[ chr ][ length ] = cldr.main([ - "dates/calendars/gregorian/days", - chr === "c" ? "stand-alone" : "format", - "short" - ]) || cldr.main([ - "dates/calendars/gregorian/days", - chr === "c" ? "stand-alone" : "format", - "abbreviated" - ]); - } else { - properties.days[ chr ][ length ] = cldr.main([ - "dates/calendars/gregorian/days", - chr === "c" ? "stand-alone" : "format", - widths[ length < 3 ? 0 : length - 3 ] - ]); - } - break; - - // Period (AM or PM) - case "a": - properties.dayPeriods = cldr.main( - "dates/calendars/gregorian/dayPeriods/format/wide" - ); - break; - - // Hour - case "h": // 1-12 - case "H": // 0-23 - case "K": // 0-11 - case "k": // 1-24 - - // Minute - case "m": - - // Second - case "s": - case "S": - case "A": - formatNumber = true; - break; - - // Zone - case "z": - case "O": - // O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT". - // OOOO: "{gmtFormat}{hourFormat}" or "{gmtZeroFormat}", eg. "GMT-08:00" or "GMT". - properties.gmtFormat = cldr.main( "dates/timeZoneNames/gmtFormat" ); - properties.gmtZeroFormat = cldr.main( "dates/timeZoneNames/gmtZeroFormat" ); - properties.tzLongHourFormat = cldr.main( "dates/timeZoneNames/hourFormat" ); - - /* falls through */ - case "Z": - case "X": - case "x": - setNumberFormatterPattern( 1 ); - setNumberFormatterPattern( 2 ); - break; - - case "v": - case "V": - throw createErrorUnsupportedFeature({ - feature: "timezone pattern `" + chr + "`" - }); - } - - if ( formatNumber ) { - setNumberFormatterPattern( length ); - } - }); - - return properties; -}; - - - - -/** - * isLeapYear( year ) - * - * @year [Number] - * - * Returns an indication whether the specified year is a leap year. - */ -var dateIsLeapYear = function( year ) { - return new Date(year, 1, 29).getMonth() === 1; -}; - - - - -/** - * lastDayOfMonth( date ) - * - * @date [Date] - * - * Return the last day of the given date's month - */ -var dateLastDayOfMonth = function( date ) { - return new Date( date.getFullYear(), date.getMonth() + 1, 0).getDate(); -}; - - - - -/** - * Differently from native date.setDate(), this function returns a date whose - * day remains inside the month boundaries. For example: - * - * setDate( FebDate, 31 ): a "Feb 28" date. - * setDate( SepDate, 31 ): a "Sep 30" date. - */ -var dateSetDate = function( date, day ) { - var lastDay = new Date( date.getFullYear(), date.getMonth() + 1, 0 ).getDate(); - - date.setDate( day < 1 ? 1 : day < lastDay ? day : lastDay ); -}; - - - - -/** - * Differently from native date.setMonth(), this function adjusts date if - * needed, so final month is always the one set. - * - * setMonth( Jan31Date, 1 ): a "Feb 28" date. - * setDate( Jan31Date, 8 ): a "Sep 30" date. - */ -var dateSetMonth = function( date, month ) { - var originalDate = date.getDate(); - - date.setDate( 1 ); - date.setMonth( month ); - dateSetDate( date, originalDate ); -}; - - - - -var outOfRange = function( value, low, high ) { - return value < low || value > high; -}; - - - - -/** - * parse( value, tokens, properties ) - * - * @value [String] string date. - * - * @tokens [Object] tokens returned by date/tokenizer. - * - * @properties [Object] output returned by date/tokenizer-properties. - * - * ref: http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns - */ -var dateParse = function( value, tokens, properties ) { - var amPm, day, daysOfYear, era, hour, hour12, timezoneOffset, valid, - YEAR = 0, - MONTH = 1, - DAY = 2, - HOUR = 3, - MINUTE = 4, - SECOND = 5, - MILLISECONDS = 6, - date = new Date(), - truncateAt = [], - units = [ "year", "month", "day", "hour", "minute", "second", "milliseconds" ]; - - if ( !tokens.length ) { - return null; - } - - valid = tokens.every(function( token ) { - var century, chr, value, length; - - if ( token.type === "literal" ) { - // continue - return true; - } - - chr = token.type.charAt( 0 ); - length = token.type.length; - - if ( chr === "j" ) { - // Locale preferred hHKk. - // http://www.unicode.org/reports/tr35/tr35-dates.html#Time_Data - chr = properties.preferredTimeData; - } - - switch ( chr ) { - - // Era - case "G": - truncateAt.push( YEAR ); - era = +token.value; - break; - - // Year - case "y": - value = token.value; - if ( length === 2 ) { - if ( outOfRange( value, 0, 99 ) ) { - return false; - } - // mimic dojo/date/locale: choose century to apply, according to a sliding - // window of 80 years before and 20 years after present year. - century = Math.floor( date.getFullYear() / 100 ) * 100; - value += century; - if ( value > date.getFullYear() + 20 ) { - value -= 100; - } - } - date.setFullYear( value ); - truncateAt.push( YEAR ); - break; - - case "Y": // Year in "Week of Year" - throw createErrorUnsupportedFeature({ - feature: "year pattern `" + chr + "`" - }); - - // Quarter (skip) - case "Q": - case "q": - break; - - // Month - case "M": - case "L": - if ( length <= 2 ) { - value = token.value; - } else { - value = +token.value; - } - if ( outOfRange( value, 1, 12 ) ) { - return false; - } - dateSetMonth( date, value - 1 ); - truncateAt.push( MONTH ); - break; - - // Week (skip) - case "w": // Week of Year. - case "W": // Week of Month. - break; - - // Day - case "d": - day = token.value; - truncateAt.push( DAY ); - break; - - case "D": - daysOfYear = token.value; - truncateAt.push( DAY ); - break; - - case "F": - // Day of Week in month. eg. 2nd Wed in July. - // Skip - break; - - // Week day - case "e": - case "c": - case "E": - // Skip. - // value = arrayIndexOf( dateWeekDays, token.value ); - break; - - // Period (AM or PM) - case "a": - amPm = token.value; - break; - - // Hour - case "h": // 1-12 - value = token.value; - if ( outOfRange( value, 1, 12 ) ) { - return false; - } - hour = hour12 = true; - date.setHours( value === 12 ? 0 : value ); - truncateAt.push( HOUR ); - break; - - case "K": // 0-11 - value = token.value; - if ( outOfRange( value, 0, 11 ) ) { - return false; - } - hour = hour12 = true; - date.setHours( value ); - truncateAt.push( HOUR ); - break; - - case "k": // 1-24 - value = token.value; - if ( outOfRange( value, 1, 24 ) ) { - return false; - } - hour = true; - date.setHours( value === 24 ? 0 : value ); - truncateAt.push( HOUR ); - break; - - case "H": // 0-23 - value = token.value; - if ( outOfRange( value, 0, 23 ) ) { - return false; - } - hour = true; - date.setHours( value ); - truncateAt.push( HOUR ); - break; - - // Minute - case "m": - value = token.value; - if ( outOfRange( value, 0, 59 ) ) { - return false; - } - date.setMinutes( value ); - truncateAt.push( MINUTE ); - break; - - // Second - case "s": - value = token.value; - if ( outOfRange( value, 0, 59 ) ) { - return false; - } - date.setSeconds( value ); - truncateAt.push( SECOND ); - break; - - case "A": - date.setHours( 0 ); - date.setMinutes( 0 ); - date.setSeconds( 0 ); - - /* falls through */ - case "S": - value = Math.round( token.value * Math.pow( 10, 3 - length ) ); - date.setMilliseconds( value ); - truncateAt.push( MILLISECONDS ); - break; - - // Zone - case "Z": - case "z": - case "O": - case "X": - case "x": - timezoneOffset = token.value - date.getTimezoneOffset(); - break; - } - - return true; - }); - - if ( !valid ) { - return null; - } - - // 12-hour format needs AM or PM, 24-hour format doesn't, ie. return null - // if amPm && !hour12 || !amPm && hour12. - if ( hour && !( !amPm ^ hour12 ) ) { - return null; - } - - if ( era === 0 ) { - // 1 BC = year 0 - date.setFullYear( date.getFullYear() * -1 + 1 ); - } - - if ( day !== undefined ) { - if ( outOfRange( day, 1, dateLastDayOfMonth( date ) ) ) { - return null; - } - date.setDate( day ); - } else if ( daysOfYear !== undefined ) { - if ( outOfRange( daysOfYear, 1, dateIsLeapYear( date.getFullYear() ) ? 366 : 365 ) ) { - return null; - } - date.setMonth(0); - date.setDate( daysOfYear ); - } - - if ( hour12 && amPm === "pm" ) { - date.setHours( date.getHours() + 12 ); - } - - if ( timezoneOffset ) { - date.setMinutes( date.getMinutes() + timezoneOffset ); - } - - // Truncate date at the most precise unit defined. Eg. - // If value is "12/31", and pattern is "MM/dd": - // => new Date( , 12, 31, 0, 0, 0, 0 ); - truncateAt = Math.max.apply( null, truncateAt ); - date = dateStartOf( date, units[ truncateAt ] ); - - return date; -}; - - - - -/** - * parseProperties( cldr ) - * - * @cldr [Cldr instance]. - * - * Return parser properties. - */ -var dateParseProperties = function( cldr ) { - return { - preferredTimeData: cldr.supplemental.timeData.preferred() - }; -}; - - - - -/** - * Generated by: - * - * regenerate().add( require( "unicode-7.0.0/categories/N/symbols" ) ).toString(); - * - * https://github.com/mathiasbynens/regenerate - * https://github.com/mathiasbynens/unicode-7.0.0 - */ -var regexpN = /[0-9\xB2\xB3\xB9\xBC-\xBE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D66-\u0D75\u0DE6-\u0DEF\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uA9F0-\uA9F9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19]|\uD800[\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDEE1-\uDEFB\uDF20-\uDF23\uDF41\uDF4A\uDFD1-\uDFD5]|\uD801[\uDCA0-\uDCA9]|\uD802[\uDC58-\uDC5F\uDC79-\uDC7F\uDCA7-\uDCAF\uDD16-\uDD1B\uDE40-\uDE47\uDE7D\uDE7E\uDE9D-\uDE9F\uDEEB-\uDEEF\uDF58-\uDF5F\uDF78-\uDF7F\uDFA9-\uDFAF]|\uD803[\uDE60-\uDE7E]|\uD804[\uDC52-\uDC6F\uDCF0-\uDCF9\uDD36-\uDD3F\uDDD0-\uDDD9\uDDE1-\uDDF4\uDEF0-\uDEF9]|\uD805[\uDCD0-\uDCD9\uDE50-\uDE59\uDEC0-\uDEC9]|\uD806[\uDCE0-\uDCF2]|\uD809[\uDC00-\uDC6E]|\uD81A[\uDE60-\uDE69\uDF50-\uDF59\uDF5B-\uDF61]|\uD834[\uDF60-\uDF71]|\uD835[\uDFCE-\uDFFF]|\uD83A[\uDCC7-\uDCCF]|\uD83C[\uDD00-\uDD0C]/; - - - - -/** - * tokenizer( value, pattern, properties ) - * - * @value [String] string date. - * - * @properties [Object] output returned by date/tokenizer-properties. - * - * Returns an Array of tokens, eg. value "5 o'clock PM", pattern "h 'o''clock' a": - * [{ - * type: "h", - * lexeme: "5" - * }, { - * type: "literal", - * lexeme: " " - * }, { - * type: "literal", - * lexeme: "o'clock" - * }, { - * type: "literal", - * lexeme: " " - * }, { - * type: "a", - * lexeme: "PM", - * value: "pm" - * }] - * - * OBS: lexeme's are always String and may return invalid ranges depending of the token type. - * Eg. "99" for month number. - * - * Return an empty Array when not successfully parsed. - */ -var dateTokenizer = function( value, numberParser, properties ) { - var valid, - timeSeparator = properties.timeSeparator, - tokens = [], - widths = [ "abbreviated", "wide", "narrow" ]; - - valid = properties.pattern.match( datePatternRe ).every(function( current ) { - var chr, length, numeric, tokenRe, - token = {}; - - function hourFormatParse( tokenRe, numberParser ) { - var aux = value.match( tokenRe ); - numberParser = numberParser || function( value ) { - return +value; - }; - - if ( !aux ) { - return false; - } - - // hourFormat containing H only, e.g., `+H;-H` - if ( aux.length < 8 ) { - token.value = - ( aux[ 1 ] ? -numberParser( aux[ 1 ] ) : numberParser( aux[ 4 ] ) ) * 60; - - // hourFormat containing H and m, e.g., `+HHmm;-HHmm` - } else { - token.value = - ( aux[ 1 ] ? -numberParser( aux[ 1 ] ) : numberParser( aux[ 7 ] ) ) * 60 + - ( aux[ 1 ] ? -numberParser( aux[ 4 ] ) : numberParser( aux[ 10 ] ) ); - } - - return true; - } - - // Transform: - // - "+H;-H" -> /\+(\d\d?)|-(\d\d?)/ - // - "+HH;-HH" -> /\+(\d\d)|-(\d\d)/ - // - "+HHmm;-HHmm" -> /\+(\d\d)(\d\d)|-(\d\d)(\d\d)/ - // - "+HH:mm;-HH:mm" -> /\+(\d\d):(\d\d)|-(\d\d):(\d\d)/ - // - // If gmtFormat is GMT{0}, the regexp must fill {0} in each side, e.g.: - // - "+H;-H" -> /GMT\+(\d\d?)|GMT-(\d\d?)/ - function hourFormatRe( hourFormat, gmtFormat, timeSeparator ) { - var re; - - if ( !gmtFormat ) { - gmtFormat = "{0}"; - } - - re = hourFormat - .replace( "+", "\\+" ) - - // Unicode equivalent to (\\d\\d) - .replace( /HH|mm/g, "((" + regexpN.source + ")(" + regexpN.source + "))" ) - - // Unicode equivalent to (\\d\\d?) - .replace( /H|m/g, "((" + regexpN.source + ")(" + regexpN.source + ")?)" ); - - if ( timeSeparator ) { - re = re.replace( /:/g, timeSeparator ); - } - - re = re.split( ";" ).map(function( part ) { - return gmtFormat.replace( "{0}", part ); - }).join( "|" ); - - return new RegExp( re ); - } - - function oneDigitIfLengthOne() { - if ( length === 1 ) { - - // Unicode equivalent to /\d/ - numeric = true; - return tokenRe = regexpN; - } - } - - function oneOrTwoDigitsIfLengthOne() { - if ( length === 1 ) { - - // Unicode equivalent to /\d\d?/ - numeric = true; - return tokenRe = new RegExp( "(" + regexpN.source + ")(" + regexpN.source + ")?" ); - } - } - - function twoDigitsIfLengthTwo() { - if ( length === 2 ) { - - // Unicode equivalent to /\d\d/ - numeric = true; - return tokenRe = new RegExp( "(" + regexpN.source + ")(" + regexpN.source + ")" ); - } - } - - // Brute-force test every locale entry in an attempt to match the given value. - // Return the first found one (and set token accordingly), or null. - function lookup( path ) { - var i, re, - data = properties[ path.join( "/" ) ]; - - for ( i in data ) { - re = new RegExp( "^" + data[ i ] ); - if ( re.test( value ) ) { - token.value = i; - return tokenRe = new RegExp( data[ i ] ); - } - } - return null; - } - - token.type = current; - chr = current.charAt( 0 ), - length = current.length; - - if ( chr === "Z" ) { - // Z..ZZZ: same as "xxxx". - if ( length < 4 ) { - chr = "x"; - length = 4; - - // ZZZZ: same as "OOOO". - } else if ( length < 5 ) { - chr = "O"; - length = 4; - - // ZZZZZ: same as "XXXXX" - } else { - chr = "X"; - length = 5; - } - } - - switch ( chr ) { - - // Era - case "G": - lookup([ - "gregorian/eras", - length <= 3 ? "eraAbbr" : ( length === 4 ? "eraNames" : "eraNarrow" ) - ]); - break; - - // Year - case "y": - case "Y": - numeric = true; - - // number l=1:+, l=2:{2}, l=3:{3,}, l=4:{4,}, ... - if ( length === 1 ) { - - // Unicode equivalent to /\d+/. - tokenRe = new RegExp( "(" + regexpN.source + ")+" ); - } else if ( length === 2 ) { - - // Unicode equivalent to /\d\d/ - tokenRe = new RegExp( "(" + regexpN.source + ")(" + regexpN.source + ")" ); - } else { - - // Unicode equivalent to /\d{length,}/ - tokenRe = new RegExp( "(" + regexpN.source + "){" + length + ",}" ); - } - break; - - // Quarter - case "Q": - case "q": - // number l=1:{1}, l=2:{2}. - // lookup l=3... - oneDigitIfLengthOne() || twoDigitsIfLengthTwo() || lookup([ - "gregorian/quarters", - chr === "Q" ? "format" : "stand-alone", - widths[ length - 3 ] - ]); - break; - - // Month - case "M": - case "L": - // number l=1:{1,2}, l=2:{2}. - // lookup l=3... - oneOrTwoDigitsIfLengthOne() || twoDigitsIfLengthTwo() || lookup([ - "gregorian/months", - chr === "M" ? "format" : "stand-alone", - widths[ length - 3 ] - ]); - break; - - // Day - case "D": - // number {l,3}. - if ( length <= 3 ) { - - // Unicode equivalent to /\d{length,3}/ - numeric = true; - tokenRe = new RegExp( "(" + regexpN.source + "){" + length + ",3}" ); - } - break; - - case "W": - case "F": - // number l=1:{1}. - oneDigitIfLengthOne(); - break; - - // Week day - case "e": - case "c": - // number l=1:{1}, l=2:{2}. - // lookup for length >=3. - if ( length <= 2 ) { - oneDigitIfLengthOne() || twoDigitsIfLengthTwo(); - break; - } - - /* falls through */ - case "E": - if ( length === 6 ) { - // Note: if short day names are not explicitly specified, abbreviated day - // names are used instead http://www.unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras - lookup([ - "gregorian/days", - [ chr === "c" ? "stand-alone" : "format" ], - "short" - ]) || lookup([ - "gregorian/days", - [ chr === "c" ? "stand-alone" : "format" ], - "abbreviated" - ]); - } else { - lookup([ - "gregorian/days", - [ chr === "c" ? "stand-alone" : "format" ], - widths[ length < 3 ? 0 : length - 3 ] - ]); - } - break; - - // Period (AM or PM) - case "a": - lookup([ - "gregorian/dayPeriods/format/wide" - ]); - break; - - // Week, Day, Hour, Minute, or Second - case "w": - case "d": - case "h": - case "H": - case "K": - case "k": - case "j": - case "m": - case "s": - // number l1:{1,2}, l2:{2}. - oneOrTwoDigitsIfLengthOne() || twoDigitsIfLengthTwo(); - break; - - case "S": - // number {l}. - - // Unicode equivalent to /\d{length}/ - numeric = true; - tokenRe = new RegExp( "(" + regexpN.source + "){" + length + "}" ); - break; - - case "A": - // number {l+5}. - - // Unicode equivalent to /\d{length+5}/ - numeric = true; - tokenRe = new RegExp( "(" + regexpN.source + "){" + ( length + 5 ) + "}" ); - break; - - // Zone - case "z": - case "O": - // O: "{gmtFormat}+H;{gmtFormat}-H" or "{gmtZeroFormat}", eg. "GMT-8" or "GMT". - // OOOO: "{gmtFormat}{hourFormat}" or "{gmtZeroFormat}", eg. "GMT-08:00" or "GMT". - if ( value === properties[ "timeZoneNames/gmtZeroFormat" ] ) { - token.value = 0; - tokenRe = new RegExp( properties[ "timeZoneNames/gmtZeroFormat" ] ); - } else { - tokenRe = hourFormatRe( - length < 4 ? "+H;-H" : properties[ "timeZoneNames/hourFormat" ], - properties[ "timeZoneNames/gmtFormat" ], - timeSeparator - ); - if ( !hourFormatParse( tokenRe, numberParser ) ) { - return null; - } - } - break; - - case "X": - // Same as x*, except it uses "Z" for zero offset. - if ( value === "Z" ) { - token.value = 0; - tokenRe = /Z/; - break; - } - - /* falls through */ - case "x": - // x: hourFormat("+HH;-HH") - // xx or xxxx: hourFormat("+HHmm;-HHmm") - // xxx or xxxxx: hourFormat("+HH:mm;-HH:mm") - tokenRe = hourFormatRe( - length === 1 ? "+HH;-HH" : ( length % 2 ? "+HH:mm;-HH:mm" : "+HHmm;-HHmm" ) - ); - if ( !hourFormatParse( tokenRe ) ) { - return null; - } - break; - - case "'": - token.type = "literal"; - current = current.replace( /''/, "'" ); - if ( length > 2 ) { - current = current.slice( 1, -1 ); - } - tokenRe = new RegExp( regexpEscape( current ) ); - break; - - default: - token.type = "literal"; - tokenRe = /./; - } - - if ( !tokenRe ) { - return false; - } - - // Get lexeme and consume it. - value = value.replace( new RegExp( "^" + tokenRe.source ), function( lexeme ) { - token.lexeme = lexeme; - if ( numeric ) { - token.value = numberParser( lexeme ); - } - return ""; - }); - - if ( !token.lexeme ) { - return false; - } - - tokens.push( token ); - return true; - }); - - return valid ? tokens : []; -}; - - - - -/** - * tokenizerProperties( pattern, cldr ) - * - * @pattern [String] raw pattern. - * - * @cldr [Cldr instance]. - * - * Return Object with data that will be used by tokenizer. - */ -var dateTokenizerProperties = function( pattern, cldr ) { - var properties = { - pattern: pattern, - timeSeparator: numberSymbol( "timeSeparator", cldr ) - }, - widths = [ "abbreviated", "wide", "narrow" ]; - - function populateProperties( path, value ) { - - // The `dates` and `calendars` trim's purpose is to reduce properties' key size only. - properties[ path.replace( /^.*\/dates\//, "" ).replace( /calendars\//, "" ) ] = value; - } - - cldr.on( "get", populateProperties ); - - pattern.match( datePatternRe ).forEach(function( current ) { - var chr, length; - - chr = current.charAt( 0 ), - length = current.length; - - if ( chr === "Z" && length < 5 ) { - chr = "O"; - length = 4; - } - - switch ( chr ) { - - // Era - case "G": - cldr.main([ - "dates/calendars/gregorian/eras", - length <= 3 ? "eraAbbr" : ( length === 4 ? "eraNames" : "eraNarrow" ) - ]); - break; - - // Year - case "u": // Extended year. Need to be implemented. - case "U": // Cyclic year name. Need to be implemented. - throw createErrorUnsupportedFeature({ - feature: "year pattern `" + chr + "`" - }); - - // Quarter - case "Q": - case "q": - if ( length > 2 ) { - cldr.main([ - "dates/calendars/gregorian/quarters", - chr === "Q" ? "format" : "stand-alone", - widths[ length - 3 ] - ]); - } - break; - - // Month - case "M": - case "L": - // number l=1:{1,2}, l=2:{2}. - // lookup l=3... - if ( length > 2 ) { - cldr.main([ - "dates/calendars/gregorian/months", - chr === "M" ? "format" : "stand-alone", - widths[ length - 3 ] - ]); - } - break; - - // Day - case "g": - // Modified Julian day. Need to be implemented. - throw createErrorUnsupportedFeature({ - feature: "Julian day pattern `g`" - }); - - // Week day - case "e": - case "c": - // lookup for length >=3. - if ( length <= 2 ) { - break; - } - - /* falls through */ - case "E": - if ( length === 6 ) { - // Note: if short day names are not explicitly specified, abbreviated day - // names are used instead http://www.unicode.org/reports/tr35/tr35-dates.html#months_days_quarters_eras - cldr.main([ - "dates/calendars/gregorian/days", - [ chr === "c" ? "stand-alone" : "format" ], - "short" - ]) || cldr.main([ - "dates/calendars/gregorian/days", - [ chr === "c" ? "stand-alone" : "format" ], - "abbreviated" - ]); - } else { - cldr.main([ - "dates/calendars/gregorian/days", - [ chr === "c" ? "stand-alone" : "format" ], - widths[ length < 3 ? 0 : length - 3 ] - ]); - } - break; - - // Period (AM or PM) - case "a": - cldr.main([ - "dates/calendars/gregorian/dayPeriods/format/wide" - ]); - break; - - // Zone - case "z": - case "O": - cldr.main( "dates/timeZoneNames/gmtFormat" ); - cldr.main( "dates/timeZoneNames/gmtZeroFormat" ); - cldr.main( "dates/timeZoneNames/hourFormat" ); - break; - - case "v": - case "V": - throw createErrorUnsupportedFeature({ - feature: "timezone pattern `" + chr + "`" - }); - } - }); - - cldr.off( "get", populateProperties ); - - return properties; -}; - - - - -function validateRequiredCldr( path, value ) { - validateCldr( path, value, { - skip: [ - /dates\/calendars\/gregorian\/dateTimeFormats\/availableFormats/, - /dates\/calendars\/gregorian\/days\/.*\/short/, - /supplemental\/timeData\/(?!001)/, - /supplemental\/weekData\/(?!001)/ - ] - }); -} - -/** - * .dateFormatter( options ) - * - * @options [Object] see date/expand_pattern for more info. - * - * Return a date formatter function (of the form below) according to the given options and the - * default/instance locale. - * - * fn( value ) - * - * @value [Date] - * - * Return a function that formats a date according to the given `format` and the default/instance - * locale. - */ -Globalize.dateFormatter = -Globalize.prototype.dateFormatter = function( options ) { - var cldr, numberFormatters, pad, pattern, properties; - - validateParameterTypePlainObject( options, "options" ); - - cldr = this.cldr; - options = options || { skeleton: "yMd" }; - - validateDefaultLocale( cldr ); - - cldr.on( "get", validateRequiredCldr ); - pattern = dateExpandPattern( options, cldr ); - properties = dateFormatProperties( pattern, cldr ); - cldr.off( "get", validateRequiredCldr ); - - // Create needed number formatters. - numberFormatters = properties.numberFormatters; - delete properties.numberFormatters; - for ( pad in numberFormatters ) { - numberFormatters[ pad ] = this.numberFormatter({ - raw: numberFormatters[ pad ] - }); - } - - return function( value ) { - validateParameterPresence( value, "value" ); - validateParameterTypeDate( value, "value" ); - return dateFormat( value, numberFormatters, properties ); - }; -}; - -/** - * .dateParser( options ) - * - * @options [Object] see date/expand_pattern for more info. - * - * Return a function that parses a string date according to the given `formats` and the - * default/instance locale. - */ -Globalize.dateParser = -Globalize.prototype.dateParser = function( options ) { - var cldr, numberParser, parseProperties, pattern, tokenizerProperties; - - validateParameterTypePlainObject( options, "options" ); - - cldr = this.cldr; - options = options || { skeleton: "yMd" }; - - validateDefaultLocale( cldr ); - - cldr.on( "get", validateRequiredCldr ); - pattern = dateExpandPattern( options, cldr ); - tokenizerProperties = dateTokenizerProperties( pattern, cldr ); - parseProperties = dateParseProperties( cldr ); - cldr.off( "get", validateRequiredCldr ); - - numberParser = this.numberParser({ raw: "0" }); - - return function( value ) { - var tokens; - - validateParameterPresence( value, "value" ); - validateParameterTypeString( value, "value" ); - - tokens = dateTokenizer( value, numberParser, tokenizerProperties ); - return dateParse( value, tokens, parseProperties ) || null; - }; -}; - -/** - * .formatDate( value, options ) - * - * @value [Date] - * - * @options [Object] see date/expand_pattern for more info. - * - * Formats a date or number according to the given options string and the default/instance locale. - */ -Globalize.formatDate = -Globalize.prototype.formatDate = function( value, options ) { - validateParameterPresence( value, "value" ); - validateParameterTypeDate( value, "value" ); - - return this.dateFormatter( options )( value ); -}; - -/** - * .parseDate( value, options ) - * - * @value [String] - * - * @options [Object] see date/expand_pattern for more info. - * - * Return a Date instance or null. - */ -Globalize.parseDate = -Globalize.prototype.parseDate = function( value, options ) { - validateParameterPresence( value, "value" ); - validateParameterTypeString( value, "value" ); - - return this.dateParser( options )( value ); -}; - -return Globalize; - - - - -})); diff --git a/web/Scripts/globalize/message.js b/web/Scripts/globalize/message.js deleted file mode 100644 index 4220f274..00000000 --- a/web/Scripts/globalize/message.js +++ /dev/null @@ -1,2022 +0,0 @@ -/** - * Globalize v1.0.0 - * - * http://github.com/jquery/globalize - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2015-04-23T12:02Z - */ -/*! - * Globalize v1.0.0 2015-04-23T12:02Z Released under the MIT license - * http://git.io/TrdQbw - */ -(function( root, factory ) { - - // UMD returnExports - if ( typeof define === "function" && define.amd ) { - - // AMD - define([ - "cldr", - "../globalize", - "cldr/event" - ], factory ); - } else if ( typeof exports === "object" ) { - - // Node, CommonJS - module.exports = factory( require( "cldrjs" ), require( "globalize" ) ); - } else { - - // Extend global - factory( root.Cldr, root.Globalize ); - } -}(this, function( Cldr, Globalize ) { - -var alwaysArray = Globalize._alwaysArray, - isPlainObject = Globalize._isPlainObject, - validate = Globalize._validate, - validateDefaultLocale = Globalize._validateDefaultLocale, - validateParameterPresence = Globalize._validateParameterPresence, - validateParameterType = Globalize._validateParameterType, - validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject; -var MessageFormat; -/* jshint ignore:start */ -MessageFormat = (function() { -MessageFormat._parse = (function() { - - /* - * Generated by PEG.js 0.8.0. - * - * http://pegjs.majda.cz/ - */ - - function peg$subclass(child, parent) { - function ctor() { this.constructor = child; } - ctor.prototype = parent.prototype; - child.prototype = new ctor(); - } - - function SyntaxError(message, expected, found, offset, line, column) { - this.message = message; - this.expected = expected; - this.found = found; - this.offset = offset; - this.line = line; - this.column = column; - - this.name = "SyntaxError"; - } - - peg$subclass(SyntaxError, Error); - - function parse(input) { - var options = arguments.length > 1 ? arguments[1] : {}, - - peg$FAILED = {}, - - peg$startRuleFunctions = { start: peg$parsestart }, - peg$startRuleFunction = peg$parsestart, - - peg$c0 = [], - peg$c1 = function(st) { - return { type: 'messageFormatPattern', statements: st }; - }, - peg$c2 = peg$FAILED, - peg$c3 = "{", - peg$c4 = { type: "literal", value: "{", description: "\"{\"" }, - peg$c5 = null, - peg$c6 = ",", - peg$c7 = { type: "literal", value: ",", description: "\",\"" }, - peg$c8 = "}", - peg$c9 = { type: "literal", value: "}", description: "\"}\"" }, - peg$c10 = function(argIdx, efmt) { - var res = { - type: "messageFormatElement", - argumentIndex: argIdx - }; - if (efmt && efmt.length) { - res.elementFormat = efmt[1]; - } else { - res.output = true; - } - return res; - }, - peg$c11 = "plural", - peg$c12 = { type: "literal", value: "plural", description: "\"plural\"" }, - peg$c13 = function(t, s) { - return { type: "elementFormat", key: t, val: s }; - }, - peg$c14 = "selectordinal", - peg$c15 = { type: "literal", value: "selectordinal", description: "\"selectordinal\"" }, - peg$c16 = "select", - peg$c17 = { type: "literal", value: "select", description: "\"select\"" }, - peg$c18 = function(t, p) { - return { type: "elementFormat", key: t, val: p }; - }, - peg$c19 = function(op, pf) { - return { type: "pluralFormatPattern", pluralForms: pf, offset: op || 0 }; - }, - peg$c20 = "offset", - peg$c21 = { type: "literal", value: "offset", description: "\"offset\"" }, - peg$c22 = ":", - peg$c23 = { type: "literal", value: ":", description: "\":\"" }, - peg$c24 = function(d) { return d; }, - peg$c25 = function(k, mfp) { - return { key: k, val: mfp }; - }, - peg$c26 = function(i) { return i; }, - peg$c27 = "=", - peg$c28 = { type: "literal", value: "=", description: "\"=\"" }, - peg$c29 = function(pf) { return { type: "selectFormatPattern", pluralForms: pf }; }, - peg$c30 = function(p) { return p; }, - peg$c31 = "#", - peg$c32 = { type: "literal", value: "#", description: "\"#\"" }, - peg$c33 = function() { return {type: 'octothorpe'}; }, - peg$c34 = function(s) { return { type: "string", val: s.join('') }; }, - peg$c35 = { type: "other", description: "identifier" }, - peg$c36 = /^[0-9a-zA-Z$_]/, - peg$c37 = { type: "class", value: "[0-9a-zA-Z$_]", description: "[0-9a-zA-Z$_]" }, - peg$c38 = /^[^ \t\n\r,.+={}]/, - peg$c39 = { type: "class", value: "[^ \\t\\n\\r,.+={}]", description: "[^ \\t\\n\\r,.+={}]" }, - peg$c40 = function(s) { return s; }, - peg$c41 = function(chars) { return chars.join(''); }, - peg$c42 = /^[^{}#\\\0-\x1F \t\n\r]/, - peg$c43 = { type: "class", value: "[^{}#\\\\\\0-\\x1F \\t\\n\\r]", description: "[^{}#\\\\\\0-\\x1F \\t\\n\\r]" }, - peg$c44 = function(x) { return x; }, - peg$c45 = "\\\\", - peg$c46 = { type: "literal", value: "\\\\", description: "\"\\\\\\\\\"" }, - peg$c47 = function() { return "\\"; }, - peg$c48 = "\\#", - peg$c49 = { type: "literal", value: "\\#", description: "\"\\\\#\"" }, - peg$c50 = function() { return "#"; }, - peg$c51 = "\\{", - peg$c52 = { type: "literal", value: "\\{", description: "\"\\\\{\"" }, - peg$c53 = function() { return "\u007B"; }, - peg$c54 = "\\}", - peg$c55 = { type: "literal", value: "\\}", description: "\"\\\\}\"" }, - peg$c56 = function() { return "\u007D"; }, - peg$c57 = "\\u", - peg$c58 = { type: "literal", value: "\\u", description: "\"\\\\u\"" }, - peg$c59 = function(h1, h2, h3, h4) { - return String.fromCharCode(parseInt("0x" + h1 + h2 + h3 + h4)); - }, - peg$c60 = /^[0-9]/, - peg$c61 = { type: "class", value: "[0-9]", description: "[0-9]" }, - peg$c62 = function(ds) { - //the number might start with 0 but must not be interpreted as an octal number - //Hence, the base is passed to parseInt explicitely - return parseInt((ds.join('')), 10); - }, - peg$c63 = /^[0-9a-fA-F]/, - peg$c64 = { type: "class", value: "[0-9a-fA-F]", description: "[0-9a-fA-F]" }, - peg$c65 = { type: "other", description: "whitespace" }, - peg$c66 = function(w) { return w.join(''); }, - peg$c67 = /^[ \t\n\r]/, - peg$c68 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" }, - - peg$currPos = 0, - peg$reportedPos = 0, - peg$cachedPos = 0, - peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, - peg$maxFailPos = 0, - peg$maxFailExpected = [], - peg$silentFails = 0, - - peg$result; - - if ("startRule" in options) { - if (!(options.startRule in peg$startRuleFunctions)) { - throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); - } - - peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; - } - - function text() { - return input.substring(peg$reportedPos, peg$currPos); - } - - function offset() { - return peg$reportedPos; - } - - function line() { - return peg$computePosDetails(peg$reportedPos).line; - } - - function column() { - return peg$computePosDetails(peg$reportedPos).column; - } - - function expected(description) { - throw peg$buildException( - null, - [{ type: "other", description: description }], - peg$reportedPos - ); - } - - function error(message) { - throw peg$buildException(message, null, peg$reportedPos); - } - - function peg$computePosDetails(pos) { - function advance(details, startPos, endPos) { - var p, ch; - - for (p = startPos; p < endPos; p++) { - ch = input.charAt(p); - if (ch === "\n") { - if (!details.seenCR) { details.line++; } - details.column = 1; - details.seenCR = false; - } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { - details.line++; - details.column = 1; - details.seenCR = true; - } else { - details.column++; - details.seenCR = false; - } - } - } - - if (peg$cachedPos !== pos) { - if (peg$cachedPos > pos) { - peg$cachedPos = 0; - peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; - } - advance(peg$cachedPosDetails, peg$cachedPos, pos); - peg$cachedPos = pos; - } - - return peg$cachedPosDetails; - } - - function peg$fail(expected) { - if (peg$currPos < peg$maxFailPos) { return; } - - if (peg$currPos > peg$maxFailPos) { - peg$maxFailPos = peg$currPos; - peg$maxFailExpected = []; - } - - peg$maxFailExpected.push(expected); - } - - function peg$buildException(message, expected, pos) { - function cleanupExpected(expected) { - var i = 1; - - expected.sort(function(a, b) { - if (a.description < b.description) { - return -1; - } else if (a.description > b.description) { - return 1; - } else { - return 0; - } - }); - - while (i < expected.length) { - if (expected[i - 1] === expected[i]) { - expected.splice(i, 1); - } else { - i++; - } - } - } - - function buildMessage(expected, found) { - function stringEscape(s) { - function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } - - return s - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') - .replace(/\x08/g, '\\b') - .replace(/\t/g, '\\t') - .replace(/\n/g, '\\n') - .replace(/\f/g, '\\f') - .replace(/\r/g, '\\r') - .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) - .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) - .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) - .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); - } - - var expectedDescs = new Array(expected.length), - expectedDesc, foundDesc, i; - - for (i = 0; i < expected.length; i++) { - expectedDescs[i] = expected[i].description; - } - - expectedDesc = expected.length > 1 - ? expectedDescs.slice(0, -1).join(", ") - + " or " - + expectedDescs[expected.length - 1] - : expectedDescs[0]; - - foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; - - return "Expected " + expectedDesc + " but " + foundDesc + " found."; - } - - var posDetails = peg$computePosDetails(pos), - found = pos < input.length ? input.charAt(pos) : null; - - if (expected !== null) { - cleanupExpected(expected); - } - - return new SyntaxError( - message !== null ? message : buildMessage(expected, found), - expected, - found, - pos, - posDetails.line, - posDetails.column - ); - } - - function peg$parsestart() { - var s0; - - s0 = peg$parsemessageFormatPattern(); - - return s0; - } - - function peg$parsemessageFormatPattern() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = []; - s2 = peg$parsemessageFormatElement(); - if (s2 === peg$FAILED) { - s2 = peg$parsestring(); - if (s2 === peg$FAILED) { - s2 = peg$parseoctothorpe(); - } - } - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parsemessageFormatElement(); - if (s2 === peg$FAILED) { - s2 = peg$parsestring(); - if (s2 === peg$FAILED) { - s2 = peg$parseoctothorpe(); - } - } - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c1(s1); - } - s0 = s1; - - return s0; - } - - function peg$parsemessageFormatElement() { - var s0, s1, s2, s3, s4, s5, s6; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 123) { - s1 = peg$c3; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c4); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parse_(); - if (s2 !== peg$FAILED) { - s3 = peg$parseid(); - if (s3 !== peg$FAILED) { - s4 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 44) { - s5 = peg$c6; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c7); } - } - if (s5 !== peg$FAILED) { - s6 = peg$parseelementFormat(); - if (s6 !== peg$FAILED) { - s5 = [s5, s6]; - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$c2; - } - } else { - peg$currPos = s4; - s4 = peg$c2; - } - if (s4 === peg$FAILED) { - s4 = peg$c5; - } - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 125) { - s6 = peg$c8; - peg$currPos++; - } else { - s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c9); } - } - if (s6 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c10(s3, s4); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - - return s0; - } - - function peg$parseelementFormat() { - var s0, s1, s2, s3, s4, s5, s6, s7; - - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c11) { - s2 = peg$c11; - peg$currPos += 6; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c12); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 44) { - s4 = peg$c6; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c7); } - } - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - s6 = peg$parsepluralFormatPattern(); - if (s6 !== peg$FAILED) { - s7 = peg$parse_(); - if (s7 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c13(s2, s6); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 13) === peg$c14) { - s2 = peg$c14; - peg$currPos += 13; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c15); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 44) { - s4 = peg$c6; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c7); } - } - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - s6 = peg$parsepluralFormatPattern(); - if (s6 !== peg$FAILED) { - s7 = peg$parse_(); - if (s7 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c13(s2, s6); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c16) { - s2 = peg$c16; - peg$currPos += 6; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c17); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 44) { - s4 = peg$c6; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c7); } - } - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - s6 = peg$parseselectFormatPattern(); - if (s6 !== peg$FAILED) { - s7 = peg$parse_(); - if (s7 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c13(s2, s6); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - s2 = peg$parseid(); - if (s2 !== peg$FAILED) { - s3 = []; - s4 = peg$parseargStylePattern(); - while (s4 !== peg$FAILED) { - s3.push(s4); - s4 = peg$parseargStylePattern(); - } - if (s3 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c18(s2, s3); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } - } - } - - return s0; - } - - function peg$parsepluralFormatPattern() { - var s0, s1, s2, s3; - - s0 = peg$currPos; - s1 = peg$parseoffsetPattern(); - if (s1 === peg$FAILED) { - s1 = peg$c5; - } - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parsepluralForm(); - if (s3 !== peg$FAILED) { - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsepluralForm(); - } - } else { - s2 = peg$c2; - } - if (s2 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c19(s1, s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - - return s0; - } - - function peg$parseoffsetPattern() { - var s0, s1, s2, s3, s4, s5, s6, s7; - - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 6) === peg$c20) { - s2 = peg$c20; - peg$currPos += 6; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c21); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 58) { - s4 = peg$c22; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c23); } - } - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - s6 = peg$parsedigits(); - if (s6 !== peg$FAILED) { - s7 = peg$parse_(); - if (s7 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c24(s6); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - - return s0; - } - - function peg$parsepluralForm() { - var s0, s1, s2, s3, s4, s5, s6, s7, s8; - - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - s2 = peg$parsepluralKey(); - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 123) { - s4 = peg$c3; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c4); } - } - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - s6 = peg$parsemessageFormatPattern(); - if (s6 !== peg$FAILED) { - s7 = peg$parse_(); - if (s7 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 125) { - s8 = peg$c8; - peg$currPos++; - } else { - s8 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c9); } - } - if (s8 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c25(s2, s6); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - - return s0; - } - - function peg$parsepluralKey() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = peg$parseid(); - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c26(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 61) { - s1 = peg$c27; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c28); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsedigits(); - if (s2 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c24(s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } - - return s0; - } - - function peg$parseselectFormatPattern() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = []; - s2 = peg$parseselectForm(); - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parseselectForm(); - } - } else { - s1 = peg$c2; - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c29(s1); - } - s0 = s1; - - return s0; - } - - function peg$parseselectForm() { - var s0, s1, s2, s3, s4, s5, s6, s7, s8; - - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - s2 = peg$parseid(); - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 123) { - s4 = peg$c3; - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c4); } - } - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - s6 = peg$parsemessageFormatPattern(); - if (s6 !== peg$FAILED) { - s7 = peg$parse_(); - if (s7 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 125) { - s8 = peg$c8; - peg$currPos++; - } else { - s8 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c9); } - } - if (s8 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c25(s2, s6); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - - return s0; - } - - function peg$parseargStylePattern() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 44) { - s2 = peg$c6; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c7); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - s4 = peg$parseid(); - if (s4 !== peg$FAILED) { - s5 = peg$parse_(); - if (s5 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c30(s4); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - - return s0; - } - - function peg$parseoctothorpe() { - var s0, s1; - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 35) { - s1 = peg$c31; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c32); } - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c33(); - } - s0 = s1; - - return s0; - } - - function peg$parsestring() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = []; - s2 = peg$parsechars(); - if (s2 === peg$FAILED) { - s2 = peg$parsewhitespace(); - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parsechars(); - if (s2 === peg$FAILED) { - s2 = peg$parsewhitespace(); - } - } - } else { - s1 = peg$c2; - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c34(s1); - } - s0 = s1; - - return s0; - } - - function peg$parseid() { - var s0, s1, s2, s3, s4, s5, s6; - - peg$silentFails++; - s0 = peg$currPos; - s1 = peg$parse_(); - if (s1 !== peg$FAILED) { - s2 = peg$currPos; - s3 = peg$currPos; - if (peg$c36.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c37); } - } - if (s4 !== peg$FAILED) { - s5 = []; - if (peg$c38.test(input.charAt(peg$currPos))) { - s6 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c39); } - } - while (s6 !== peg$FAILED) { - s5.push(s6); - if (peg$c38.test(input.charAt(peg$currPos))) { - s6 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c39); } - } - } - if (s5 !== peg$FAILED) { - s4 = [s4, s5]; - s3 = s4; - } else { - peg$currPos = s3; - s3 = peg$c2; - } - } else { - peg$currPos = s3; - s3 = peg$c2; - } - if (s3 !== peg$FAILED) { - s3 = input.substring(s2, peg$currPos); - } - s2 = s3; - if (s2 !== peg$FAILED) { - s3 = peg$parse_(); - if (s3 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c40(s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c35); } - } - - return s0; - } - - function peg$parsechars() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = []; - s2 = peg$parsechar(); - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parsechar(); - } - } else { - s1 = peg$c2; - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c41(s1); - } - s0 = s1; - - return s0; - } - - function peg$parsechar() { - var s0, s1, s2, s3, s4, s5; - - s0 = peg$currPos; - if (peg$c42.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c44(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c45) { - s1 = peg$c45; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c46); } - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c47(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c48) { - s1 = peg$c48; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c49); } - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c50(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c51) { - s1 = peg$c51; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c52); } - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c53(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c54) { - s1 = peg$c54; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c55); } - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c56(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c57) { - s1 = peg$c57; - peg$currPos += 2; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c58); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsehexDigit(); - if (s2 !== peg$FAILED) { - s3 = peg$parsehexDigit(); - if (s3 !== peg$FAILED) { - s4 = peg$parsehexDigit(); - if (s4 !== peg$FAILED) { - s5 = peg$parsehexDigit(); - if (s5 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c59(s2, s3, s4, s5); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } else { - peg$currPos = s0; - s0 = peg$c2; - } - } - } - } - } - } - - return s0; - } - - function peg$parsedigits() { - var s0, s1, s2; - - s0 = peg$currPos; - s1 = []; - if (peg$c60.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c61); } - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - if (peg$c60.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c61); } - } - } - } else { - s1 = peg$c2; - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c62(s1); - } - s0 = s1; - - return s0; - } - - function peg$parsehexDigit() { - var s0; - - if (peg$c63.test(input.charAt(peg$currPos))) { - s0 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c64); } - } - - return s0; - } - - function peg$parse_() { - var s0, s1, s2; - - peg$silentFails++; - s0 = peg$currPos; - s1 = []; - s2 = peg$parsewhitespace(); - while (s2 !== peg$FAILED) { - s1.push(s2); - s2 = peg$parsewhitespace(); - } - if (s1 !== peg$FAILED) { - peg$reportedPos = s0; - s1 = peg$c66(s1); - } - s0 = s1; - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c65); } - } - - return s0; - } - - function peg$parsewhitespace() { - var s0; - - if (peg$c67.test(input.charAt(peg$currPos))) { - s0 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c68); } - } - - return s0; - } - - peg$result = peg$startRuleFunction(); - - if (peg$result !== peg$FAILED && peg$currPos === input.length) { - return peg$result; - } else { - if (peg$result !== peg$FAILED && peg$currPos < input.length) { - peg$fail({ type: "end", description: "end of input" }); - } - - throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); - } - } - - return { - SyntaxError: SyntaxError, - parse: parse - }; -})().parse; - - -/** @file messageformat.js - ICU PluralFormat + SelectFormat for JavaScript - * @author Alex Sexton - @SlexAxton - * @version 0.3.0-1 - * @copyright 2012-2015 Alex Sexton, Eemeli Aro, and Contributors - * @license To use or fork, MIT. To contribute back, Dojo CLA */ - - -/** Utility function for quoting an Object's key value iff required - * @private */ -function propname(key, obj) { - if (/^[A-Z_$][0-9A-Z_$]*$/i.test(key)) { - return obj ? obj + '.' + key : key; - } else { - var jkey = JSON.stringify(key); - return obj ? obj + '[' + jkey + ']' : jkey; - } -}; - - -/** Create a new message formatter - * - * @class - * @global - * @param {string|string[]} [locale="en"] - The locale to use, with fallbacks - * @param {function} [pluralFunc] - Optional custom pluralization function - * @param {function[]} [formatters] - Optional custom formatting functions */ -function MessageFormat(locale, pluralFunc, formatters) { - this.lc = [locale]; - this.runtime.pluralFuncs = {}; - this.runtime.pluralFuncs[this.lc[0]] = pluralFunc; - this.runtime.fmt = {}; - if (formatters) for (var f in formatters) { - this.runtime.fmt[f] = formatters[f]; - } -} - - - - -/** Parse an input string to its AST - * - * Precompiled from `lib/messageformat-parser.pegjs` by - * {@link http://pegjs.org/ PEG.js}. Included in MessageFormat object - * to enable testing. - * - * @private */ - - - -/** Pluralization functions from - * {@link http://github.com/eemeli/make-plural.js make-plural} - * - * @memberof MessageFormat - * @type Object. */ -MessageFormat.plurals = {}; - - -/** Default number formatting functions in the style of ICU's - * {@link http://icu-project.org/apiref/icu4j/com/ibm/icu/text/MessageFormat.html simpleArg syntax} - * implemented using the - * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl Intl} - * object defined by ECMA-402. - * - * **Note**: Intl is not defined in default Node until 0.11.15 / 0.12.0, so - * earlier versions require a {@link https://www.npmjs.com/package/intl polyfill}. - * Therefore {@link MessageFormat.withIntlSupport} needs to be true for these - * functions to be available for inclusion in the output. - * - * @see MessageFormat#setIntlSupport - * - * @namespace - * @memberof MessageFormat - * @property {function} number - Represent a number as an integer, percent or currency value - * @property {function} date - Represent a date as a full/long/default/short string - * @property {function} time - Represent a time as a full/long/default/short string - * - * @example - * > var MessageFormat = require('messageformat'); - * > var mf = (new MessageFormat('en')).setIntlSupport(true); - * > mf.currency = 'EUR'; - * > var mfunc = mf.compile("The total is {V,number,currency}."); - * > mfunc({V:5.5}) - * "The total is €5.50." - * - * @example - * > var MessageFormat = require('messageformat'); - * > var mf = new MessageFormat('en', null, {number: MessageFormat.number}); - * > mf.currency = 'EUR'; - * > var mfunc = mf.compile("The total is {V,number,currency}."); - * > mfunc({V:5.5}) - * "The total is €5.50." */ -MessageFormat.formatters = {}; - -/** Enable or disable support for the default formatters, which require the - * `Intl` object. Note that this can't be autodetected, as the environment - * in which the formatted text is compiled into Javascript functions is not - * necessarily the same environment in which they will get executed. - * - * @see MessageFormat.formatters - * - * @memberof MessageFormat - * @param {boolean} [enable=true] - * @returns {Object} The MessageFormat instance, to allow for chaining - * @example - * > var Intl = require('intl'); - * > var MessageFormat = require('messageformat'); - * > var mf = (new MessageFormat('en')).setIntlSupport(true); - * > mf.currency = 'EUR'; - * > mf.compile("The total is {V,number,currency}.")({V:5.5}); - * "The total is €5.50." */ - - - -/** A set of utility functions that are called by the compiled Javascript - * functions, these are included locally in the output of {@link - * MessageFormat#compile compile()}. - * - * @namespace - * @memberof MessageFormat */ -MessageFormat.prototype.runtime = { - - /** Utility function for `#` in plural rules - * - * @param {number} value - The value to operate on - * @param {number} [offset=0] - An optional offset, set by the surrounding context */ - number: function(value, offset) { - if (isNaN(value)) throw new Error("'" + value + "' isn't a number."); - return value - (offset || 0); - }, - - /** Utility function for `{N, plural|selectordinal, ...}` - * - * @param {number} value - The key to use to find a pluralization rule - * @param {number} offset - An offset to apply to `value` - * @param {function} lcfunc - A locale function from `pluralFuncs` - * @param {Object.} data - The object from which results are looked up - * @param {?boolean} isOrdinal - If true, use ordinal rather than cardinal rules - * @returns {string} The result of the pluralization */ - plural: function(value, offset, lcfunc, data, isOrdinal) { - if ({}.hasOwnProperty.call(data, value)) return data[value](); - if (offset) value -= offset; - var key = lcfunc(value, isOrdinal); - if (key in data) return data[key](); - return data.other(); - }, - - /** Utility function for `{N, select, ...}` - * - * @param {number} value - The key to use to find a selection - * @param {Object.} data - The object from which results are looked up - * @returns {string} The result of the select statement */ - select: function(value, data) { - if ({}.hasOwnProperty.call(data, value)) return data[value](); - return data.other() - }, - - /** Pluralization functions included in compiled output - * @instance - * @type Object. */ - pluralFuncs: {}, - - /** Custom formatting functions called by `{var, fn[, args]*}` syntax - * - * For examples, see {@link MessageFormat.formatters} - * - * @instance - * @see MessageFormat.formatters - * @type Object. */ - fmt: {}, - - /** Custom stringifier to clean up browser inconsistencies - * @instance */ - toString: function () { - var _stringify = function(o, level) { - if (typeof o != 'object') { - var funcStr = o.toString().replace(/^(function )\w*/, '$1'); - var indent = /([ \t]*)\S.*$/.exec(funcStr); - return indent ? funcStr.replace(new RegExp('^' + indent[1], 'mg'), '') : funcStr; - } - var s = []; - for (var i in o) if (i != 'toString') { - if (level == 0) s.push('var ' + i + ' = ' + _stringify(o[i], level + 1) + ';\n'); - else s.push(propname(i) + ': ' + _stringify(o[i], level + 1)); - } - if (level == 0) return s.join(''); - if (s.length == 0) return '{}'; - var indent = ' '; while (--level) indent += ' '; - return '{\n' + s.join(',\n').replace(/^/gm, indent) + '\n}'; - }; - return _stringify(this, 0); - } -}; - - -/** Recursively map an AST to its resulting string - * - * @memberof MessageFormat - * - * @param ast - the Ast node for which the JS code should be generated - * - * @private */ -MessageFormat.prototype._precompile = function(ast, data) { - data = data || { keys: {}, offset: {} }; - var r = [], i, tmp, args = []; - - switch ( ast.type ) { - case 'messageFormatPattern': - for ( i = 0; i < ast.statements.length; ++i ) { - r.push(this._precompile( ast.statements[i], data )); - } - tmp = r.join(' + ') || '""'; - return data.pf_count ? tmp : 'function(d) { return ' + tmp + '; }'; - - case 'messageFormatElement': - data.pf_count = data.pf_count || 0; - if ( ast.output ) { - return propname(ast.argumentIndex, 'd'); - } - else { - data.keys[data.pf_count] = ast.argumentIndex; - return this._precompile( ast.elementFormat, data ); - } - return ''; - - case 'elementFormat': - args = [ propname(data.keys[data.pf_count], 'd') ]; - switch (ast.key) { - case 'select': - args.push(this._precompile(ast.val, data)); - return 'select(' + args.join(', ') + ')'; - case 'selectordinal': - args = args.concat([ 0, propname(this.lc[0], 'pluralFuncs'), this._precompile(ast.val, data), 1 ]); - return 'plural(' + args.join(', ') + ')'; - case 'plural': - data.offset[data.pf_count || 0] = ast.val.offset || 0; - args = args.concat([ data.offset[data.pf_count] || 0, propname(this.lc[0], 'pluralFuncs'), this._precompile(ast.val, data) ]); - return 'plural(' + args.join(', ') + ')'; - default: - if (this.withIntlSupport && !(ast.key in this.runtime.fmt) && (ast.key in MessageFormat.formatters)) { - tmp = MessageFormat.formatters[ast.key]; - this.runtime.fmt[ast.key] = (typeof tmp(this) == 'function') ? tmp(this) : tmp; - } - args.push(JSON.stringify(this.lc)); - if (ast.val && ast.val.length) args.push(JSON.stringify(ast.val.length == 1 ? ast.val[0] : ast.val)); - return 'fmt.' + ast.key + '(' + args.join(', ') + ')'; - } - - case 'pluralFormatPattern': - case 'selectFormatPattern': - data.pf_count = data.pf_count || 0; - if (ast.type == 'selectFormatPattern') data.offset[data.pf_count] = 0; - var needOther = true; - for (i = 0; i < ast.pluralForms.length; ++i) { - var key = ast.pluralForms[i].key; - if (key === 'other') needOther = false; - var data_copy = JSON.parse(JSON.stringify(data)); - data_copy.pf_count++; - r.push(propname(key) + ': function() { return ' + this._precompile(ast.pluralForms[i].val, data_copy) + ';}'); - } - if (needOther) throw new Error("No 'other' form found in " + ast.type + " " + data.pf_count); - return '{ ' + r.join(', ') + ' }'; - - case 'string': - return JSON.stringify(ast.val || ""); - - case 'octothorpe': - if (!data.pf_count) return '"#"'; - args = [ propname(data.keys[data.pf_count-1], 'd') ]; - if (data.offset[data.pf_count-1]) args.push(data.offset[data.pf_count-1]); - return 'number(' + args.join(', ') + ')'; - - default: - throw new Error( 'Bad AST type: ' + ast.type ); - } -}; - -/** Compile messages into an executable function with clean string - * representation. - * - * If `messages` is a single string including ICU MessageFormat declarations, - * `opt` is ignored and the returned function takes a single Object parameter - * `d` representing each of the input's defined variables. The returned - * function will be defined in a local scope that includes all the required - * runtime variables. - * - * If `messages` is a map of keys to strings, or a map of namespace keys to - * such key/string maps, the returned function will fill the specified global - * with javascript functions matching the structure of the input. In such use, - * the output of `compile()` is expected to be serialized using `.toString()`, - * and will include definitions of the runtime functions. If `opt.global` is - * null, calling the output function will return the object itself. - * - * Together, the input parameters should match the following patterns: - * ```js - * messages = "string" || { key0: "string0", key1: "string1", ... } || { - * ns0: { key0: "string0", key1: "string1", ... }, - * ns1: { key0: "string0", key1: "string1", ... }, - * ... - * } - * - * opt = null || { - * locale: null || { - * ns0: "lc0" || [ "lc0", ... ], - * ns1: "lc1" || [ "lc1", ... ], - * ... - * }, - * global: null || "module.exports" || "exports" || "i18n" || ... - * } - * ``` - * - * @memberof MessageFormat - * @param {string|Object} - * messages - The input message(s) to be compiled, in ICU MessageFormat - * @param {Object} [opt={}] - Options controlling output for non-simple intput - * @param {Object} [opt.locale] - The locales to use for the messages, with a - * structure matching that of `messages` - * @param {string} [opt.global=""] - The global variable that the output - * function should use, or a null string for none. "exports" and - * "module.exports" are recognised as special cases. - * @returns {function} The first match found for the given locale(s) - * - * @example - * > var MessageFormat = require('messageformat'), - * ... mf = new MessageFormat('en'), - * ... mfunc0 = mf.compile('A {TYPE} example.'); - * > mfunc0({TYPE:'simple'}) - * 'A simple example.' - * > mfunc0.toString() - * 'function (d) { return "A " + d.TYPE + " example."; }' - * - * @example - * > var msgSet = { a: 'A {TYPE} example.', - * ... b: 'This has {COUNT, plural, one{one member} other{# members}}.' }, - * ... mfuncSet = mf.compile(msgSet); - * > mfuncSet().a({TYPE:'more complex'}) - * 'A more complex example.' - * > mfuncSet().b({COUNT:2}) - * 'This has 2 members.' - * - * > console.log(mfuncSet.toString()) - * function anonymous() { - * var number = function (value, offset) { - * if (isNaN(value)) throw new Error("'" + value + "' isn't a number."); - * return value - (offset || 0); - * }; - * var plural = function (value, offset, lcfunc, data, isOrdinal) { - * if ({}.hasOwnProperty.call(data, value)) return data[value](); - * if (offset) value -= offset; - * var key = lcfunc(value, isOrdinal); - * if (key in data) return data[key](); - * return data.other(); - * }; - * var select = function (value, data) { - * if ({}.hasOwnProperty.call(data, value)) return data[value](); - * return data.other() - * }; - * var pluralFuncs = { - * en: function (n, ord) { - * var s = String(n).split('.'), v0 = !s[1], t0 = Number(s[0]) == n, - * n10 = t0 && s[0].slice(-1), n100 = t0 && s[0].slice(-2); - * if (ord) return (n10 == 1 && n100 != 11) ? 'one' - * : (n10 == 2 && n100 != 12) ? 'two' - * : (n10 == 3 && n100 != 13) ? 'few' - * : 'other'; - * return (n == 1 && v0) ? 'one' : 'other'; - * } - * }; - * var fmt = {}; - * - * return { - * a: function(d) { return "A " + d.TYPE + " example."; }, - * b: function(d) { return "This has " + plural(d.COUNT, 0, pluralFuncs.en, { one: function() { return "one member";}, other: function() { return number(d.COUNT)+" members";} }) + "."; } - * } - * } - * - * @example - * > mf.runtime.pluralFuncs.fi = MessageFormat.plurals.fi; - * > var multiSet = { en: { a: 'A {TYPE} example.', - * ... b: 'This is the {COUNT, selectordinal, one{#st} two{#nd} few{#rd} other{#th}} example.' }, - * ... fi: { a: '{TYPE} esimerkki.', - * ... b: 'Tämä on {COUNT, selectordinal, other{#.}} esimerkki.' } }, - * ... multiSetLocales = { en: 'en', fi: 'fi' }, - * ... mfuncSet = mf.compile(multiSet, { locale: multiSetLocales, global: 'i18n' }); - * > mfuncSet(this); - * > i18n.en.b({COUNT:3}) - * 'This is the 3rd example.' - * > i18n.fi.b({COUNT:3}) - * 'Tämä on 3. esimerkki.' */ -MessageFormat.prototype.compile = function ( messages, opt ) { - var r = {}, lc0 = this.lc, - compileMsg = function(self, msg) { - try { - var ast = MessageFormat._parse(msg); - return self._precompile(ast); - } catch (e) { - throw new Error((ast ? 'Precompiler' : 'Parser') + ' error: ' + e.toString()); - } - }, - stringify = function(r, level) { - if (!level) level = 0; - if (typeof r != 'object') return r; - var o = [], indent = ''; - for (var i = 0; i < level; ++i) indent += ' '; - for (var k in r) o.push('\n' + indent + ' ' + propname(k) + ': ' + stringify(r[k], level + 1)); - return '{' + o.join(',') + '\n' + indent + '}'; - }; - - if (typeof messages == 'string') { - var f = new Function( - 'number, plural, select, pluralFuncs, fmt', - 'return ' + compileMsg(this, messages)); - return f(this.runtime.number, this.runtime.plural, this.runtime.select, - this.runtime.pluralFuncs, this.runtime.fmt); - } - - opt = opt || {}; - - for (var ns in messages) { - if (opt.locale) this.lc = opt.locale[ns] && [].concat(opt.locale[ns]) || lc0; - if (typeof messages[ns] == 'string') { - try { r[ns] = compileMsg(this, messages[ns]); } - catch (e) { e.message = e.message.replace(':', ' with `' + ns + '`:'); throw e; } - } else { - r[ns] = {}; - for (var key in messages[ns]) { - try { r[ns][key] = compileMsg(this, messages[ns][key]); } - catch (e) { e.message = e.message.replace(':', ' with `' + key + '` in `' + ns + '`:'); throw e; } - } - } - } - - this.lc = lc0; - var s = this.runtime.toString() + '\n'; - switch (opt.global || '') { - case 'exports': - var o = []; - for (var k in r) o.push(propname(k, 'exports') + ' = ' + stringify(r[k])); - return new Function(s + o.join(';\n')); - case 'module.exports': - return new Function(s + 'module.exports = ' + stringify(r)); - case '': - return new Function(s + 'return ' + stringify(r)); - default: - return new Function('G', s + propname(opt.global, 'G') + ' = ' + stringify(r)); - } -}; - - -return MessageFormat; -}()); -/* jshint ignore:end */ - - -var validateMessageBundle = function( cldr ) { - validate( - "E_MISSING_MESSAGE_BUNDLE", - "Missing message bundle for locale `{locale}`.", - cldr.attributes.bundle && cldr.get( "globalize-messages/{bundle}" ) !== undefined, - { - locale: cldr.locale - } - ); -}; - - - - -var validateMessagePresence = function( path, value ) { - path = path.join( "/" ); - validate( "E_MISSING_MESSAGE", "Missing required message content `{path}`.", - value !== undefined, { path: path } ); -}; - - - - -var validateMessageType = function( path, value ) { - path = path.join( "/" ); - validate( - "E_INVALID_MESSAGE", - "Invalid message content `{path}`. {expected} expected.", - typeof value === "string", - { - expected: "a string", - path: path - } - ); -}; - - - - -var validateParameterTypeMessageVariables = function( value, name ) { - validateParameterType( - value, - name, - value === undefined || isPlainObject( value ) || Array.isArray( value ), - "Array or Plain Object" - ); -}; - - - - -var validatePluralModulePresence = function() { - validate( "E_MISSING_PLURAL_MODULE", "Plural module not loaded.", - Globalize.plural !== undefined, {} ); -}; - - - - -var slice = [].slice; - -function MessageFormatInit( globalize, cldr ) { - var plural; - return new MessageFormat( cldr.locale, function( value ) { - if ( !plural ) { - validatePluralModulePresence(); - plural = globalize.pluralGenerator(); - } - return plural( value ); - }); -} - -/** - * .loadMessages( json ) - * - * @json [JSON] - * - * Load translation data. - */ -Globalize.loadMessages = function( json ) { - var locale, - customData = { - "globalize-messages": json, - "main": {} - }; - - validateParameterPresence( json, "json" ); - validateParameterTypePlainObject( json, "json" ); - - // Set available bundles by populating customData main dataset. - for ( locale in json ) { - if ( json.hasOwnProperty( locale ) ) { - customData.main[ locale ] = {}; - } - } - - Cldr.load( customData ); -}; - -/** - * .messageFormatter( path ) - * - * @path [String or Array] - * - * Format a message given its path. - */ -Globalize.messageFormatter = -Globalize.prototype.messageFormatter = function( path ) { - var cldr, formatter, message; - - validateParameterPresence( path, "path" ); - validateParameterType( path, "path", typeof path === "string" || Array.isArray( path ), - "a String nor an Array" ); - - path = alwaysArray( path ); - cldr = this.cldr; - - validateDefaultLocale( cldr ); - validateMessageBundle( cldr ); - - message = cldr.get( [ "globalize-messages/{bundle}" ].concat( path ) ); - validateMessagePresence( path, message ); - - // If message is an Array, concatenate it. - if ( Array.isArray( message ) ) { - message = message.join( " " ); - } - validateMessageType( path, message ); - - formatter = MessageFormatInit( this, cldr ).compile( message ); - - return function( variables ) { - if ( typeof variables === "number" || typeof variables === "string" ) { - variables = slice.call( arguments, 0 ); - } - validateParameterTypeMessageVariables( variables, "variables" ); - return formatter( variables ); - }; -}; - -/** - * .formatMessage( path [, variables] ) - * - * @path [String or Array] - * - * @variables [Number, String, Array or Object] - * - * Format a message given its path. - */ -Globalize.formatMessage = -Globalize.prototype.formatMessage = function( path /* , variables */ ) { - return this.messageFormatter( path ).apply( {}, slice.call( arguments, 1 ) ); -}; - -return Globalize; - - - - -})); diff --git a/web/Scripts/globalize/number.js b/web/Scripts/globalize/number.js deleted file mode 100644 index 7ab4256d..00000000 --- a/web/Scripts/globalize/number.js +++ /dev/null @@ -1,1266 +0,0 @@ -/** - * Globalize v1.0.0 - * - * http://github.com/jquery/globalize - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2015-04-23T12:02Z - */ -/*! - * Globalize v1.0.0 2015-04-23T12:02Z Released under the MIT license - * http://git.io/TrdQbw - */ -(function( root, factory ) { - - // UMD returnExports - if ( typeof define === "function" && define.amd ) { - - // AMD - define([ - "cldr", - "../globalize", - "cldr/event", - "cldr/supplemental" - ], factory ); - } else if ( typeof exports === "object" ) { - - // Node, CommonJS - module.exports = factory( require( "cldrjs" ), require( "globalize" ) ); - } else { - - // Global - factory( root.Cldr, root.Globalize ); - } -}(this, function( Cldr, Globalize ) { - -var createError = Globalize._createError, - objectExtend = Globalize._objectExtend, - regexpEscape = Globalize._regexpEscape, - stringPad = Globalize._stringPad, - validateCldr = Globalize._validateCldr, - validateDefaultLocale = Globalize._validateDefaultLocale, - validateParameterPresence = Globalize._validateParameterPresence, - validateParameterRange = Globalize._validateParameterRange, - validateParameterType = Globalize._validateParameterType, - validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject; - - -var createErrorUnsupportedFeature = function( feature ) { - return createError( "E_UNSUPPORTED", "Unsupported {feature}.", { - feature: feature - }); -}; - - - - -var validateParameterTypeNumber = function( value, name ) { - validateParameterType( - value, - name, - value === undefined || typeof value === "number", - "Number" - ); -}; - - - - -var validateParameterTypeString = function( value, name ) { - validateParameterType( - value, - name, - value === undefined || typeof value === "string", - "a string" - ); -}; - - - - -/** - * goupingSeparator( number, primaryGroupingSize, secondaryGroupingSize ) - * - * @number [Number]. - * - * @primaryGroupingSize [Number] - * - * @secondaryGroupingSize [Number] - * - * Return the formatted number with group separator. - */ -var numberFormatGroupingSeparator = function( number, primaryGroupingSize, secondaryGroupingSize ) { - var index, - currentGroupingSize = primaryGroupingSize, - ret = "", - sep = ",", - switchToSecondary = secondaryGroupingSize ? true : false; - - number = String( number ).split( "." ); - index = number[ 0 ].length; - - while ( index > currentGroupingSize ) { - ret = number[ 0 ].slice( index - currentGroupingSize, index ) + - ( ret.length ? sep : "" ) + ret; - index -= currentGroupingSize; - if ( switchToSecondary ) { - currentGroupingSize = secondaryGroupingSize; - switchToSecondary = false; - } - } - - number[ 0 ] = number[ 0 ].slice( 0, index ) + ( ret.length ? sep : "" ) + ret; - return number.join( "." ); -}; - - - - -/** - * integerFractionDigits( number, minimumIntegerDigits, minimumFractionDigits, - * maximumFractionDigits, round, roundIncrement ) - * - * @number [Number] - * - * @minimumIntegerDigits [Number] - * - * @minimumFractionDigits [Number] - * - * @maximumFractionDigits [Number] - * - * @round [Function] - * - * @roundIncrement [Function] - * - * Return the formatted integer and fraction digits. - */ -var numberFormatIntegerFractionDigits = function( number, minimumIntegerDigits, minimumFractionDigits, maximumFractionDigits, round, - roundIncrement ) { - - // Fraction - if ( maximumFractionDigits ) { - - // Rounding - if ( roundIncrement ) { - number = round( number, roundIncrement ); - - // Maximum fraction digits - } else { - number = round( number, { exponent: -maximumFractionDigits } ); - } - - // Minimum fraction digits - if ( minimumFractionDigits ) { - number = String( number ).split( "." ); - number[ 1 ] = stringPad( number[ 1 ] || "", minimumFractionDigits, true ); - number = number.join( "." ); - } - } else { - number = round( number ); - } - - number = String( number ); - - // Minimum integer digits - if ( minimumIntegerDigits ) { - number = number.split( "." ); - number[ 0 ] = stringPad( number[ 0 ], minimumIntegerDigits ); - number = number.join( "." ); - } - - return number; -}; - - - - -/** - * toPrecision( number, precision, round ) - * - * @number (Number) - * - * @precision (Number) significant figures precision (not decimal precision). - * - * @round (Function) - * - * Return number.toPrecision( precision ) using the given round function. - */ -var numberToPrecision = function( number, precision, round ) { - var roundOrder; - - // Get number at two extra significant figure precision. - number = number.toPrecision( precision + 2 ); - - // Then, round it to the required significant figure precision. - roundOrder = Math.ceil( Math.log( Math.abs( number ) ) / Math.log( 10 ) ); - roundOrder -= precision; - - return round( number, { exponent: roundOrder } ); -}; - - - - -/** - * toPrecision( number, minimumSignificantDigits, maximumSignificantDigits, round ) - * - * @number [Number] - * - * @minimumSignificantDigits [Number] - * - * @maximumSignificantDigits [Number] - * - * @round [Function] - * - * Return the formatted significant digits number. - */ -var numberFormatSignificantDigits = function( number, minimumSignificantDigits, maximumSignificantDigits, round ) { - var atMinimum, atMaximum; - - // Sanity check. - if ( minimumSignificantDigits > maximumSignificantDigits ) { - maximumSignificantDigits = minimumSignificantDigits; - } - - atMinimum = numberToPrecision( number, minimumSignificantDigits, round ); - atMaximum = numberToPrecision( number, maximumSignificantDigits, round ); - - // Use atMaximum only if it has more significant digits than atMinimum. - number = +atMinimum === +atMaximum ? atMinimum : atMaximum; - - // Expand integer numbers, eg. 123e5 to 12300. - number = ( +number ).toString( 10 ); - - if ( (/e/).test( number ) ) { - throw createErrorUnsupportedFeature({ - feature: "integers out of (1e21, 1e-7)" - }); - } - - // Add trailing zeros if necessary. - if ( minimumSignificantDigits - number.replace( /^0+|\./g, "" ).length > 0 ) { - number = number.split( "." ); - number[ 1 ] = stringPad( number[ 1 ] || "", minimumSignificantDigits - number[ 0 ].replace( /^0+/, "" ).length, true ); - number = number.join( "." ); - } - - return number; -}; - - - - -/** - * format( number, properties ) - * - * @number [Number]. - * - * @properties [Object] Output of number/format-properties. - * - * Return the formatted number. - * ref: http://www.unicode.org/reports/tr35/tr35-numbers.html - */ -var numberFormat = function( number, properties ) { - var infinitySymbol, maximumFractionDigits, maximumSignificantDigits, minimumFractionDigits, - minimumIntegerDigits, minimumSignificantDigits, nanSymbol, nuDigitsMap, padding, prefix, - primaryGroupingSize, pattern, ret, round, roundIncrement, secondaryGroupingSize, suffix, - symbolMap; - - padding = properties[ 1 ]; - minimumIntegerDigits = properties[ 2 ]; - minimumFractionDigits = properties[ 3 ]; - maximumFractionDigits = properties[ 4 ]; - minimumSignificantDigits = properties[ 5 ]; - maximumSignificantDigits = properties[ 6 ]; - roundIncrement = properties[ 7 ]; - primaryGroupingSize = properties[ 8 ]; - secondaryGroupingSize = properties[ 9 ]; - round = properties[ 15 ]; - infinitySymbol = properties[ 16 ]; - nanSymbol = properties[ 17 ]; - symbolMap = properties[ 18 ]; - nuDigitsMap = properties[ 19 ]; - - // NaN - if ( isNaN( number ) ) { - return nanSymbol; - } - - if ( number < 0 ) { - pattern = properties[ 12 ]; - prefix = properties[ 13 ]; - suffix = properties[ 14 ]; - } else { - pattern = properties[ 11 ]; - prefix = properties[ 0 ]; - suffix = properties[ 10 ]; - } - - // Infinity - if ( !isFinite( number ) ) { - return prefix + infinitySymbol + suffix; - } - - ret = prefix; - - // Percent - if ( pattern.indexOf( "%" ) !== -1 ) { - number *= 100; - - // Per mille - } else if ( pattern.indexOf( "\u2030" ) !== -1 ) { - number *= 1000; - } - - // Significant digit format - if ( !isNaN( minimumSignificantDigits * maximumSignificantDigits ) ) { - number = numberFormatSignificantDigits( number, minimumSignificantDigits, - maximumSignificantDigits, round ); - - // Integer and fractional format - } else { - number = numberFormatIntegerFractionDigits( number, minimumIntegerDigits, - minimumFractionDigits, maximumFractionDigits, round, roundIncrement ); - } - - // Remove the possible number minus sign - number = number.replace( /^-/, "" ); - - // Grouping separators - if ( primaryGroupingSize ) { - number = numberFormatGroupingSeparator( number, primaryGroupingSize, - secondaryGroupingSize ); - } - - ret += number; - - // Scientific notation - // TODO implement here - - // Padding/'([^']|'')+'|''|[.,\-+E%\u2030]/g - // TODO implement here - - ret += suffix; - - return ret.replace( /('([^']|'')+'|'')|./g, function( character, literal ) { - - // Literals - if ( literal ) { - literal = literal.replace( /''/, "'" ); - if ( literal.length > 2 ) { - literal = literal.slice( 1, -1 ); - } - return literal; - } - - // Symbols - character = character.replace( /[.,\-+E%\u2030]/, function( symbol ) { - return symbolMap[ symbol ]; - }); - - // Numbering system - if ( nuDigitsMap ) { - character = character.replace( /[0-9]/, function( digit ) { - return nuDigitsMap[ +digit ]; - }); - } - - return character; - }); -}; - - - - -/** - * NumberingSystem( cldr ) - * - * - http://www.unicode.org/reports/tr35/tr35-numbers.html#otherNumberingSystems - * - http://cldr.unicode.org/index/bcp47-extension - * - http://www.unicode.org/reports/tr35/#u_Extension - */ -var numberNumberingSystem = function( cldr ) { - var nu = cldr.attributes[ "u-nu" ]; - - if ( nu ) { - if ( nu === "traditio" ) { - nu = "traditional"; - } - if ( [ "native", "traditional", "finance" ].indexOf( nu ) !== -1 ) { - - // Unicode locale extension `u-nu` is set using either (native, traditional or - // finance). So, lookup the respective locale's numberingSystem and return it. - return cldr.main([ "numbers/otherNumberingSystems", nu ]); - } - - // Unicode locale extension `u-nu` is set with an explicit numberingSystem. Return it. - return nu; - } - - // Return the default numberingSystem. - return cldr.main( "numbers/defaultNumberingSystem" ); -}; - - - - -/** - * nuMap( cldr ) - * - * @cldr [Cldr instance]. - * - * Return digits map if numbering system is different than `latn`. - */ -var numberNumberingSystemDigitsMap = function( cldr ) { - var aux, - nu = numberNumberingSystem( cldr ); - - if ( nu === "latn" ) { - return; - } - - aux = cldr.supplemental([ "numberingSystems", nu ]); - - if ( aux._type !== "numeric" ) { - throw createErrorUnsupportedFeature( "`" + aux._type + "` numbering system" ); - } - - return aux._digits; -}; - - - - -/** - * EBNF representation: - * - * number_pattern_re = prefix? - * padding? - * (integer_fraction_pattern | significant_pattern) - * scientific_notation? - * suffix? - * - * prefix = non_number_stuff - * - * padding = "*" regexp(.) - * - * integer_fraction_pattern = integer_pattern - * fraction_pattern? - * - * integer_pattern = regexp([#,]*[0,]*0+) - * - * fraction_pattern = "." regexp(0*[0-9]*#*) - * - * significant_pattern = regexp([#,]*@+#*) - * - * scientific_notation = regexp(E\+?0+) - * - * suffix = non_number_stuff - * - * non_number_stuff = regexp(('[^']+'|''|[^*#@0,.E])*) - * - * - * Regexp groups: - * - * 0: number_pattern_re - * 1: prefix - * 2: - - * 3: padding - * 4: (integer_fraction_pattern | significant_pattern) - * 5: integer_fraction_pattern - * 6: integer_pattern - * 7: fraction_pattern - * 8: significant_pattern - * 9: scientific_notation - * 10: suffix - * 11: - - */ -var numberPatternRe = (/^(('[^']+'|''|[^*#@0,.E])*)(\*.)?((([#,]*[0,]*0+)(\.0*[0-9]*#*)?)|([#,]*@+#*))(E\+?0+)?(('[^']+'|''|[^*#@0,.E])*)$/); - - - - -/** - * format( number, pattern ) - * - * @number [Number]. - * - * @pattern [String] raw pattern for numbers. - * - * Return the formatted number. - * ref: http://www.unicode.org/reports/tr35/tr35-numbers.html - */ -var numberPatternProperties = function( pattern ) { - var aux1, aux2, fractionPattern, integerFractionOrSignificantPattern, integerPattern, - maximumFractionDigits, maximumSignificantDigits, minimumFractionDigits, - minimumIntegerDigits, minimumSignificantDigits, padding, prefix, primaryGroupingSize, - roundIncrement, scientificNotation, secondaryGroupingSize, significantPattern, suffix; - - pattern = pattern.match( numberPatternRe ); - if ( !pattern ) { - throw new Error( "Invalid pattern: " + pattern ); - } - - prefix = pattern[ 1 ]; - padding = pattern[ 3 ]; - integerFractionOrSignificantPattern = pattern[ 4 ]; - significantPattern = pattern[ 8 ]; - scientificNotation = pattern[ 9 ]; - suffix = pattern[ 10 ]; - - // Significant digit format - if ( significantPattern ) { - significantPattern.replace( /(@+)(#*)/, function( match, minimumSignificantDigitsMatch, maximumSignificantDigitsMatch ) { - minimumSignificantDigits = minimumSignificantDigitsMatch.length; - maximumSignificantDigits = minimumSignificantDigits + - maximumSignificantDigitsMatch.length; - }); - - // Integer and fractional format - } else { - fractionPattern = pattern[ 7 ]; - integerPattern = pattern[ 6 ]; - - if ( fractionPattern ) { - - // Minimum fraction digits, and rounding. - fractionPattern.replace( /[0-9]+/, function( match ) { - minimumFractionDigits = match; - }); - if ( minimumFractionDigits ) { - roundIncrement = +( "0." + minimumFractionDigits ); - minimumFractionDigits = minimumFractionDigits.length; - } else { - minimumFractionDigits = 0; - } - - // Maximum fraction digits - // 1: ignore decimal character - maximumFractionDigits = fractionPattern.length - 1 /* 1 */; - } - - // Minimum integer digits - integerPattern.replace( /0+$/, function( match ) { - minimumIntegerDigits = match.length; - }); - } - - // Scientific notation - if ( scientificNotation ) { - throw createErrorUnsupportedFeature({ - feature: "scientific notation (not implemented)" - }); - } - - // Padding - if ( padding ) { - throw createErrorUnsupportedFeature({ - feature: "padding (not implemented)" - }); - } - - // Grouping - if ( ( aux1 = integerFractionOrSignificantPattern.lastIndexOf( "," ) ) !== -1 ) { - - // Primary grouping size is the interval between the last group separator and the end of - // the integer (or the end of the significant pattern). - aux2 = integerFractionOrSignificantPattern.split( "." )[ 0 ]; - primaryGroupingSize = aux2.length - aux1 - 1; - - // Secondary grouping size is the interval between the last two group separators. - if ( ( aux2 = integerFractionOrSignificantPattern.lastIndexOf( ",", aux1 - 1 ) ) !== -1 ) { - secondaryGroupingSize = aux1 - 1 - aux2; - } - } - - // Return: - // 0: @prefix String - // 1: @padding Array [ , ] TODO - // 2: @minimumIntegerDigits non-negative integer Number value indicating the minimum integer - // digits to be used. Numbers will be padded with leading zeroes if necessary. - // 3: @minimumFractionDigits and - // 4: @maximumFractionDigits are non-negative integer Number values indicating the minimum and - // maximum fraction digits to be used. Numbers will be rounded or padded with trailing - // zeroes if necessary. - // 5: @minimumSignificantDigits and - // 6: @maximumSignificantDigits are positive integer Number values indicating the minimum and - // maximum fraction digits to be shown. Either none or both of these properties are - // present; if they are, they override minimum and maximum integer and fraction digits - // – the formatter uses however many integer and fraction digits are required to display - // the specified number of significant digits. - // 7: @roundIncrement Decimal round increment or null - // 8: @primaryGroupingSize - // 9: @secondaryGroupingSize - // 10: @suffix String - return [ - prefix, - padding, - minimumIntegerDigits, - minimumFractionDigits, - maximumFractionDigits, - minimumSignificantDigits, - maximumSignificantDigits, - roundIncrement, - primaryGroupingSize, - secondaryGroupingSize, - suffix - ]; -}; - - - - -/** - * Symbol( name, cldr ) - * - * @name [String] Symbol name. - * - * @cldr [Cldr instance]. - * - * Return the localized symbol given its name. - */ -var numberSymbol = function( name, cldr ) { - return cldr.main([ - "numbers/symbols-numberSystem-" + numberNumberingSystem( cldr ), - name - ]); -}; - - - - -var numberSymbolName = { - ".": "decimal", - ",": "group", - "%": "percentSign", - "+": "plusSign", - "-": "minusSign", - "E": "exponential", - "\u2030": "perMille" -}; - - - - -/** - * symbolMap( cldr ) - * - * @cldr [Cldr instance]. - * - * Return the (localized symbol, pattern symbol) key value pair, eg. { - * ".": "٫", - * ",": "٬", - * "%": "٪", - * ... - * }; - */ -var numberSymbolMap = function( cldr ) { - var symbol, - symbolMap = {}; - - for ( symbol in numberSymbolName ) { - symbolMap[ symbol ] = numberSymbol( numberSymbolName[ symbol ], cldr ); - } - - return symbolMap; -}; - - - - -var numberTruncate = function( value ) { - if ( isNaN( value ) ) { - return NaN; - } - return Math[ value < 0 ? "ceil" : "floor" ]( value ); -}; - - - - -/** - * round( method ) - * - * @method [String] with either "round", "ceil", "floor", or "truncate". - * - * Return function( value, incrementOrExp ): - * - * @value [Number] eg. 123.45. - * - * @incrementOrExp [Number] optional, eg. 0.1; or - * [Object] Either { increment: } or { exponent: } - * - * Return the rounded number, eg: - * - round( "round" )( 123.45 ): 123; - * - round( "ceil" )( 123.45 ): 124; - * - round( "floor" )( 123.45 ): 123; - * - round( "truncate" )( 123.45 ): 123; - * - round( "round" )( 123.45, 0.1 ): 123.5; - * - round( "round" )( 123.45, 10 ): 120; - * - * Based on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round - * Ref: #376 - */ -var numberRound = function( method ) { - method = method || "round"; - method = method === "truncate" ? numberTruncate : Math[ method ]; - - return function( value, incrementOrExp ) { - var exp, increment; - - value = +value; - - // If the value is not a number, return NaN. - if ( isNaN( value ) ) { - return NaN; - } - - // Exponent given. - if ( typeof incrementOrExp === "object" && incrementOrExp.exponent ) { - exp = +incrementOrExp.exponent; - increment = 1; - - if ( exp === 0 ) { - return method( value ); - } - - // If the exp is not an integer, return NaN. - if ( !( typeof exp === "number" && exp % 1 === 0 ) ) { - return NaN; - } - - // Increment given. - } else { - increment = +incrementOrExp || 1; - - if ( increment === 1 ) { - return method( value ); - } - - // If the increment is not a number, return NaN. - if ( isNaN( increment ) ) { - return NaN; - } - - increment = increment.toExponential().split( "e" ); - exp = +increment[ 1 ]; - increment = +increment[ 0 ]; - } - - // Shift & Round - value = value.toString().split( "e" ); - value[ 0 ] = +value[ 0 ] / increment; - value[ 1 ] = value[ 1 ] ? ( +value[ 1 ] - exp ) : -exp; - value = method( +(value[ 0 ] + "e" + value[ 1 ] ) ); - - // Shift back - value = value.toString().split( "e" ); - value[ 0 ] = +value[ 0 ] * increment; - value[ 1 ] = value[ 1 ] ? ( +value[ 1 ] + exp ) : exp; - return +( value[ 0 ] + "e" + value[ 1 ] ); - }; -}; - - - - -/** - * formatProperties( pattern, cldr [, options] ) - * - * @pattern [String] raw pattern for numbers. - * - * @cldr [Cldr instance]. - * - * @options [Object]: - * - minimumIntegerDigits [Number] - * - minimumFractionDigits, maximumFractionDigits [Number] - * - minimumSignificantDigits, maximumSignificantDigits [Number] - * - round [String] "ceil", "floor", "round" (default), or "truncate". - * - useGrouping [Boolean] default true. - * - * Return the processed properties that will be used in number/format. - * ref: http://www.unicode.org/reports/tr35/tr35-numbers.html - */ -var numberFormatProperties = function( pattern, cldr, options ) { - var negativePattern, negativePrefix, negativeProperties, negativeSuffix, positivePattern, - properties; - - function getOptions( attribute, propertyIndex ) { - if ( attribute in options ) { - properties[ propertyIndex ] = options[ attribute ]; - } - } - - options = options || {}; - pattern = pattern.split( ";" ); - - positivePattern = pattern[ 0 ]; - - negativePattern = pattern[ 1 ] || "-" + positivePattern; - negativeProperties = numberPatternProperties( negativePattern ); - negativePrefix = negativeProperties[ 0 ]; - negativeSuffix = negativeProperties[ 10 ]; - - properties = numberPatternProperties( positivePattern ).concat([ - positivePattern, - negativePrefix + positivePattern + negativeSuffix, - negativePrefix, - negativeSuffix, - numberRound( options.round ), - numberSymbol( "infinity", cldr ), - numberSymbol( "nan", cldr ), - numberSymbolMap( cldr ), - numberNumberingSystemDigitsMap( cldr ) - ]); - - getOptions( "minimumIntegerDigits", 2 ); - getOptions( "minimumFractionDigits", 3 ); - getOptions( "maximumFractionDigits", 4 ); - getOptions( "minimumSignificantDigits", 5 ); - getOptions( "maximumSignificantDigits", 6 ); - - // Grouping separators - if ( options.useGrouping === false ) { - properties[ 8 ] = null; - } - - // Normalize number of digits if only one of either minimumFractionDigits or - // maximumFractionDigits is passed in as an option - if ( "minimumFractionDigits" in options && !( "maximumFractionDigits" in options ) ) { - // maximumFractionDigits = Math.max( minimumFractionDigits, maximumFractionDigits ); - properties[ 4 ] = Math.max( properties[ 3 ], properties[ 4 ] ); - } else if ( !( "minimumFractionDigits" in options ) && - "maximumFractionDigits" in options ) { - // minimumFractionDigits = Math.min( minimumFractionDigits, maximumFractionDigits ); - properties[ 3 ] = Math.min( properties[ 3 ], properties[ 4 ] ); - } - - // Return: - // 0-10: see number/pattern-properties. - // 11: @positivePattern [String] Positive pattern. - // 12: @negativePattern [String] Negative pattern. - // 13: @negativePrefix [String] Negative prefix. - // 14: @negativeSuffix [String] Negative suffix. - // 15: @round [Function] Round function. - // 16: @infinitySymbol [String] Infinity symbol. - // 17: @nanSymbol [String] NaN symbol. - // 18: @symbolMap [Object] A bunch of other symbols. - // 19: @nuDigitsMap [Array] Digits map if numbering system is different than `latn`. - return properties; -}; - - - - -/** - * EBNF representation: - * - * number_pattern_re = prefix_including_padding? - * number - * scientific_notation? - * suffix? - * - * number = integer_including_group_separator fraction_including_decimal_separator - * - * integer_including_group_separator = - * regexp([0-9,]*[0-9]+) - * - * fraction_including_decimal_separator = - * regexp((\.[0-9]+)?) - - * prefix_including_padding = non_number_stuff - * - * scientific_notation = regexp(E[+-]?[0-9]+) - * - * suffix = non_number_stuff - * - * non_number_stuff = regexp([^0-9]*) - * - * - * Regexp groups: - * - * 0: number_pattern_re - * 1: prefix - * 2: integer_including_group_separator fraction_including_decimal_separator - * 3: integer_including_group_separator - * 4: fraction_including_decimal_separator - * 5: scientific_notation - * 6: suffix - */ -var numberNumberRe = (/^([^0-9]*)(([0-9,]*[0-9]+)(\.[0-9]+)?)(E[+-]?[0-9]+)?([^0-9]*)$/); - - - - -/** - * parse( value, properties ) - * - * @value [String]. - * - * @properties [Object] Parser properties is a reduced pre-processed cldr - * data set returned by numberParserProperties(). - * - * Return the parsed Number (including Infinity) or NaN when value is invalid. - * ref: http://www.unicode.org/reports/tr35/tr35-numbers.html - */ -var numberParse = function( value, properties ) { - var aux, infinitySymbol, invertedNuDigitsMap, invertedSymbolMap, localizedDigitRe, - localizedSymbolsRe, negativePrefix, negativeSuffix, number, prefix, suffix; - - infinitySymbol = properties[ 0 ]; - invertedSymbolMap = properties[ 1 ]; - negativePrefix = properties[ 2 ]; - negativeSuffix = properties[ 3 ]; - invertedNuDigitsMap = properties[ 4 ]; - - // Infinite number. - if ( aux = value.match( infinitySymbol ) ) { - - number = Infinity; - prefix = value.slice( 0, aux.length ); - suffix = value.slice( aux.length + 1 ); - - // Finite number. - } else { - - // TODO: Create it during setup, i.e., make it a property. - localizedSymbolsRe = new RegExp( - Object.keys( invertedSymbolMap ).map(function( localizedSymbol ) { - return regexpEscape( localizedSymbol ); - }).join( "|" ), - "g" - ); - - // Reverse localized symbols. - value = value.replace( localizedSymbolsRe, function( localizedSymbol ) { - return invertedSymbolMap[ localizedSymbol ]; - }); - - // Reverse localized numbering system. - if ( invertedNuDigitsMap ) { - - // TODO: Create it during setup, i.e., make it a property. - localizedDigitRe = new RegExp( - Object.keys( invertedNuDigitsMap ).map(function( localizedDigit ) { - return regexpEscape( localizedDigit ); - }).join( "|" ), - "g" - ); - value = value.replace( localizedDigitRe, function( localizedDigit ) { - return invertedNuDigitsMap[ localizedDigit ]; - }); - } - - // Is it a valid number? - value = value.match( numberNumberRe ); - if ( !value ) { - - // Invalid number. - return NaN; - } - - prefix = value[ 1 ]; - suffix = value[ 6 ]; - - // Remove grouping separators. - number = value[ 2 ].replace( /,/g, "" ); - - // Scientific notation - if ( value[ 5 ] ) { - number += value[ 5 ]; - } - - number = +number; - - // Is it a valid number? - if ( isNaN( number ) ) { - - // Invalid number. - return NaN; - } - - // Percent - if ( value[ 0 ].indexOf( "%" ) !== -1 ) { - number /= 100; - suffix = suffix.replace( "%", "" ); - - // Per mille - } else if ( value[ 0 ].indexOf( "\u2030" ) !== -1 ) { - number /= 1000; - suffix = suffix.replace( "\u2030", "" ); - } - } - - // Negative number - // "If there is an explicit negative subpattern, it serves only to specify the negative prefix - // and suffix. If there is no explicit negative subpattern, the negative subpattern is the - // localized minus sign prefixed to the positive subpattern" UTS#35 - if ( prefix === negativePrefix && suffix === negativeSuffix ) { - number *= -1; - } - - return number; -}; - - - - -/** - * symbolMap( cldr ) - * - * @cldr [Cldr instance]. - * - * Return the (localized symbol, pattern symbol) key value pair, eg. { - * "٫": ".", - * "٬": ",", - * "٪": "%", - * ... - * }; - */ -var numberSymbolInvertedMap = function( cldr ) { - var symbol, - symbolMap = {}; - - for ( symbol in numberSymbolName ) { - symbolMap[ numberSymbol( numberSymbolName[ symbol ], cldr ) ] = symbol; - } - - return symbolMap; -}; - - - - -/** - * parseProperties( pattern, cldr ) - * - * @pattern [String] raw pattern for numbers. - * - * @cldr [Cldr instance]. - * - * Return parser properties, used to feed parser function. - */ -var numberParseProperties = function( pattern, cldr ) { - var invertedNuDigitsMap, invertedNuDigitsMapSanityCheck, negativePattern, negativeProperties, - nuDigitsMap = numberNumberingSystemDigitsMap( cldr ); - - pattern = pattern.split( ";" ); - negativePattern = pattern[ 1 ] || "-" + pattern[ 0 ]; - negativeProperties = numberPatternProperties( negativePattern ); - if ( nuDigitsMap ) { - invertedNuDigitsMap = nuDigitsMap.split( "" ).reduce(function( object, localizedDigit, i ) { - object[ localizedDigit ] = String( i ); - return object; - }, {} ); - invertedNuDigitsMapSanityCheck = "0123456789".split( "" ).reduce(function( object, digit ) { - object[ digit ] = "invalid"; - return object; - }, {} ); - invertedNuDigitsMap = objectExtend( - invertedNuDigitsMapSanityCheck, - invertedNuDigitsMap - ); - } - - // 0: @infinitySymbol [String] Infinity symbol. - // 1: @invertedSymbolMap [Object] Inverted symbol map augmented with sanity check. - // The sanity check prevents permissive parsing, i.e., it prevents symbols that doesn't - // belong to the localized set to pass through. This is obtained with the result of the - // inverted map object overloading symbol name map object (the remaining symbol name - // mappings will invalidate parsing, working as the sanity check). - // 2: @negativePrefix [String] Negative prefix. - // 3: @negativeSuffix [String] Negative suffix with percent or per mille stripped out. - // 4: @invertedNuDigitsMap [Object] Inverted digits map if numbering system is different than - // `latn` augmented with sanity check (similar to invertedSymbolMap). - return [ - numberSymbol( "infinity", cldr ), - objectExtend( {}, numberSymbolName, numberSymbolInvertedMap( cldr ) ), - negativeProperties[ 0 ], - negativeProperties[ 10 ].replace( "%", "" ).replace( "\u2030", "" ), - invertedNuDigitsMap - ]; -}; - - - - -/** - * Pattern( style ) - * - * @style [String] "decimal" (default) or "percent". - * - * @cldr [Cldr instance]. - */ -var numberPattern = function( style, cldr ) { - if ( style !== "decimal" && style !== "percent" ) { - throw new Error( "Invalid style" ); - } - - return cldr.main([ - "numbers", - style + "Formats-numberSystem-" + numberNumberingSystem( cldr ), - "standard" - ]); -}; - - - - -/** - * .numberFormatter( [options] ) - * - * @options [Object]: - * - style: [String] "decimal" (default) or "percent". - * - see also number/format options. - * - * Return a function that formats a number according to the given options and default/instance - * locale. - */ -Globalize.numberFormatter = -Globalize.prototype.numberFormatter = function( options ) { - var cldr, maximumFractionDigits, maximumSignificantDigits, minimumFractionDigits, - minimumIntegerDigits, minimumSignificantDigits, pattern, properties; - - validateParameterTypePlainObject( options, "options" ); - - options = options || {}; - cldr = this.cldr; - - validateDefaultLocale( cldr ); - - cldr.on( "get", validateCldr ); - - if ( options.raw ) { - pattern = options.raw; - } else { - pattern = numberPattern( options.style || "decimal", cldr ); - } - - properties = numberFormatProperties( pattern, cldr, options ); - - cldr.off( "get", validateCldr ); - - minimumIntegerDigits = properties[ 2 ]; - minimumFractionDigits = properties[ 3 ]; - maximumFractionDigits = properties[ 4 ]; - - minimumSignificantDigits = properties[ 5 ]; - maximumSignificantDigits = properties[ 6 ]; - - // Validate significant digit format properties - if ( !isNaN( minimumSignificantDigits * maximumSignificantDigits ) ) { - validateParameterRange( minimumSignificantDigits, "minimumSignificantDigits", 1, 21 ); - validateParameterRange( maximumSignificantDigits, "maximumSignificantDigits", - minimumSignificantDigits, 21 ); - - } else if ( !isNaN( minimumSignificantDigits ) || !isNaN( maximumSignificantDigits ) ) { - throw new Error( "Neither or both the minimum and maximum significant digits must be " + - "present" ); - - // Validate integer and fractional format - } else { - validateParameterRange( minimumIntegerDigits, "minimumIntegerDigits", 1, 21 ); - validateParameterRange( minimumFractionDigits, "minimumFractionDigits", 0, 20 ); - validateParameterRange( maximumFractionDigits, "maximumFractionDigits", - minimumFractionDigits, 20 ); - } - - return function( value ) { - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - return numberFormat( value, properties ); - }; -}; - -/** - * .numberParser( [options] ) - * - * @options [Object]: - * - style: [String] "decimal" (default) or "percent". - * - * Return the number parser according to the default/instance locale. - */ -Globalize.numberParser = -Globalize.prototype.numberParser = function( options ) { - var cldr, pattern, properties; - - validateParameterTypePlainObject( options, "options" ); - - options = options || {}; - cldr = this.cldr; - - validateDefaultLocale( cldr ); - - cldr.on( "get", validateCldr ); - - if ( options.raw ) { - pattern = options.raw; - } else { - pattern = numberPattern( options.style || "decimal", cldr ); - } - - properties = numberParseProperties( pattern, cldr ); - - cldr.off( "get", validateCldr ); - - return function( value ) { - validateParameterPresence( value, "value" ); - validateParameterTypeString( value, "value" ); - return numberParse( value, properties ); - }; -}; - -/** - * .formatNumber( value [, options] ) - * - * @value [Number] number to be formatted. - * - * @options [Object]: see number/format-properties. - * - * Format a number according to the given options and default/instance locale. - */ -Globalize.formatNumber = -Globalize.prototype.formatNumber = function( value, options ) { - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - - return this.numberFormatter( options )( value ); -}; - -/** - * .parseNumber( value [, options] ) - * - * @value [String] - * - * @options [Object]: See numberParser(). - * - * Return the parsed Number (including Infinity) or NaN when value is invalid. - */ -Globalize.parseNumber = -Globalize.prototype.parseNumber = function( value, options ) { - validateParameterPresence( value, "value" ); - validateParameterTypeString( value, "value" ); - - return this.numberParser( options )( value ); -}; - -/** - * Optimization to avoid duplicating some internal functions across modules. - */ -Globalize._createErrorUnsupportedFeature = createErrorUnsupportedFeature; -Globalize._numberNumberingSystem = numberNumberingSystem; -Globalize._numberPattern = numberPattern; -Globalize._numberSymbol = numberSymbol; -Globalize._stringPad = stringPad; -Globalize._validateParameterTypeNumber = validateParameterTypeNumber; -Globalize._validateParameterTypeString = validateParameterTypeString; - -return Globalize; - - - - -})); diff --git a/web/Scripts/globalize/plural.js b/web/Scripts/globalize/plural.js deleted file mode 100644 index cd4c4cff..00000000 --- a/web/Scripts/globalize/plural.js +++ /dev/null @@ -1,359 +0,0 @@ -/** - * Globalize v1.0.0 - * - * http://github.com/jquery/globalize - * - * Copyright jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2015-04-23T12:02Z - */ -/*! - * Globalize v1.0.0 2015-04-23T12:02Z Released under the MIT license - * http://git.io/TrdQbw - */ -(function( root, factory ) { - - // UMD returnExports - if ( typeof define === "function" && define.amd ) { - - // AMD - define([ - "cldr", - "../globalize", - "cldr/event", - "cldr/supplemental" - ], factory ); - } else if ( typeof exports === "object" ) { - - // Node, CommonJS - module.exports = factory( require( "cldrjs" ), require( "globalize" ) ); - } else { - - // Global - factory( root.Cldr, root.Globalize ); - } -}(this, function( Cldr, Globalize ) { - -var validateCldr = Globalize._validateCldr, - validateDefaultLocale = Globalize._validateDefaultLocale, - validateParameterPresence = Globalize._validateParameterPresence, - validateParameterType = Globalize._validateParameterType, - validateParameterTypePlainObject = Globalize._validateParameterTypePlainObject; -var MakePlural; -/* jshint ignore:start */ -MakePlural = (function() { - - -var _toArray = function (arr) { return Array.isArray(arr) ? arr : Array.from(arr); }; - -var _toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; - -var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }; - -var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - - -/** - * make-plural.js -- https://github.com/eemeli/make-plural.js/ - * Copyright (c) 2014-2015 by Eemeli Aro - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * The software is provided "as is" and the author disclaims all warranties - * with regard to this software including all implied warranties of - * merchantability and fitness. In no event shall the author be liable for - * any special, direct, indirect, or consequential damages or any damages - * whatsoever resulting from loss of use, data or profits, whether in an - * action of contract, negligence or other tortious action, arising out of - * or in connection with the use or performance of this software. - */ - -var Parser = (function () { - function Parser() { - _classCallCheck(this, Parser); - } - - _createClass(Parser, [{ - key: 'parse', - value: function parse(cond) { - var _this = this; - - if (cond === 'i = 0 or n = 1') { - return 'n >= 0 && n <= 1'; - }if (cond === 'i = 0,1') { - return 'n >= 0 && n < 2'; - }if (cond === 'i = 1 and v = 0') { - this.v0 = 1; - return 'n == 1 && v0'; - } - return cond.replace(/([tv]) (!?)= 0/g, function (m, sym, noteq) { - var sn = sym + '0'; - _this[sn] = 1; - return noteq ? '!' + sn : sn; - }).replace(/\b[fintv]\b/g, function (m) { - _this[m] = 1; - return m; - }).replace(/([fin]) % (10+)/g, function (m, sym, num) { - var sn = sym + num; - _this[sn] = 1; - return sn; - }).replace(/n10+ = 0/g, 't0 && $&').replace(/(\w+ (!?)= )([0-9.]+,[0-9.,]+)/g, function (m, se, noteq, x) { - if (m === 'n = 0,1') return '(n == 0 || n == 1)'; - if (noteq) return se + x.split(',').join(' && ' + se); - return '(' + se + x.split(',').join(' || ' + se) + ')'; - }).replace(/(\w+) (!?)= ([0-9]+)\.\.([0-9]+)/g, function (m, sym, noteq, x0, x1) { - if (Number(x0) + 1 === Number(x1)) { - if (noteq) return '' + sym + ' != ' + x0 + ' && ' + sym + ' != ' + x1; - return '(' + sym + ' == ' + x0 + ' || ' + sym + ' == ' + x1 + ')'; - } - if (noteq) return '(' + sym + ' < ' + x0 + ' || ' + sym + ' > ' + x1 + ')'; - if (sym === 'n') { - _this.t0 = 1;return '(t0 && n >= ' + x0 + ' && n <= ' + x1 + ')'; - } - return '(' + sym + ' >= ' + x0 + ' && ' + sym + ' <= ' + x1 + ')'; - }).replace(/ and /g, ' && ').replace(/ or /g, ' || ').replace(/ = /g, ' == '); - } - }, { - key: 'vars', - value: (function (_vars) { - function vars() { - return _vars.apply(this, arguments); - } - - vars.toString = function () { - return _vars.toString(); - }; - - return vars; - })(function () { - var vars = []; - if (this.i) vars.push('i = s[0]'); - if (this.f || this.v) vars.push('f = s[1] || \'\''); - if (this.t) vars.push('t = (s[1] || \'\').replace(/0+$/, \'\')'); - if (this.v) vars.push('v = f.length'); - if (this.v0) vars.push('v0 = !s[1]'); - if (this.t0 || this.n10 || this.n100) vars.push('t0 = Number(s[0]) == n'); - for (var k in this) { - if (/^.10+$/.test(k)) { - var k0 = k[0] === 'n' ? 't0 && s[0]' : k[0]; - vars.push('' + k + ' = ' + k0 + '.slice(-' + k.substr(2).length + ')'); - } - }if (!vars.length) return ''; - return 'var ' + ['s = String(n).split(\'.\')'].concat(vars).join(', '); - }) - }]); - - return Parser; -})(); - - - -var MakePlural = (function () { - function MakePlural(lc) { - var _ref = arguments[1] === undefined ? MakePlural : arguments[1]; - - var cardinals = _ref.cardinals; - var ordinals = _ref.ordinals; - - _classCallCheck(this, MakePlural); - - if (!cardinals && !ordinals) throw new Error('At least one type of plural is required'); - this.lc = lc; - this.categories = { cardinal: [], ordinal: [] }; - this.parser = new Parser(); - - this.fn = this.buildFunction(cardinals, ordinals); - this.fn._obj = this; - this.fn.categories = this.categories; - - this.fn.toString = this.fnToString.bind(this); - return this.fn; - } - - _createClass(MakePlural, [{ - key: 'compile', - value: function compile(type, req) { - var cases = []; - var rules = MakePlural.rules[type][this.lc]; - if (!rules) { - if (req) throw new Error('Locale "' + this.lc + '" ' + type + ' rules not found'); - this.categories[type] = ['other']; - return '\'other\''; - } - for (var r in rules) { - var _rules$r$trim$split = rules[r].trim().split(/\s*@\w*/); - - var _rules$r$trim$split2 = _toArray(_rules$r$trim$split); - - var cond = _rules$r$trim$split2[0]; - var examples = _rules$r$trim$split2.slice(1); - var cat = r.replace('pluralRule-count-', ''); - if (cond) cases.push([this.parser.parse(cond), cat]); - - } - this.categories[type] = cases.map(function (c) { - return c[1]; - }).concat('other'); - if (cases.length === 1) { - return '(' + cases[0][0] + ') ? \'' + cases[0][1] + '\' : \'other\''; - } else { - return [].concat(_toConsumableArray(cases.map(function (c) { - return '(' + c[0] + ') ? \'' + c[1] + '\''; - })), ['\'other\'']).join('\n : '); - } - } - }, { - key: 'buildFunction', - value: function buildFunction(cardinals, ordinals) { - var _this3 = this; - - var compile = function compile(c) { - return c ? (c[1] ? 'return ' : 'if (ord) return ') + _this3.compile.apply(_this3, _toConsumableArray(c)) : ''; - }, - fold = { vars: function vars(str) { - return (' ' + str + ';').replace(/(.{1,78})(,|$) ?/g, '$1$2\n '); - }, - cond: function cond(str) { - return (' ' + str + ';').replace(/(.{1,78}) (\|\| |$) ?/gm, '$1\n $2'); - } }, - cond = [ordinals && ['ordinal', !cardinals], cardinals && ['cardinal', true]].map(compile).map(fold.cond), - body = [fold.vars(this.parser.vars())].concat(_toConsumableArray(cond)).join('\n').replace(/\s+$/gm, '').replace(/^[\s;]*[\r\n]+/gm, ''), - args = ordinals && cardinals ? 'n, ord' : 'n'; - return new Function(args, body); - } - }, { - key: 'fnToString', - value: function fnToString(name) { - return Function.prototype.toString.call(this.fn).replace(/^function( \w+)?/, name ? 'function ' + name : 'function').replace('\n/**/', ''); - } - }], [{ - key: 'load', - value: function load() { - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - args.forEach(function (cldr) { - var data = cldr && cldr.supplemental || null; - if (!data) throw new Error('Data does not appear to be CLDR data'); - MakePlural.rules = { - cardinal: data['plurals-type-cardinal'] || MakePlural.rules.cardinal, - ordinal: data['plurals-type-ordinal'] || MakePlural.rules.ordinal - }; - }); - return MakePlural; - } - }]); - - return MakePlural; -})(); - - - -MakePlural.cardinals = true; -MakePlural.ordinals = false; -MakePlural.rules = { cardinal: {}, ordinal: {} }; - - -return MakePlural; -}()); -/* jshint ignore:end */ - - -var validateParameterTypeNumber = function( value, name ) { - validateParameterType( - value, - name, - value === undefined || typeof value === "number", - "Number" - ); -}; - - - - -var validateParameterTypePluralType = function( value, name ) { - validateParameterType( - value, - name, - value === undefined || value === "cardinal" || value === "ordinal", - "String \"cardinal\" or \"ordinal\"" - ); -}; - - - - -/** - * .plural( value ) - * - * @value [Number] - * - * Return the corresponding form (zero | one | two | few | many | other) of a - * value given locale. - */ -Globalize.plural = -Globalize.prototype.plural = function( value, options ) { - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - return this.pluralGenerator( options )( value ); -}; - -/** - * .pluralGenerator( [options] ) - * - * Return a plural function (of the form below). - * - * fn( value ) - * - * @value [Number] - * - * Return the corresponding form (zero | one | two | few | many | other) of a value given the - * default/instance locale. - */ -Globalize.pluralGenerator = -Globalize.prototype.pluralGenerator = function( options ) { - var cldr, isOrdinal, plural, type; - - validateParameterTypePlainObject( options, "options" ); - - options = options || {}; - type = options.type || "cardinal"; - cldr = this.cldr; - - validateParameterTypePluralType( options.type, "options.type" ); - - validateDefaultLocale( cldr ); - - isOrdinal = type === "ordinal"; - - cldr.on( "get", validateCldr ); - cldr.supplemental([ "plurals-type-" + type, "{language}" ]); - cldr.off( "get", validateCldr ); - - MakePlural.rules = {}; - MakePlural.rules[ type ] = cldr.supplemental( "plurals-type-" + type ); - - plural = new MakePlural( cldr.attributes.language, { - "ordinals": isOrdinal, - "cardinals": !isOrdinal - }); - - return function( value ) { - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - - return plural( value ); - }; -}; - -return Globalize; - - - - -})); diff --git a/web/Scripts/globalize/relative-time.js b/web/Scripts/globalize/relative-time.js deleted file mode 100644 index 2cdd47a7..00000000 --- a/web/Scripts/globalize/relative-time.js +++ /dev/null @@ -1,187 +0,0 @@ -/** - * Globalize v1.0.0 - * - * http://github.com/jquery/globalize - * - * Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2015-04-23T12:02Z - */ -/*! - * Globalize v1.0.0 2015-04-23T12:02Z Released under the MIT license - * http://git.io/TrdQbw - */ -(function( root, factory ) { - - // UMD returnExports - if ( typeof define === "function" && define.amd ) { - - // AMD - define([ - "cldr", - "../globalize", - "./number", - "./plural", - "cldr/event", - "cldr/supplemental" - ], factory ); - } else if ( typeof exports === "object" ) { - - // Node, CommonJS - module.exports = factory( require( "cldrjs" ), require( "globalize" ) ); - } else { - - // Extend global - factory( root.Cldr, root.Globalize ); - } -}(this, function( Cldr, Globalize ) { - -var formatMessage = Globalize._formatMessage, - validateCldr = Globalize._validateCldr, - validateDefaultLocale = Globalize._validateDefaultLocale, - validateParameterPresence = Globalize._validateParameterPresence, - validateParameterTypeString = Globalize._validateParameterTypeString, - validateParameterTypeNumber = Globalize._validateParameterTypeNumber; - - -/** - * format( value, numberFormatter, pluralGenerator, properties ) - * - * @value [Number] The number to format - * - * @numberFormatter [String] A numberFormatter from Globalize.numberFormatter - * - * @pluralGenerator [String] A pluralGenerator from Globalize.pluralGenerator - * - * @properties [Object] containing relative time plural message. - * - * Format relative time. - */ -var relativeTimeFormat = function( value, numberFormatter, pluralGenerator, properties ) { - - var relativeTime, - message = properties[ "relative-type-" + value ]; - - if ( message ) { - return message; - } - - relativeTime = value <= 0 ? properties[ "relativeTime-type-past" ] - : properties[ "relativeTime-type-future" ]; - - value = Math.abs( value ); - - message = relativeTime[ "relativeTimePattern-count-" + pluralGenerator( value ) ]; - return formatMessage( message, [ numberFormatter( value ) ] ); -}; - - - - -/** - * properties( unit, cldr, options ) - * - * @unit [String] eg. "day", "week", "month", etc. - * - * @cldr [Cldr instance]. - * - * @options [Object] - * - form: [String] eg. "short" or "narrow". Or falsy for default long form. - * - * Return relative time properties. - */ -var relativeTimeProperties = function( unit, cldr, options ) { - - var form = options.form, - raw, properties, key, match; - - if ( form ) { - unit = unit + "-" + form; - } - - raw = cldr.main( [ "dates", "fields", unit ] ); - properties = { - "relativeTime-type-future": raw[ "relativeTime-type-future" ], - "relativeTime-type-past": raw[ "relativeTime-type-past" ] - }; - for ( key in raw ) { - if ( raw.hasOwnProperty( key ) ) { - match = /relative-type-(-?[0-9]+)/.exec( key ); - if ( match ) { - properties[ key ] = raw[ key ]; - } - } - } - - return properties; -}; - - - - -/** - * .formatRelativeTime( value, unit [, options] ) - * - * @value [Number] The number of unit to format. - * - * @unit [String] see .relativeTimeFormatter() for details. - * - * @options [Object] see .relativeTimeFormatter() for details. - * - * Formats a relative time according to the given unit, options, and the default/instance locale. - */ -Globalize.formatRelativeTime = -Globalize.prototype.formatRelativeTime = function( value, unit, options ) { - - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - - return this.relativeTimeFormatter( unit, options )( value ); -}; - -/** - * .relativeTimeFormatter( unit [, options ]) - * - * @unit [String] String value indicating the unit to be formatted. eg. "day", "week", "month", etc. - * - * @options [Object] - * - form: [String] eg. "short" or "narrow". Or falsy for default long form. - * - * Returns a function that formats a relative time according to the given unit, options, and the - * default/instance locale. - */ -Globalize.relativeTimeFormatter = -Globalize.prototype.relativeTimeFormatter = function( unit, options ) { - var cldr, numberFormatter, pluralGenerator, properties; - - validateParameterPresence( unit, "unit" ); - validateParameterTypeString( unit, "unit" ); - - cldr = this.cldr; - options = options || {}; - - validateDefaultLocale( cldr ); - - cldr.on( "get", validateCldr ); - properties = relativeTimeProperties( unit, cldr, options ); - cldr.off( "get", validateCldr ); - - numberFormatter = this.numberFormatter( options ); - pluralGenerator = this.pluralGenerator(); - - return function( value ) { - validateParameterPresence( value, "value" ); - validateParameterTypeNumber( value, "value" ); - - return relativeTimeFormat( value, numberFormatter, pluralGenerator, properties ); - }; -}; - -return Globalize; - - - - -})); diff --git a/web/Scripts/knockout-3.4.0.debug.js b/web/Scripts/knockout-3.4.0.debug.js new file mode 100644 index 00000000..3bbeb22a --- /dev/null +++ b/web/Scripts/knockout-3.4.0.debug.js @@ -0,0 +1,5871 @@ +/*! + * Knockout JavaScript library v3.4.0 + * (c) Steven Sanderson - http://knockoutjs.com/ + * License: MIT (http://www.opensource.org/licenses/mit-license.php) + */ + +(function(){ +var DEBUG=true; +(function(undefined){ + // (0, eval)('this') is a robust way of getting a reference to the global object + // For details, see http://stackoverflow.com/questions/14119988/return-this-0-evalthis/14120023#14120023 + var window = this || (0, eval)('this'), + document = window['document'], + navigator = window['navigator'], + jQueryInstance = window["jQuery"], + JSON = window["JSON"]; +(function(factory) { + // Support three module loading scenarios + if (typeof define === 'function' && define['amd']) { + // [1] AMD anonymous module + define(['exports', 'require'], factory); + } else if (typeof exports === 'object' && typeof module === 'object') { + // [2] CommonJS/Node.js + factory(module['exports'] || exports); // module.exports is for Node.js + } else { + // [3] No module loader (plain