├── .gitattributes ├── license.txt ├── src ├── packages │ ├── Nancy.0.16.1 │ │ ├── Nancy.0.16.1.nupkg │ │ ├── lib │ │ │ └── net40 │ │ │ │ └── Nancy.dll │ │ └── Nancy.0.16.1.nuspec │ ├── SimpleJson.0.15.0.0 │ │ └── SimpleJson.0.15.0.0.nupkg │ ├── repositories.config │ ├── MarkdownSharp.1.13.0.0 │ │ ├── lib │ │ │ └── 35 │ │ │ │ ├── MarkdownSharp.dll │ │ │ │ ├── MarkdownSharp.pdb │ │ │ │ └── MarkdownSharp.xml │ │ └── MarkdownSharp.1.13.0.0.nupkg │ ├── mongocsharpdriver.1.7 │ │ ├── lib │ │ │ └── net35 │ │ │ │ ├── MongoDB.Bson.dll │ │ │ │ ├── MongoDB.Bson.pdb │ │ │ │ ├── MongoDB.Driver.dll │ │ │ │ └── MongoDB.Driver.pdb │ │ ├── mongocsharpdriver.1.7.nupkg │ │ ├── mongocsharpdriver.1.7.nuspec │ │ └── Release Notes v1.7.txt │ ├── HttpHelper.0.11.1-alpha │ │ ├── HttpHelper.0.11.1-alpha.nupkg │ │ └── readme.txt │ ├── Nancy.Hosting.Aspnet.0.16.1 │ │ ├── Nancy.Hosting.Aspnet.0.16.1.nupkg │ │ ├── lib │ │ │ └── net40 │ │ │ │ └── Nancy.Hosting.Aspnet.dll │ │ ├── content │ │ │ └── web.config.transform │ │ └── Nancy.Hosting.Aspnet.0.16.1.nuspec │ └── Nancy.Authentication.Forms.0.16.1 │ │ ├── Nancy.Authentication.Forms.0.16.1.nupkg │ │ ├── lib │ │ └── net40 │ │ │ └── Nancy.Authentication.Forms.dll │ │ └── Nancy.Authentication.Forms.0.16.1.nuspec ├── Nancy.Demo.Samples │ ├── Content │ │ ├── css │ │ │ ├── fancybox_overlay.png │ │ │ ├── fancybox_sprite.png │ │ │ ├── jquery.fancybox.css │ │ │ └── font-awesome.css │ │ ├── font │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.ttf │ │ │ └── fontawesome-webfont.woff │ │ ├── img │ │ │ ├── glyphicons-halflings.png │ │ │ └── glyphicons-halflings-white.png │ │ └── js │ │ │ ├── jquery.autoellipsis-1.0.10.min.js │ │ │ ├── jquery.dotdotdot-1.5.6-packed.js │ │ │ ├── jquery.masonry.min.js │ │ │ ├── moment.min.js │ │ │ ├── jquery.autoellipsis.js │ │ │ └── jquery.fancybox.pack.js │ ├── IUserDatabase.cs │ ├── User.cs │ ├── Views │ │ ├── login.sshtml │ │ ├── about.sshtml │ │ ├── howto.sshtml │ │ ├── contributors.sshtml │ │ ├── index.sshtml │ │ └── master.sshtml │ ├── Data │ │ ├── NugetPackageInformation.cs │ │ ├── IContributorModelFactory.cs │ │ ├── IDemoModelFactory.cs │ │ ├── IContributorRepository.cs │ │ ├── IDemoRepository.cs │ │ ├── MongoDbContributorRepository.cs │ │ ├── MongoDbDemoRepository.cs │ │ ├── DefaultGitHubUserFactory.cs │ │ ├── DefaultContributorModelFactory.cs │ │ └── DefaultDemoModelFactory.cs │ ├── Modules │ │ ├── Home.cs │ │ ├── Api.cs │ │ ├── Contributors.cs │ │ ├── Login.cs │ │ └── Admin.cs │ ├── packages.config │ ├── Configuration.cs │ ├── Net │ │ ├── IGitHubHttpClient.cs │ │ └── DefaultGithubHttpClient.cs │ ├── GitHubApiCredentials.cs │ ├── IRepositoryNugetChecker.cs │ ├── Models │ │ ├── ContributorModel.cs │ │ └── DemoModel.cs │ ├── Web.config │ ├── IGitHubFileContentExtractor.cs │ ├── UserDatabase.cs │ ├── Web.Debug.config │ ├── Web.Release.config │ ├── DefaultRepositoryNugetChecker.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Bootstrapper.cs │ ├── DefaultGitHubFileContentExtractor.cs │ ├── ConfigLoader.cs │ └── Nancy.Demo.Samples.csproj └── Nancy.Demo.Samples.sln ├── .gitignore └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * -crlf -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/license.txt -------------------------------------------------------------------------------- /src/packages/Nancy.0.16.1/Nancy.0.16.1.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/Nancy.0.16.1/Nancy.0.16.1.nupkg -------------------------------------------------------------------------------- /src/packages/Nancy.0.16.1/lib/net40/Nancy.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/Nancy.0.16.1/lib/net40/Nancy.dll -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/css/fancybox_overlay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/Nancy.Demo.Samples/Content/css/fancybox_overlay.png -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/css/fancybox_sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/Nancy.Demo.Samples/Content/css/fancybox_sprite.png -------------------------------------------------------------------------------- /src/packages/SimpleJson.0.15.0.0/SimpleJson.0.15.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/SimpleJson.0.15.0.0/SimpleJson.0.15.0.0.nupkg -------------------------------------------------------------------------------- /src/packages/repositories.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/font/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/Nancy.Demo.Samples/Content/font/fontawesome-webfont.eot -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/font/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/Nancy.Demo.Samples/Content/font/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/font/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/Nancy.Demo.Samples/Content/font/fontawesome-webfont.woff -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/Nancy.Demo.Samples/Content/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /src/packages/MarkdownSharp.1.13.0.0/lib/35/MarkdownSharp.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/MarkdownSharp.1.13.0.0/lib/35/MarkdownSharp.dll -------------------------------------------------------------------------------- /src/packages/MarkdownSharp.1.13.0.0/lib/35/MarkdownSharp.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/MarkdownSharp.1.13.0.0/lib/35/MarkdownSharp.pdb -------------------------------------------------------------------------------- /src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Bson.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Bson.dll -------------------------------------------------------------------------------- /src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Bson.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Bson.pdb -------------------------------------------------------------------------------- /src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Driver.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Driver.dll -------------------------------------------------------------------------------- /src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Driver.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/mongocsharpdriver.1.7/lib/net35/MongoDB.Driver.pdb -------------------------------------------------------------------------------- /src/packages/mongocsharpdriver.1.7/mongocsharpdriver.1.7.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/mongocsharpdriver.1.7/mongocsharpdriver.1.7.nupkg -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/Nancy.Demo.Samples/Content/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /src/packages/MarkdownSharp.1.13.0.0/MarkdownSharp.1.13.0.0.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/MarkdownSharp.1.13.0.0/MarkdownSharp.1.13.0.0.nupkg -------------------------------------------------------------------------------- /src/packages/HttpHelper.0.11.1-alpha/HttpHelper.0.11.1-alpha.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/HttpHelper.0.11.1-alpha/HttpHelper.0.11.1-alpha.nupkg -------------------------------------------------------------------------------- /src/packages/Nancy.Hosting.Aspnet.0.16.1/Nancy.Hosting.Aspnet.0.16.1.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/Nancy.Hosting.Aspnet.0.16.1/Nancy.Hosting.Aspnet.0.16.1.nupkg -------------------------------------------------------------------------------- /src/packages/Nancy.Hosting.Aspnet.0.16.1/lib/net40/Nancy.Hosting.Aspnet.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/Nancy.Hosting.Aspnet.0.16.1/lib/net40/Nancy.Hosting.Aspnet.dll -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/IUserDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System; 4 | 5 | public interface IUserDatabase 6 | { 7 | Guid? ValidateUser(string password); 8 | } 9 | } -------------------------------------------------------------------------------- /src/packages/Nancy.Authentication.Forms.0.16.1/Nancy.Authentication.Forms.0.16.1.nupkg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/Nancy.Authentication.Forms.0.16.1/Nancy.Authentication.Forms.0.16.1.nupkg -------------------------------------------------------------------------------- /src/packages/Nancy.Authentication.Forms.0.16.1/lib/net40/Nancy.Authentication.Forms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NancyFx/Nancy.Demo.Samples/HEAD/src/packages/Nancy.Authentication.Forms.0.16.1/lib/net40/Nancy.Authentication.Forms.dll -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/User.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System.Collections.Generic; 4 | using Security; 5 | 6 | public class User : IUserIdentity 7 | { 8 | public string UserName { get; set; } 9 | 10 | public IEnumerable Claims { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.[Cc]ache 2 | *.csproj.user 3 | *.[Rr]e[Ss]harper* 4 | *.sln.cache 5 | *.suo 6 | *.user 7 | *.orig 8 | *.pidb 9 | *.userprefs 10 | .DS_Store 11 | deploy/ 12 | build/ 13 | [Bb]in/ 14 | [Dd]ebug/ 15 | [Oo]bj/ 16 | [Rr]elease/ 17 | _[Rr]e[Ss]harper.*/ 18 | *.docstates 19 | *.tss 20 | *.ncrunchproject 21 | *.ncrunchsolution 22 | *.dotCover 23 | .htaccess 24 | deploy.config -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Views/login.sshtml: -------------------------------------------------------------------------------- 1 | @Master['master'] 2 | 3 | @Section['Content'] 4 |
5 | Please enter password to login 6 | 7 | 8 | 9 |
10 | @EndSection -------------------------------------------------------------------------------- /src/packages/Nancy.Hosting.Aspnet.0.16.1/content/web.config.transform: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/NugetPackageInformation.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | /// 4 | /// Stores information about a Nuget package. 5 | /// 6 | public class NugetPackageInformation 7 | { 8 | /// 9 | /// The name of the package. 10 | /// 11 | public string Name { get; set; } 12 | 13 | /// 14 | /// The version of the package. 15 | /// 16 | public string Version { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Modules/Home.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Modules 2 | { 3 | public class Home : NancyModule 4 | { 5 | public Home() 6 | { 7 | Get["/"] = parameters => 8 | { 9 | return View["index"]; 10 | }; 11 | 12 | Get["/about"] = parameters => { 13 | return View["about"]; 14 | }; 15 | 16 | Get["/howto"] = parameters => { 17 | return View["howto"]; 18 | }; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Configuration.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | public class Configuration 4 | { 5 | static Configuration() 6 | { 7 | ConnectionString = @"mongodb://localhost:27017"; 8 | EncryptionKey = "SuperSecretPass"; 9 | HmacKey = "UberSuperSecret"; 10 | Password = "password"; 11 | } 12 | 13 | public static string ConnectionString { get; set; } 14 | 15 | public static string EncryptionKey { get; set; } 16 | 17 | public static string HmacKey { get; set; } 18 | 19 | public static string Password { get; set; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Modules/Api.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Modules 2 | { 3 | using Data; 4 | 5 | public class Api : NancyModule 6 | { 7 | public Api(IDemoRepository demoRepository, IContributorRepository contributorRepository) 8 | : base("/api") 9 | { 10 | Get["/contributors"] = parameters => 11 | { 12 | return Negotiate.WithModel(contributorRepository.GetAll()); 13 | }; 14 | 15 | Get["/demos"] = parameters => 16 | { 17 | return Negotiate.WithModel(demoRepository.GetAll()); 18 | }; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Net/IGitHubHttpClient.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Net 2 | { 3 | /// 4 | /// Defines the functionality for requesting data, from the GitHub API, over HTTP. 5 | /// 6 | public interface IGitHubHttpClient 7 | { 8 | /// 9 | /// Sends a HTTP Get request to the provided and returns the response value. 10 | /// 11 | /// The relative url of that the request should be sent to. 12 | /// The value of the response. 13 | dynamic Get(string relativeUrl); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/GitHubApiCredentials.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | /// 4 | /// Default implementation of the interface. 5 | /// 6 | public class GitHubApiCredentials : IGitHubApiCredentials 7 | { 8 | /// 9 | /// The password of the account. 10 | /// 11 | public string Password 12 | { 13 | get { return string.Empty; } 14 | } 15 | 16 | /// 17 | /// The username of the account. 18 | /// 19 | public string Username 20 | { 21 | get { return string.Empty; } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/IRepositoryNugetChecker.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | /// 4 | /// Defines the functionality for checking that there is a Nuget available for 5 | /// a GitHub repository. 6 | /// 7 | public interface IRepositoryNugetChecker 8 | { 9 | /// 10 | /// Checks if there is a Nuget avilable for the repository with the specified 11 | /// 12 | /// The name of the repository. 13 | /// if there is a Nuget available, otherwise . 14 | bool IsNugetAvailable(string name); 15 | } 16 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/IContributorModelFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using Nancy.Demo.Samples.Models; 4 | 5 | /// 6 | /// Defines the functionality for retreiving information about a GitHub user. 7 | /// 8 | public interface IContributorModelFactory 9 | { 10 | /// 11 | /// Retrieves information about a GitHub user that is identified by the provided . 12 | /// 13 | /// The username that should be queried. 14 | /// A instance. 15 | ContributorModel Retrieve(string username); 16 | } 17 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nancy.Demo.Samples 2 | 3 | This site/demo shows a simple Nancy website that aggregates Nancy demo projects from multiple GitHub accounts that follow the Nancy.Demo.xxxx naming convention. 4 | 5 | ## The Tech 6 | 7 | For rendering the views this site uses the SuperSimpleViewEngine, which is built into Nancy core, along with Knockout.js 8 | for binding data to the view. 9 | 10 | On the storage front, we're using MongoDB, with the live samples site using MongoHQ. If you're running locally you will need to make sure you have a local instance of MongoDB running on your machine, or edit the Configuration.cs class and alter the connection string to point to your own MongoHQ account. 11 | -------------------------------------------------------------------------------- /src/packages/mongocsharpdriver.1.7/mongocsharpdriver.1.7.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mongocsharpdriver 5 | 1.7 6 | Official MongoDB C# driver 7 | 10gen, Inc. 8 | 10gen, Inc. 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | http://www.mongodb.org/display/DOCS/CSharp+Language+Center 11 | http://jobs.mongodb.org/files/logos/889002/889002.png 12 | true 13 | Official 10gen supported C# driver for MongoDB 14 | en-US 15 | mongodb mongo nosql 16 | 17 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Modules/Contributors.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Modules 2 | { 3 | using Data; 4 | 5 | public class Contributors : NancyModule 6 | { 7 | public Contributors(IContributorRepository contributorRepository, IDemoModelFactory demoModelFactory, IContributorModelFactory factory) 8 | : base("/contributors") 9 | { 10 | Get["/"] = x => { 11 | return View["contributors"]; 12 | }; 13 | 14 | Post["/"] = x => { 15 | var contributor = 16 | factory.Retrieve((string)Request.Form.username); 17 | 18 | if (contributorRepository != null) 19 | { 20 | contributorRepository.Persist(contributor); 21 | } 22 | 23 | return Response.AsRedirect("~/contributors"); 24 | }; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/IDemoModelFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System.Collections.Generic; 4 | using Nancy.Demo.Samples.Models; 5 | 6 | /// 7 | /// Defines the functionality for retreiving information about the available demos from the user 8 | /// that is identified, on GitHub, using the specified . 9 | /// 10 | public interface IDemoModelFactory 11 | { 12 | /// 13 | /// Retrieves information about Nancy demo projects, from the GitHub account that is 14 | /// identified with the provided . 15 | /// 16 | /// The username that should be queried. 17 | /// An , containing instances. 18 | IEnumerable Retrieve(string username); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nancy.Demo.Samples", "Nancy.Demo.Samples\Nancy.Demo.Samples.csproj", "{EB6E1B40-53CE-4B0D-AD20-22C44D636FB1}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {EB6E1B40-53CE-4B0D-AD20-22C44D636FB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {EB6E1B40-53CE-4B0D-AD20-22C44D636FB1}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {EB6E1B40-53CE-4B0D-AD20-22C44D636FB1}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {EB6E1B40-53CE-4B0D-AD20-22C44D636FB1}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Models/ContributorModel.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Models 2 | { 3 | /// 4 | /// Model that represents a contributor. 5 | /// 6 | public class ContributorModel 7 | { 8 | /// 9 | /// The url of the contributor avatar. 10 | /// 11 | public string AvatarUrl { get; set; } 12 | 13 | /// 14 | /// The id of the model. 15 | /// 16 | public string Id { get; set; } 17 | 18 | /// 19 | /// The name of the contributor. 20 | /// 21 | public string Name { get; set; } 22 | 23 | /// 24 | /// The url to the contributors page on GitHub. 25 | /// 26 | public string Url { get; set; } 27 | 28 | /// 29 | /// The username of the contributor. 30 | /// 31 | public string Username { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Modules/Login.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Modules 2 | { 3 | using System; 4 | using Authentication.Forms; 5 | 6 | public class Login : NancyModule 7 | { 8 | public Login(IUserDatabase userDatabase) 9 | { 10 | 11 | Get["/login"] = x => 12 | { 13 | return View["login"]; 14 | }; 15 | 16 | Post["/login"] = parameters => 17 | { 18 | var userGuid = userDatabase.ValidateUser((string)this.Request.Form.Password); 19 | 20 | if (userGuid == null) 21 | { 22 | return Response.AsRedirect("/"); 23 | } 24 | 25 | DateTime? expiry = null; 26 | 27 | return this.LoginAndRedirect(userGuid.Value, expiry); 28 | }; 29 | 30 | Get["/logout"] = x => 31 | { 32 | return this.LogoutAndRedirect("~/"); 33 | }; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/IGitHubFileContentExtractor.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System; 4 | 5 | /// 6 | /// Defines the functionality for extracting the content of a file hosted on GitHub. 7 | /// 8 | public interface IGitHubFileContentExtractor 9 | { 10 | /// 11 | /// Extracts the content of the file GitHub hosted file. 12 | /// 13 | /// Function that extracts the desired values from the file. 14 | /// The username of the GitHub account where the repository exists. 15 | /// The name of the repository that contains the file. 16 | /// The repository relative path to the file. 17 | /// The content of the file if it was available, otherwise . 18 | T Extract(string username, string repositoryName, string relativeFilePath, Func valueExtractor); 19 | } 20 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Views/about.sshtml: -------------------------------------------------------------------------------- 1 | @Master['master'] 2 | 3 | @Section['Content'] 4 |
5 |

About

6 |

7 | Welcome to the Nancy Samples site! 8 |

9 |

10 | This site/demo shows a simple Nancy website that aggregates Nancy demo projects from multiple GitHub accounts that follow the 11 | Nancy.Demo.xxxx naming convention. 12 |

13 |

The Tech

14 |

15 | For rendering the views this site uses the SuperSimpleViewEngine, which is build into Nancy core, along with Knockout.js 16 | for binding data to the view. 17 |

18 |

19 | On the storage front, we're using MongoDB, with the live samples site using MongoHQ. 20 | If you're running locally you will need to make sure you have a local instance of MongoDB running on your machine, or edit the Configuration.cs class and 21 | alter the connection string to point to your own MongoHQ account. 22 |

23 |
24 | @EndSection 25 | -------------------------------------------------------------------------------- /src/packages/Nancy.0.16.1/Nancy.0.16.1.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Nancy 5 | 0.16.1 6 | Andreas Håkansson, Steven Robbins and contributors 7 | Andreas Håkansson, Steven Robbins and contributors 8 | https://github.com/NancyFx/Nancy/blob/master/license.txt 9 | http://nancyfx.org/ 10 | http://nancyfx.org/nancy-nuget.png 11 | false 12 | Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. 13 | Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. 14 | Andreas Håkansson, Steven Robbins and contributors 15 | en-US 16 | Nancy 17 | 18 | -------------------------------------------------------------------------------- /src/packages/Nancy.Hosting.Aspnet.0.16.1/Nancy.Hosting.Aspnet.0.16.1.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Nancy.Hosting.Aspnet 5 | 0.16.1 6 | Andreas Håkansson, Steven Robbins and contributors 7 | Andreas Håkansson, Steven Robbins and contributors 8 | https://github.com/NancyFx/Nancy/blob/master/license.txt 9 | http://nancyfx.org/ 10 | http://nancyfx.org/nancy-nuget.png 11 | false 12 | Enables hosting Nancy on ASP.NET 13 | Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. 14 | Andreas Håkansson, Steven Robbins and contributors 15 | en-US 16 | Nancy ASP.NET 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/packages/Nancy.Authentication.Forms.0.16.1/Nancy.Authentication.Forms.0.16.1.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Nancy.Authentication.Forms 5 | 0.16.1 6 | Andreas Håkansson, Steven Robbins and contributors 7 | Andreas Håkansson, Steven Robbins and contributors 8 | https://github.com/NancyFx/Nancy/blob/master/license.txt 9 | http://nancyfx.org/ 10 | http://nancyfx.org/nancy-nuget.png 11 | false 12 | A forms authentication provider for Nancy. 13 | Nancy is a lightweight web framework for the .Net platform, inspired by Sinatra. Nancy aim at delivering a low ceremony approach to building light, fast web applications. 14 | Andreas Håkansson, Steven Robbins and contributors 15 | en-US 16 | Nancy Authentication 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/IContributorRepository.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System.Collections.Generic; 4 | using Nancy.Demo.Samples.Models; 5 | 6 | /// 7 | /// Defines the functionality for retrieving and storing instances in 8 | /// an underlying data store. 9 | /// 10 | public interface IContributorRepository 11 | { 12 | /// 13 | /// Deletes a contributor based on the provided . 14 | /// 15 | /// The username of the contributor to delete. 16 | void DeleteByUserName(string username); 17 | 18 | /// 19 | /// Gets all the contributors in the data store. 20 | /// 21 | /// An , of instances. 22 | IEnumerable GetAll(); 23 | 24 | /// 25 | /// Persists a new contributors in the data store. 26 | /// 27 | /// The instance to persist 28 | void Persist(ContributorModel contributor); 29 | } 30 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/IDemoRepository.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System.Collections.Generic; 4 | using Nancy.Demo.Samples.Models; 5 | 6 | /// 7 | /// Defines the functionality for retrieving and storing instances in 8 | /// an underlying data store. 9 | /// 10 | public interface IDemoRepository 11 | { 12 | /// 13 | /// Deletes all demos. 14 | /// 15 | void DeleteAll(); 16 | 17 | /// 18 | /// Deletes demos by the specified author. 19 | /// 20 | /// The name of the author to delete the demos for. 21 | void DeleteByAuthor(string name); 22 | 23 | /// 24 | /// Gets all the demos in the data store. 25 | /// 26 | /// An , of instances. 27 | IEnumerable GetAll(); 28 | 29 | /// 30 | /// Persists a new demo in the data store. 31 | /// 32 | /// The instance to persist 33 | void Persist(DemoModel demo); 34 | } 35 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/UserDatabase.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using Authentication.Forms; 7 | using Security; 8 | 9 | public class UserDatabase : IUserMapper, IUserDatabase 10 | { 11 | private readonly List> users = new List>(); 12 | 13 | public UserDatabase() 14 | { 15 | users.Add(new Tuple("admin", Configuration.Password, new Guid("55E1E49E-B7E8-4EEA-8459-7A906AC4D4C0"))); 16 | } 17 | 18 | public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context) 19 | { 20 | var userRecord = users.FirstOrDefault(u => u.Item3 == identifier); 21 | 22 | return userRecord == null 23 | ? null 24 | : new User { UserName = userRecord.Item1 }; 25 | } 26 | 27 | public Guid? ValidateUser(string password) 28 | { 29 | var userRecord = users.FirstOrDefault(u => u.Item2 == password); 30 | 31 | if (userRecord == null) 32 | { 33 | return null; 34 | } 35 | 36 | return userRecord.Item3; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Modules/Admin.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Modules 2 | { 3 | using Data; 4 | using Security; 5 | 6 | public class Admin : NancyModule 7 | { 8 | public Admin(IContributorRepository contributorRepository, IDemoModelFactory demoModelFactory, IDemoRepository demoRepository) 9 | { 10 | this.RequiresAuthentication(); 11 | 12 | Delete["/contributor/{username}"] = parameters => 13 | { 14 | contributorRepository.DeleteByUserName((string)parameters.username); 15 | demoRepository.DeleteByAuthor((string)parameters.username); 16 | 17 | return Response.AsRedirect("~/contributors"); 18 | }; 19 | 20 | Post["/contributors/refresh"] = parameters => 21 | { 22 | var model = 23 | contributorRepository.GetAll(); 24 | 25 | demoRepository.DeleteAll(); 26 | 27 | foreach (var contributorModel in model) 28 | { 29 | var demos = 30 | demoModelFactory.Retrieve(contributorModel.Username); 31 | 32 | foreach (var demoModel in demos) 33 | { 34 | demoRepository.Persist(demoModel); 35 | } 36 | } 37 | 38 | return Response.AsRedirect("~/contributors"); 39 | }; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/DefaultRepositoryNugetChecker.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System; 4 | using System.IO; 5 | 6 | /// 7 | /// Default implemenation of the interface, that uses the Nuget 8 | /// OData feed to determin if there is a Nuget available or not. 9 | /// 10 | public class DefaultRepositoryNugetChecker : IRepositoryNugetChecker 11 | { 12 | /// 13 | /// Checks if there is a Nuget avilable for the repository with the specified 14 | /// 15 | /// The name of the repository. 16 | /// if there is a Nuget available, otherwise . 17 | public bool IsNugetAvailable(string name) 18 | { 19 | var url = 20 | string.Format(@" http://nuget.org/api/v2/Packages?$filter=Id%20eq%20'{0}'", name); 21 | 22 | var client = 23 | new HttpHelper(url); 24 | 25 | using (var stream = client.OpenRead()) 26 | { 27 | using (var reader = new StreamReader(stream)) 28 | { 29 | var content = 30 | reader.ReadToEnd(); 31 | 32 | return content.IndexOf("", StringComparison.OrdinalIgnoreCase) >= 0; 33 | } 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Nancy.Demo.Samples")] 9 | [assembly: AssemblyDescription("Demo website for aggregating Nancy demo projects from GitHub")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Nancy.Demo.Samples")] 13 | [assembly: AssemblyCopyright("Copyright © Andreas Håkansson 2012")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("071c84c6-436c-413b-9bb3-52875d36b3fb")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/MongoDbContributorRepository.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System.Collections.Generic; 4 | using Models; 5 | using MongoDB.Driver; 6 | using MongoDB.Driver.Builders; 7 | 8 | /// 9 | /// MongoDB based implementation of the interface. 10 | /// 11 | public class MongoDbContributorRepository : IContributorRepository 12 | { 13 | private readonly MongoCollection collection; 14 | 15 | /// 16 | /// Initializes a new instance of the class, with 17 | /// the provided . 18 | /// 19 | /// The instance that should be used by the repository. 20 | public MongoDbContributorRepository(MongoDatabase database) 21 | { 22 | this.collection = database.GetCollection("contributors"); 23 | } 24 | 25 | /// 26 | /// Deletes a contributor based on the provided . 27 | /// 28 | /// The username of the contributor to delete. 29 | public void DeleteByUserName(string username) 30 | { 31 | this.collection.Remove(Query.Where(contributor => contributor.Username == username)); 32 | } 33 | 34 | /// 35 | /// Gets all the contributors in the data store. 36 | /// 37 | /// An , of instances. 38 | public IEnumerable GetAll() 39 | { 40 | return this.collection.FindAll(); 41 | } 42 | 43 | /// 44 | /// Persists a new contributors in the data store. 45 | /// 46 | /// The instance to persist 47 | public void Persist(ContributorModel contributor) 48 | { 49 | collection.Insert(contributor); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/MongoDbDemoRepository.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System.Collections.Generic; 4 | using Models; 5 | using MongoDB.Driver; 6 | using MongoDB.Driver.Builders; 7 | 8 | /// 9 | /// MongoDB based implementation of the interface. 10 | /// 11 | public class MongoDbDemoRepository : IDemoRepository 12 | { 13 | private readonly MongoCollection collection; 14 | 15 | /// 16 | /// Initializes a new instance of the class, with 17 | /// the provided . 18 | /// 19 | /// The instance that should be used by the repository. 20 | public MongoDbDemoRepository(MongoDatabase database) 21 | { 22 | this.collection = database.GetCollection("demos"); 23 | } 24 | 25 | /// 26 | /// Deletes all demos. 27 | /// 28 | public void DeleteAll() 29 | { 30 | this.collection.Drop(); 31 | } 32 | 33 | /// 34 | /// Deletes demos by the specified author. 35 | /// 36 | /// The name of the author to delete the demos for. 37 | public void DeleteByAuthor(string name) 38 | { 39 | this.collection.Remove(Query.Where(demo => demo.Author == name)); 40 | } 41 | 42 | /// 43 | /// Gets all the demos in the data store. 44 | /// 45 | /// An , of instances. 46 | public IEnumerable GetAll() 47 | { 48 | return this.collection.FindAll(); 49 | } 50 | 51 | /// 52 | /// Persists a new demo in the data store. 53 | /// 54 | /// The instance to persist 55 | public void Persist(DemoModel demo) 56 | { 57 | collection.Insert(demo); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Views/howto.sshtml: -------------------------------------------------------------------------------- 1 | @Master['master'] 2 | 3 | @Section['Content'] 4 |
5 |

Creating a Sample

6 | 7 |

It's pretty simple to create a sample for the site, but there's a few conventions you need to follow:

8 | 9 |
    10 |
  1. Think of an idea that you want to demo :-)
  2. 11 |
  3. Install the Nancy.Template extension, for Visual Studio, to get the project template. If you are not running Visual Studio, or prefer to get the template source, you can find it in the Nancy.Templates repository. 12 |
  4. Create your project, using the appropriate Nancy Demo project, and Github repository with the Nancy.Demo.[name] naming convention.
  5. 13 |
  6. Make sure you use NuGet for your dependencies, the site will parse your packages.conf.
  7. 14 |
  8. Add a readme.md to the root of the repo and provide details of what the sample is, what it does, and how to get it running if there are any additional steps required.
  9. 15 |
  10. Add a root "index view" with the readme details in a "hero" div (<div class="hero-unit"></div>).
  11. 16 |
  12. For code snippets use <pre><code></code></pre> and they will be syntax highligted using highlight.js.
  13. 17 |
  14. Add a license.txt, preferably MIT, but this isn't a hard requirement.
  15. 18 |
  16. Follow the general Bootstrapper styles and theming for consistency.
  17. 19 |
  18. Make sure any external content, such as CSS, images, js etc have the appropriate licenses and make sure you respect any copyright or attribution clauses on any external dependencies.
  19. 20 |
21 | 22 |

Once you've done all that and pushed it up to Github, you just need to let us know, either:

23 | 24 | 28 | 29 |

Once your account is added the site will automatically pickup any additional Demo projects you add.

30 | 31 |

Have fun! :-)

32 | 33 |

- Team Nancy

34 |
35 | @EndSection 36 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/DefaultGitHubUserFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System; 4 | using System.Linq; 5 | using Nancy.Demo.Samples.Models; 6 | using Net; 7 | 8 | /// 9 | /// Default implementation of the interface. 10 | /// 11 | public class DefaultContributorModelFactory : IContributorModelFactory 12 | { 13 | private readonly IGitHubHttpClient client; 14 | 15 | /// 16 | /// Initializes a new instance of the , using 17 | /// the provided . 18 | /// 19 | /// The that should be used to retrieve information. 20 | public DefaultContributorModelFactory(IGitHubHttpClient client) 21 | { 22 | this.client = client; 23 | } 24 | 25 | /// 26 | /// Retrieves information about a GitHub user that is identified by the provided . 27 | /// 28 | /// The username that should be queried. 29 | /// A instance. 30 | public ContributorModel Retrieve(string username) 31 | { 32 | var relativeUrl = 33 | string.Format("users/{0}", username); 34 | 35 | var response = 36 | this.client.Get(relativeUrl); 37 | 38 | return !IsValidResponse(response) ? 39 | null : 40 | new ContributorModel 41 | { 42 | Id = Guid.NewGuid().ToString(), 43 | AvatarUrl = response.avatar_url, 44 | Name = response.name, 45 | Url = response.html_url, 46 | Username = response.login 47 | }; 48 | } 49 | 50 | private static bool IsValidResponse(dynamic response) 51 | { 52 | var invalidResponseMessages = 53 | new[] { "Not Found" }; 54 | 55 | return !invalidResponseMessages.Any(x => x.Equals(response.message, StringComparison.OrdinalIgnoreCase)); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/DefaultContributorModelFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System; 4 | using System.Linq; 5 | using Nancy.Demo.Samples.Models; 6 | using Net; 7 | 8 | /// 9 | /// Default implementation of the interface. 10 | /// 11 | public class DefaultContributorModelFactory : IContributorModelFactory 12 | { 13 | private readonly IGitHubHttpClient client; 14 | 15 | /// 16 | /// Initializes a new instance of the , using 17 | /// the provided . 18 | /// 19 | /// The that should be used to retrieve information. 20 | public DefaultContributorModelFactory(IGitHubHttpClient client) 21 | { 22 | this.client = client; 23 | } 24 | 25 | /// 26 | /// Retrieves information about a GitHub user that is identified by the provided . 27 | /// 28 | /// The username that should be queried. 29 | /// A instance. 30 | public ContributorModel Retrieve(string username) 31 | { 32 | var relativeUrl = 33 | string.Format("users/{0}", username); 34 | 35 | var response = 36 | this.client.Get(relativeUrl); 37 | 38 | return !IsValidResponse(response) ? 39 | null : 40 | new ContributorModel 41 | { 42 | Id = Guid.NewGuid().ToString(), 43 | AvatarUrl = response.avatar_url, 44 | Name = response.name, 45 | Url = response.html_url, 46 | Username = response.login 47 | }; 48 | } 49 | 50 | private static bool IsValidResponse(dynamic response) 51 | { 52 | var invalidResponseMessages = 53 | new[] { "Not Found" }; 54 | 55 | return !invalidResponseMessages.Any(x => x.Equals(response.message, StringComparison.OrdinalIgnoreCase)); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Net/DefaultGithubHttpClient.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Net 2 | { 3 | using System; 4 | using System.IO; 5 | using System.Runtime.Caching; 6 | 7 | /// 8 | /// Default implementation of the interface, for communicating with 9 | /// the GitHub API. 10 | /// 11 | /// This client will cache responses for 5 minutes. 12 | public class DefaultGithubHttpClient : IGitHubHttpClient 13 | { 14 | private readonly MemoryCache cache = new MemoryCache("__Nancy_Github_Api_Cache"); 15 | 16 | /// 17 | /// Initialzes a new instance of the class 18 | /// 19 | public DefaultGithubHttpClient() 20 | { 21 | } 22 | 23 | /// 24 | /// Sends a HTTP Get request to the provided and returns the response value. 25 | /// 26 | /// The url that the request should be sent to. 27 | /// The value of the response. 28 | public dynamic Get(string relativeUrl) 29 | { 30 | if (this.cache.Contains(relativeUrl)) 31 | { 32 | return this.cache[relativeUrl]; 33 | } 34 | 35 | var url = 36 | GetFullyQualifiedUrl(relativeUrl); 37 | 38 | return RetrieveResponse(url); 39 | } 40 | 41 | private static string GetFullyQualifiedUrl(string relativeUrl) 42 | { 43 | return string.Concat("https://api.github.com/", relativeUrl); 44 | } 45 | 46 | private dynamic RetrieveResponse(string url) 47 | { 48 | var httpHelper = 49 | new HttpHelper(url); 50 | 51 | httpHelper.HttpWebRequest.UserAgent = "samples-nancyfx.org"; 52 | 53 | using (var stream = httpHelper.OpenRead()) 54 | { 55 | using (var reader = new StreamReader(stream)) 56 | { 57 | var json = 58 | reader.ReadToEnd(); 59 | 60 | var result = 61 | SimpleJson.DeserializeObject(json); 62 | 63 | this.cache.Add( 64 | url, 65 | result, 66 | DateTime.Now.AddMinutes(5)); 67 | 68 | return result; 69 | } 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Models/DemoModel.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Models 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using Data; 6 | 7 | /// 8 | /// Stores information about a demo project. 9 | /// 10 | public class DemoModel 11 | { 12 | /// 13 | /// Gets or sets the name of the author. 14 | /// 15 | public string Author { get; set; } 16 | 17 | /// 18 | /// Gets or sets the description of the project. 19 | /// 20 | public string Description { get; set; } 21 | 22 | /// 23 | /// Gets or sets the URL to the authors gravatar. 24 | /// 25 | public string Gravatar { get; set; } 26 | 27 | /// 28 | /// Gets or sets whether or not there exists a nuget of the demo project. 29 | /// 30 | public bool HasNuget { get; set; } 31 | 32 | /// 33 | /// Gets or sets the date that the demo was created. 34 | /// 35 | public DateTime CreatedAt { get; set; } 36 | 37 | /// 38 | /// Gets or sets when the demo was indexed by the application. 39 | /// 40 | public DateTime IndexedAt { get; set; } 41 | 42 | /// 43 | /// Gets or sets when a commit was last made to the demo. 44 | /// 45 | public DateTime LastCommit { get; set; } 46 | 47 | /// 48 | /// Gets or sets the name of the demo. 49 | /// 50 | public string Name { get; set; } 51 | 52 | /// 53 | /// Gets or sets the ID of the demo. 54 | /// 55 | public string Id { get; set; } 56 | 57 | public IEnumerable Packages { get; set; } 58 | 59 | /// 60 | /// Gets or sets the content of the readme file of the demo. 61 | /// 62 | public string Readme { get; set; } 63 | 64 | /// 65 | /// Gets or sets the URL to the repository on GitHub. 66 | /// 67 | public string Url { get; set; } 68 | 69 | /// 70 | /// Gets or sets the version of the demo. 71 | /// 72 | public string Version { get; set; } 73 | 74 | /// 75 | /// Gets if the demo was created within the last month. 76 | /// 77 | public bool IsNew 78 | { 79 | get { return DateTime.Now.Date.Subtract(this.CreatedAt).Days < 30; } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Bootstrapper.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System.IO; 4 | using Authentication.Forms; 5 | using Cryptography; 6 | using Data; 7 | using Diagnostics; 8 | using Extensions; 9 | using MongoDB.Driver; 10 | using Nancy.Bootstrapper; 11 | using Nancy.TinyIoc; 12 | 13 | public class Bootstrapper : DefaultNancyBootstrapper 14 | { 15 | protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) 16 | { 17 | base.ApplicationStartup(container, pipelines); 18 | 19 | var cryptographyConfiguration = new CryptographyConfiguration( 20 | new RijndaelEncryptionProvider(new PassphraseKeyGenerator(Configuration.EncryptionKey, new byte[] { 8, 2, 10, 4, 68, 120, 7, 14 })), 21 | new DefaultHmacProvider(new PassphraseKeyGenerator(Configuration.HmacKey, new byte[] { 1, 20, 73, 49, 25, 106, 78, 86 }))); 22 | 23 | var authenticationConfiguration = 24 | new FormsAuthenticationConfiguration() 25 | { 26 | CryptographyConfiguration = cryptographyConfiguration, 27 | RedirectUrl = "/login", 28 | UserMapper = container.Resolve(), 29 | }; 30 | 31 | FormsAuthentication.Enable(pipelines, authenticationConfiguration); 32 | } 33 | 34 | protected override void ConfigureApplicationContainer(TinyIoCContainer container) 35 | { 36 | base.ConfigureApplicationContainer(container); 37 | 38 | var config = new Configuration(); 39 | 40 | var binDirectory = 41 | Path.GetDirectoryName(this.GetType().GetAssemblyPath()); 42 | 43 | var configPath = 44 | Path.Combine(binDirectory ?? @".\", "deploy.config"); 45 | 46 | ConfigLoader.Load(configPath, config); 47 | 48 | var client = 49 | new MongoClient(Configuration.ConnectionString); 50 | 51 | container.Register((c, p) => client.GetServer()); 52 | } 53 | 54 | protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context) 55 | { 56 | base.ConfigureRequestContainer(container, context); 57 | 58 | var server = 59 | container.Resolve(); 60 | 61 | container.Register((c, p) => server.GetDatabase("Demos")); 62 | container.Register(); 63 | container.Register(); 64 | } 65 | 66 | protected override DiagnosticsConfiguration DiagnosticsConfiguration 67 | { 68 | get { return new DiagnosticsConfiguration() { Password = Configuration.Password }; } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/DefaultGitHubFileContentExtractor.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System; 4 | using System.Linq; 5 | using System.Text; 6 | using Net; 7 | 8 | /// 9 | /// Default implementation of the interface. 10 | /// 11 | public class DefaultGitHubFileContentExtractor : IGitHubFileContentExtractor 12 | { 13 | private readonly IGitHubHttpClient client; 14 | 15 | /// 16 | /// Initializes a new instance of the class, 17 | /// with the provided . 18 | /// 19 | /// The that should be used to communicate with the GitHub API. 20 | public DefaultGitHubFileContentExtractor(IGitHubHttpClient client) 21 | { 22 | this.client = client; 23 | } 24 | 25 | /// 26 | /// Extracts the content of the file GitHub hosted file. 27 | /// 28 | /// Function that extracts the desired values from the file. 29 | /// The username of the GitHub account where the repository exists. 30 | /// The name of the repository that contains the file. 31 | /// The repository relative path to the file. 32 | /// The content of the file if it was available, otherwise . 33 | public T Extract(string username, string repositoryName, string relativeFilePath, Func valueExtractor) 34 | { 35 | var url = 36 | GetFullyQualifiedUrl(username, repositoryName, relativeFilePath); 37 | 38 | var response = 39 | client.Get(url); 40 | 41 | return IsValidResponse(response) ? 42 | DecodeContent(response, valueExtractor) : 43 | default(T); 44 | } 45 | 46 | private static T DecodeContent(dynamic response, Func valueExtractor) 47 | { 48 | var decoded = 49 | Convert.FromBase64String(response.content); 50 | 51 | var content = 52 | Encoding.UTF8.GetString(decoded); 53 | 54 | return valueExtractor.Invoke(content); 55 | } 56 | 57 | private static string GetFullyQualifiedUrl(string username, string repositoryName, string relativeFilePath) 58 | { 59 | return string.Format("repos/{0}/{1}/{2}", username, repositoryName, relativeFilePath); 60 | } 61 | 62 | private static bool IsValidResponse(dynamic response) 63 | { 64 | var invalidResponseMessages = 65 | new[] { "Not Found", "This repository is empty." }; 66 | 67 | return !invalidResponseMessages.Any(x => x.Equals(response.message, StringComparison.OrdinalIgnoreCase)); 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Views/contributors.sshtml: -------------------------------------------------------------------------------- 1 | @Master['master'] 2 | 3 | @Section['Content'] 4 | 5 | @IfNotNull.Context.CurrentUser 6 |
7 |
8 |
9 | Please enter github username of user to add 10 | 11 | 12 | 13 |
14 | 15 |
16 | Click to refresh 17 |

18 | When you press this button, the GitHub accounts of the contributors will be 19 | re-scanned to detect new demos and updates to existing. It invokes the 20 | /contributors/refresh route and you can invoke this from 21 | a scheduled task if you want to refresh at an interval. 22 |

23 | 24 |
25 |
26 |
27 | @EndIf 28 | 29 |

Contributors

30 | 31 |
32 |
33 | 34 | 35 | 36 | 37 |
38 |

39 | 40 | 41 |

42 | @IfNotNull.Context.CurrentUser 43 | Delete 44 | @EndIf 45 |
46 |
47 |
48 | 49 | @EndSection 50 | 51 | @Section['Scripts'] 52 | 53 | $(function() { 54 | ko.applyBindings(new ContributorsViewModel()); 55 | }); 56 | 57 | function ContributorModel(data, onRemoved) { 58 | var self = this 59 | 60 | self.avatarUrl = data.AvatarUrl; 61 | self.id = data.Id, 62 | self.name = data.Name; 63 | self.url = data.Url; 64 | self.username = data.Username; 65 | 66 | self.fullName = ko.computed(function () { 67 | return self.username + ' (' + self.name + ')'; 68 | }); 69 | 70 | self.remove = function(data, event) { 71 | $.ajax({ 72 | type: 'DELETE', 73 | url: '/contributor/' + self.username, 74 | success: function() { 75 | onRemoved(self); 76 | } 77 | }); 78 | }; 79 | 80 | }; 81 | 82 | function ContributorsViewModel() { 83 | var self = this; 84 | 85 | self.contributors = ko.observableArray(); 86 | 87 | $.getJSON("/api/contributors", function (response) { 88 | var mapped = $.map(response, function (repo) { 89 | return new ContributorModel(repo, self.onContributorRemoved); 90 | }); 91 | self.contributors(mapped); 92 | }); 93 | 94 | self.onContributorRemoved = function(contributor) { 95 | self.contributors.remove(contributor); 96 | } 97 | }; 98 | 99 | @EndSection -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/js/jquery.autoellipsis-1.0.10.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | Copyright (c) 2011 Peter van der Spek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */(function(a){function m(){if(!d){d=!0;for(var c in b)a(c).each(function(){var d,e;d=a(this),e=d.data("jqae"),(e.containerWidth!=d.width()||e.containerHeight!=d.height())&&f(d,b[c])});d=!1}}function l(a){b[a]&&(delete b[a],b.length||c&&(window.clearInterval(c),c=undefined))}function k(a,d){b[a]=d,c||(c=window.setInterval(function(){m()},200))}function j(){return this.nodeType===3}function i(b){if(b.contents().length){var c=b.contents(),d=c.eq(c.length-1);if(d.filter(j).length){var e=d.get(0).nodeValue;e=a.trim(e);if(e==""){d.remove();return!0}return!1}while(i(d));if(d.contents().length)return!1;d.remove();return!0}return!1}function h(a){if(a.contents().length){var b=a.contents(),c=b.eq(b.length-1);return c.filter(j).length?c:h(c)}a.append("");var b=a.contents();return b.eq(b.length-1)}function g(b){var c=h(b);if(c.length){var d=c.get(0).nodeValue,e=d.lastIndexOf(" ");e>-1?(d=a.trim(d.substring(0,e)),c.get(0).nodeValue=d):c.get(0).nodeValue="";return!0}return!1}function f(b,c){var d=b.data("jqae");d||(d={});var e=d.wrapperElement;e||(e=b.wrapInner("
").find(">div"),e.css({margin:0,padding:0,border:0}));var f=e.data("jqae");f||(f={});var j=f.originalContent;j?e=f.originalContent.clone(!0).data("jqae",{originalContent:j}).replaceAll(e):e.data("jqae",{originalContent:e.clone(!0)}),b.data("jqae",{wrapperElement:e,containerWidth:b.width(),containerHeight:b.height()});var k=b.height(),l=(parseInt(b.css("padding-top"),10)||0)+(parseInt(b.css("border-top-width"),10)||0)-(e.offset().top-b.offset().top),m=!1,n=e;c.selector&&(n=a(e.find(c.selector).get().reverse())),n.each(function(){var b=a(this),d=b.text(),f=!1;if(e.innerHeight()-b.innerHeight()>k+l)b.remove();else{i(b);if(b.contents().length){m&&(h(b).get(0).nodeValue+=c.ellipsis,m=!1);while(e.innerHeight()>k+l){f=g(b);if(!f){m=!0,b.remove();break}i(b);if(b.contents().length)h(b).get(0).nodeValue+=c.ellipsis;else{m=!0,b.remove();break}}c.setTitle=="onEllipsis"&&f||c.setTitle=="always"?b.attr("title",d):c.setTitle!="never"&&b.removeAttr("title")}}})}var b={},c,d=!1,e={ellipsis:"...",setTitle:"never",live:!1};a.fn.ellipsis=function(b,c){var d,g;d=a(this),typeof b!="string"&&(c=b,b=undefined),g=a.extend({},e,c),g.selector=b,d.each(function(){var b=a(this);f(b,g)}),g.live?k(d.selector,g):l(d.selector);return this}})(jQuery) -------------------------------------------------------------------------------- /src/packages/mongocsharpdriver.1.7/Release Notes v1.7.txt: -------------------------------------------------------------------------------- 1 | C# Driver Version 1.7 Release Notes 2 | =================================== 3 | 4 | This is a major release. 5 | 6 | This release has two major goals: to standardize on the name WriteConcern and 7 | to make Acknowledged the new default WriteConcern. 8 | 9 | The following classes are being replaced: 10 | 11 | - SafeMode is replaced by WriteConcern 12 | - SafeModeResult is replaced by WriteConcernResult 13 | - MongoSafeModeException is replaced by WriteConcernException 14 | 15 | To make Acknowledged the new default WriteConcern without breaking any existing 16 | code that might rely on the old default we are introducing a new root class 17 | called MongoClient. 18 | 19 | An online version of these release notes is available at: 20 | 21 | https://github.com/mongodb/mongo-csharp-driver/blob/master/Release%20Notes/Release%20Notes%20v1.7.md 22 | 23 | File by file change logs are available at: 24 | 25 | https://github.com/mongodb/mongo-csharp-driver/blob/master/Release%20Notes/Change%20Log%20v1.7-Bson.txt 26 | https://github.com/mongodb/mongo-csharp-driver/blob/master/Release%20Notes/Change%20Log%20v1.7-Driver.txt 27 | 28 | The full list of JIRA issues resolved in this release is available at: 29 | 30 | https://jira.mongodb.org/secure/IssueNavigator.jspa?mode=hide&requestId=12915 31 | 32 | Documentation on the C# driver can be found at: 33 | 34 | http://www.mongodb.org/display/DOCS/CSharp+Language+Center 35 | http://api.mongodb.org/csharp/current/ 36 | 37 | Standardizing on WriteConcern instead of SafeMode 38 | ------------------------------------------------- 39 | 40 | Some MongoDB drivers (the C# driver included) have used SafeMode as the name 41 | for the class which determines whether writes to the database are checked for 42 | errors. We are now standardizing across all drivers to use the name WriteConcern 43 | instead of SafeMode. The C# driver will continue to support the SafeMode class 44 | for a few releases but eventually it will be removed. 45 | 46 | You should start using the new WriteConcern class, but we have also provided 47 | an implicit conversion from SafeMode to WriteConcern so any code that passes 48 | a SafeMode argument to a method taking a WriteConcern parameter will still 49 | compile and work. 50 | 51 | New MongoClient class and default WriteConcern 52 | ---------------------------------------------- 53 | 54 | The new default WriteConcern is Acknowledged, but we have introduced the new 55 | default in a way that doesn't alter the behavior of existing programs. We 56 | are introducing a new root class called MongoClient that defaults the 57 | WriteConcern to Acknowledged. The existing MongoServer Create methods are 58 | deprecated but when used continue to default to a WriteConcern of Unacknowledged. 59 | 60 | In prior releases you would start using the C# driver with code like this: 61 | 62 | var connectionString = "mongodb://localhost"; 63 | var server = MongoServer.Create(connectionString); // deprecated 64 | var database = server.GetDatabase("test"); // WriteConcern defaulted to Unacknowledged 65 | 66 | The new way to start using the C# driver is: 67 | 68 | var connectionString = "mongodb://localhost"; 69 | var client = new MongoClient(connectionString); 70 | var server = client.GetServer(); 71 | var database = server.GetDatabase("test"); // WriteConcern defaulted to Acknowledged 72 | 73 | If you use the old way to start using the driver the default WriteConcern will 74 | be Unacknowledged, but if you use the new way (using MongoClient) the default 75 | WriteConcern will be Acknowledged. 76 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Views/index.sshtml: -------------------------------------------------------------------------------- 1 | @Master['master'] 2 | 3 | @Section['Content'] 4 | 5 |
6 |
7 | 8 |
9 |
10 | New! 11 |
12 |
13 | 14 |
15 | 16 | 17 | 18 | 19 |
20 |

21 | 22 |

23 | 24 |
25 | version by 26 |
27 |
28 | 29 |
30 |

31 |

32 | 33 |

34 | Last updated: 35 |

36 | 37 |
38 | Packages used in this sample 39 |
40 | 47 |
48 |
49 | 50 |
51 | 52 |
53 | 54 |
55 | Read more 56 |
57 |
58 | @EndSection 59 | 60 | @Section['Scripts'] 61 | 62 | $(function() { 63 | hljs.tabReplace = ' '; 64 | ko.applyBindings(new DemosViewModel()); 65 | }); 66 | 67 | function DemoModel(data) { 68 | var self = this 69 | 70 | self.author = data.Author; 71 | self.description = data.Description; 72 | self.gravatar = data.Gravatar; 73 | self.hasNuget = data.HasNuget; 74 | self.lastCommit = data.LastCommit; 75 | self.name = data.Name; 76 | self.packages = data.Packages; 77 | self.readMe = data.Readme; 78 | self.url = data.Url; 79 | self.version = data.Version; 80 | self.isNew = data.IsNew; 81 | 82 | self.authorUrl = ko.computed(function () { 83 | return 'http://github.com/' + self.author; 84 | }); 85 | 86 | self.nugetUrl = ko.computed(function() { 87 | return 'http://nuget.org/packages/' + self.name; 88 | }); 89 | 90 | self.demoName = ko.computed(function () { 91 | return self.name.replace('Nancy.Demo.', ''); 92 | }); 93 | }; 94 | 95 | ko.bindingHandlers.modal = { 96 | update: function (element, valueAccessor) { 97 | $(element).click(function () { 98 | 99 | var content = 100 | $($('.content', $(element).parent()).html()); 101 | 102 | var originalDescription = 103 | $(".description", $(element).parent()).triggerHandler("originalContent").text(); 104 | 105 | $(".description", content).html(originalDescription); 106 | 107 | $.fancybox({ 108 | content: $('
').addClass('list-widget').html(content) 109 | }); 110 | }); 111 | } 112 | }; 113 | 114 | ko.bindingHandlers.ellipsis = { 115 | update: function(element, valueAccessor, allBindingsAccessor) { 116 | 117 | var $element = $(element), 118 | list = ko.utils.unwrapObservable(allBindingsAccessor().foreach) 119 | 120 | if (!list.length) 121 | return 122 | 123 | $(".widget .description").dotdotdot({watch:true}); 124 | } 125 | }; 126 | 127 | function DemosViewModel() { 128 | var self = this; 129 | 130 | self.demos = ko.observableArray(); 131 | 132 | $.getJSON("/api/demos", function (response) { 133 | var mapped = $.map(response, function (demo) { 134 | return new DemoModel(demo); 135 | }); 136 | self.demos(mapped); 137 | }); 138 | }; 139 | 140 | @EndSection -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/js/jquery.dotdotdot-1.5.6-packed.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery dotdotdot 1.5.6 3 | * 4 | * Copyright (c) 2013 Fred Heusschen 5 | * www.frebsite.nl 6 | * 7 | * Plugin website: 8 | * dotdotdot.frebsite.nl 9 | * 10 | * Dual licensed under the MIT and GPL licenses. 11 | * http://en.wikipedia.org/wiki/MIT_License 12 | * http://en.wikipedia.org/wiki/GNU_General_Public_License 13 | */ 14 | 15 | 16 | eval(function(p,a,c,k,e,r){e=function(c){return(c35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(6($){4($.F.u){5}$.F.u=6(o){4(s.y==0){1e(D,\'1U 1V 1W 11 "\'+s.1X+\'".\');5 s}4(s.y>1){5 s.1Y(6(){$(s).u(o)})}7 d=s;4(d.T(\'u\')){d.M(\'1z.x\')}d.1A=6(){d.U(\'N.x\',6(e,c){e.12();e.13();r.1f=(8 r.A==\'1Z\')?r.A:1B(d);r.1f+=r.1C;4(8 c!=\'B\'){4(8 c==\'1g\'||c 1D 20){c=$(\'<1h />\').G(c).H()}4(c 1D $){f=c}}$C=d.21(\'<1h 22="u" />\').V();$C.14().G(f.1E(D)).1F({\'A\':\'1G\',\'I\':\'1G\',\'23\':\'24\',\'25\':0,\'26\':0});7 a=9,O=9;4(w.15){a=w.15.1E(D);w.15.E()}4(W($C,r)){4(r.1i==\'V\'){O=V($C,r,a)}v{O=P($C,d,$C,r,a)}}$C.27($C.H());$C=Q;4($.28(r.1j)){r.1j.J(d[0],O,f)}w.t=O;5 O}).U(\'t.x\',6(e,a){e.12();e.13();4(8 a==\'6\'){a.J(d[0],w.t)}5 w.t}).U(\'29.x\',6(e,a){e.12();e.13();4(8 a==\'6\'){a.J(d[0],f)}5 f}).U(\'1z.x\',6(e){e.12();e.13();d.1k().1H().14().G(f).T(\'u\',9)});5 d};d.1H=6(){d.1I(\'.x\');5 d};d.X=6(){d.1k();4(r.X==\'R\'){7 b=$(R),1l=b.I(),1m=b.A();b.U(\'1J.x\'+w.1n,6(){4(1l!=b.I()||1m!=b.A()||!r.1K){1l=b.I();1m=b.A();4(K){1L(K)}K=2a(6(){d.M(\'N.x\')},10)}})}v{Y=16(d);K=2b(6(){7 a=16(d);4(Y.I!=a.I||Y.A!=a.A){d.M(\'N.x\');Y=16(d)}},2c)}5 d};d.1k=6(){$(R).1I(\'1J.x\'+w.1n);4(K){1L(K)}5 d};7 f=d.H(),r=$.2d(D,{},$.F.u.1M,o),w={},Y={},K=Q,$C=Q;w.15=1N(r.1o,d);w.t=9;w.1n=n++;d.T(\'u\',D).1A().M(\'N.x\');4(r.X){d.X()}5 d};$.F.u.1M={\'P\':\'... \',\'1i\':\'2e\',\'1p\':{\'E\':[\' \',\',\',\';\',\'.\',\'!\',\'?\'],\'1O\':[]},\'1C\':0,\'1j\':Q,\'1o\':Q,\'A\':Q,\'X\':9,\'1K\':D,\'1e\':9};7 n=1;6 V(b,o,c){7 d=b.V(),t=9;b.14();11(7 a=0,l=d.y;aj){7 k=i.H().1q(-1-j);f=1s(k,b,c,o,d)}v{7 e=i.2G().H().1q(-1)[0];4(8 e!=\'B\'){7 h=1u(1t(e),o);1a(e,h);i.E();f=D}}}5 f}6 W(a,o){5 a.1v()>o.1f}6 1u(a,o){1Q($.1S(a.Z(-1),o.1p.E)>-1){a=a.Z(0,-1)}4($.1S(a.Z(-1),o.1p.1O)<0){a+=o.P}5 a}6 16(a){5{\'I\':a.2H(),\'A\':a.1v()}}6 1a(e,a){4(e.1b){e.1b=a}v 4(e.1c){e.1c=a}v 4(e.1d){e.1d=a}}6 1t(e){4(e.1b){5 e.1b}v 4(e.1c){5 e.1c}v 4(e.1d){5 e.1d}v{5""}}6 1N(e,a){4(8 e==\'B\'){5 9}4(!e){5 9}4(8 e==\'1g\'){e=$(e,a);5(e.y)?e:9}4(8 e==\'1P\'){5(8 e.2I==\'B\')?9:e}5 9}6 1B(b){7 h=b.1v(),a=[\'2J\',\'2K\'];11(7 z=0,l=a.y;z\');b.1y(a);a=b.1x();b.E();5 s.M(\'N\',[a])}5 q.J(s,a)}5 q.J(s)}})(2N);',62,174,'||||if|return|function|var|typeof|false||||||||||||||||||opts|this|isTruncated|dotdotdot|else|conf|dot|length||height|undefined|inr|true|remove|fn|append|contents|width|call|watchInt|midPos|trigger|update|trunc|ellipsis|null|window|textArr|data|bind|children|test|watch|watchOrg|slice||for|preventDefault|stopPropagation|empty|afterElement|getSizes|position|startPos|endPos|setTextContent|innerText|nodeValue|textContent|debug|maxHeight|string|div|wrap|callback|unwatch|_wWidth|_wHeight|dotId|after|lastCharacter|eq|break|ellipsisElement|getTextContent|addEllipsis|innerHeight|console|html|text|destroy|bind_events|getTrueInnerHeight|tolerance|instanceof|clone|css|auto|unbind_events|unbind|resize|windowResizeFix|clearInterval|defaults|getElement|noEllipsis|object|while|join|inArray|log|No|element|found|selector|each|number|HTMLElement|wrapInner|class|border|none|padding|margin|replaceWith|isFunction|originalContent|setTimeout|setInterval|100|extend|word|table|thead|tbody|tfoot|tr|col|colgroup|embed|param|ol|ul|dl|select|optgroup|option|textarea|script|style|continue|is|nodeType|letter|split|Math|floor|parent|size|prev|innerWidth|jquery|paddingTop|paddingBottom|parseInt|isNaN|jQuery'.split('|'),0,{})) -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/ConfigLoader.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples 2 | { 3 | using System; 4 | using System.ComponentModel; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | 9 | /// 10 | /// Populates a confinguration object from a text file. 11 | /// Each line in the file is of the format "PropertyName:Value" (without the quotes) 12 | /// and ignores any lines starting with # 13 | /// 14 | public static class ConfigLoader 15 | { 16 | private const BindingFlags PublicStaticIgnoreCase = BindingFlags.IgnoreCase | BindingFlags.Static | BindingFlags.Public; 17 | 18 | private const BindingFlags PublicInstanceIgnoreCase = BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public; 19 | 20 | /// 21 | /// Populates a confinguration object from a text file. 22 | /// Each line in the file is of the format "PropertyName:Value" (without the quotes) 23 | /// and ignores any lines starting with # 24 | /// 25 | /// Filename to load from, if the file does not exist no work is done 26 | /// Object to populate 27 | public static void Load(string filename, object configurationObject) 28 | { 29 | if (!File.Exists(filename) || configurationObject == null) 30 | { 31 | return; 32 | } 33 | 34 | var configEntries = File.ReadAllLines(filename) 35 | .Where(l => !l.StartsWith("#")) 36 | .Select(l => l.Split(new[] { ':' }, 2, StringSplitOptions.RemoveEmptyEntries)) 37 | .ToArray() 38 | .Where(c => c.Length == 2); 39 | 40 | foreach (var configEntry in configEntries) 41 | { 42 | SetEntry(configEntry[0].Trim(), configEntry[1].Trim(), configurationObject); 43 | } 44 | } 45 | 46 | private static void SetEntry(string key, string value, object configurationObject) 47 | { 48 | if (SetStaticProperty(key, value, configurationObject)) 49 | { 50 | return; 51 | } 52 | 53 | SetInstanceProperty(key, value, configurationObject); 54 | } 55 | 56 | private static bool SetStaticProperty(string key, string value, object configurationObject) 57 | { 58 | var property = configurationObject.GetType() 59 | .GetProperty(key, PublicStaticIgnoreCase); 60 | 61 | if (property == null) 62 | { 63 | return false; 64 | } 65 | 66 | try 67 | { 68 | var convertedValue = Convert(value, property.PropertyType); 69 | 70 | property.SetValue(configurationObject, convertedValue, null); 71 | 72 | return true; 73 | } 74 | catch (Exception) 75 | { 76 | return false; 77 | } 78 | } 79 | 80 | private static bool SetInstanceProperty(string key, string value, object configurationObject) 81 | { 82 | var property = configurationObject.GetType() 83 | .GetProperty(key, PublicInstanceIgnoreCase); 84 | 85 | if (property == null) 86 | { 87 | return false; 88 | } 89 | 90 | try 91 | { 92 | var convertedValue = Convert(value, property.PropertyType); 93 | 94 | property.SetValue(configurationObject, convertedValue, null); 95 | 96 | return true; 97 | } 98 | catch (Exception) 99 | { 100 | return false; 101 | } 102 | } 103 | 104 | private static object Convert(string input, Type destinationType) 105 | { 106 | if (destinationType == typeof (string)) 107 | { 108 | return input; 109 | } 110 | 111 | var converter = TypeDescriptor.GetConverter(destinationType); 112 | 113 | if (converter == null || !converter.CanConvertFrom(typeof(string))) 114 | { 115 | return null; 116 | } 117 | 118 | try 119 | { 120 | return converter.ConvertFrom(input); 121 | } 122 | catch (FormatException) 123 | { 124 | if (destinationType == typeof(bool) && converter.GetType() == typeof(BooleanConverter) && "on".Equals(input, StringComparison.OrdinalIgnoreCase)) 125 | { 126 | return true; 127 | } 128 | return null; 129 | } 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/js/jquery.masonry.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jQuery Masonry v2.1.06 3 | * A dynamic layout plugin for jQuery 4 | * The flip-side of CSS Floats 5 | * http://masonry.desandro.com 6 | * 7 | * Licensed under the MIT license. 8 | * Copyright 2012 David DeSandro 9 | */ 10 | (function(a,b,c){"use strict";var d=b.event,e;d.special.smartresize={setup:function(){b(this).bind("resize",d.special.smartresize.handler)},teardown:function(){b(this).unbind("resize",d.special.smartresize.handler)},handler:function(a,c){var d=this,f=arguments;a.type="smartresize",e&&clearTimeout(e),e=setTimeout(function(){b.event.handle.apply(d,f)},c==="execAsap"?0:100)}},b.fn.smartresize=function(a){return a?this.bind("smartresize",a):this.trigger("smartresize",["execAsap"])},b.Mason=function(a,c){this.element=b(c),this._create(a),this._init()},b.Mason.settings={isResizable:!0,isAnimated:!1,animationOptions:{queue:!1,duration:500},gutterWidth:0,isRTL:!1,isFitWidth:!1,containerStyle:{position:"relative"}},b.Mason.prototype={_filterFindBricks:function(a){var b=this.options.itemSelector;return b?a.filter(b).add(a.find(b)):a},_getBricks:function(a){var b=this._filterFindBricks(a).css({position:"absolute"}).addClass("masonry-brick");return b},_create:function(c){this.options=b.extend(!0,{},b.Mason.settings,c),this.styleQueue=[];var d=this.element[0].style;this.originalStyle={height:d.height||""};var e=this.options.containerStyle;for(var f in e)this.originalStyle[f]=d[f]||"";this.element.css(e),this.horizontalDirection=this.options.isRTL?"right":"left";var g=this.element.css("padding-"+this.horizontalDirection),h=this.element.css("padding-top");this.offset={x:g?parseInt(g,10):0,y:h?parseInt(h,10):0},this.isFluid=this.options.columnWidth&&typeof this.options.columnWidth=="function";var i=this;setTimeout(function(){i.element.addClass("masonry")},0),this.options.isResizable&&b(a).bind("smartresize.masonry",function(){i.resize()}),this.reloadItems()},_init:function(a){this._getColumns(),this._reLayout(a)},option:function(a,c){b.isPlainObject(a)&&(this.options=b.extend(!0,this.options,a))},layout:function(a,b){for(var c=0,d=a.length;c 2 | 3 | 4 | Nancy.Demo.Samples 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 144 | 145 | 146 | 147 | 148 | 171 | 172 |
173 | @Section['Content'] 174 |
175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Data/DefaultDemoModelFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Nancy.Demo.Samples.Data 2 | { 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text.RegularExpressions; 7 | using Nancy.Helpers; 8 | using MarkdownSharp; 9 | using Nancy.Demo.Samples.Models; 10 | using Net; 11 | 12 | /// 13 | /// Default implementation of the interface. This implemenation will 14 | /// look for repositories that followes the Name.Demo.ProjectName naming convention. 15 | /// 16 | public class DefaultDemoModelFactory : IDemoModelFactory 17 | { 18 | private readonly IGitHubHttpClient client; 19 | private readonly IGitHubFileContentExtractor githubFileContentExtractor; 20 | private readonly IRepositoryNugetChecker repositoryNugetChecker; 21 | 22 | private readonly Regex assemblyVersionPattern = new Regex(@"AssemblyVersion\(\""(?[0-9\.]*)\""\)", RegexOptions.Compiled); 23 | private readonly Regex nugetPackagesPattern = new Regex("(?:id=\"(?Nancy(?:.+?)?)\" version=\"(?.+?)\")", RegexOptions.Multiline | RegexOptions.Compiled); 24 | private readonly Regex readMePattern = new Regex(@"[\`]{3}(?.+?)(?:[\n\r]+)(?.+?)(?:[\n\r]+)[\`]{3}", RegexOptions.Singleline | RegexOptions.Compiled); 25 | 26 | /// 27 | /// Creates a new instance of the class, using the provided 28 | /// , and . 29 | /// 30 | /// The that should be used to communicate with GitHub. 31 | /// 32 | /// The that should be used to verify that a Nuget is available for the demo. 33 | public DefaultDemoModelFactory(IGitHubHttpClient client, IGitHubFileContentExtractor githubFileContentExtractor, IRepositoryNugetChecker repositoryNugetChecker) 34 | { 35 | this.client = client; 36 | this.githubFileContentExtractor = githubFileContentExtractor; 37 | this.repositoryNugetChecker = repositoryNugetChecker; 38 | } 39 | 40 | /// 41 | /// Retrieves information about Nancy demo projects, from the GitHub account that is 42 | /// identified with the provided . 43 | /// 44 | /// The username that should be queried. 45 | /// An , containing instances. 46 | public IEnumerable Retrieve(string username) 47 | { 48 | var url = 49 | string.Format("users/{0}/repos", username); 50 | 51 | var data = 52 | this.client.Get(url); 53 | 54 | return CreateDemosModels(data); 55 | } 56 | 57 | private IEnumerable CreateDemosModels(dynamic result) 58 | { 59 | var demos = ((IEnumerable)result) 60 | .Where(repo => repo.name.StartsWith("Nancy.Demo", StringComparison.OrdinalIgnoreCase)) 61 | .Where(repo => ((bool)repo.fork) == false) 62 | .Select(repo => new DemoModel { 63 | Id = Guid.NewGuid().ToString(), 64 | Name = repo.name, 65 | CreatedAt = DateTime.Parse(repo.created_at), 66 | Description = repo.description, 67 | Author = repo.owner.login, 68 | Gravatar = repo.owner.avatar_url, 69 | HasNuget = this.repositoryNugetChecker.IsNugetAvailable(repo.name), 70 | IndexedAt = DateTime.Now, 71 | LastCommit = DateTime.Parse(repo.updated_at), 72 | Url = repo.html_url, 73 | Packages = this.ExtractNugetPackages(repo.owner.login, repo.name), 74 | Readme = this.ExtractReadMe(repo.owner.login, repo.name), 75 | Version = this.ExtractVersion(repo.owner.login, repo.name) 76 | }); 77 | 78 | return GetValid(demos.ToArray()); 79 | } 80 | 81 | private static IEnumerable GetValid(IEnumerable demos) 82 | { 83 | return demos; 84 | //.Where(demo => !string.IsNullOrWhiteSpace(demo.Readme)) 85 | //.Where(demo => !string.IsNullOrWhiteSpace(demo.Version)) 86 | //.Where(demo => !string.IsNullOrWhiteSpace(demo.Description)); 87 | } 88 | 89 | private IEnumerable ExtractNugetPackages(string owner, string repositoryName) 90 | { 91 | var relativeFilePath = 92 | string.Format("contents/src/{0}/packages.config", repositoryName); 93 | 94 | return this.githubFileContentExtractor.Extract(owner, repositoryName, relativeFilePath, content => 95 | { 96 | if (string.IsNullOrWhiteSpace(content)) 97 | { 98 | return Enumerable.Empty(); 99 | } 100 | 101 | return nugetPackagesPattern.Matches(content) 102 | .OfType() 103 | .Select(match => new NugetPackageInformation { 104 | Name = match.Groups["name"].Value, 105 | Version = match.Groups["version"].Value}); 106 | }); 107 | } 108 | 109 | private string ExtractReadMe(string owner, string repositoryName) 110 | { 111 | return this.githubFileContentExtractor.Extract(owner, repositoryName, "readme", content => 112 | { 113 | if (string.IsNullOrWhiteSpace(content)) 114 | { 115 | return string.Empty; 116 | } 117 | 118 | content = 119 | HttpUtility.HtmlEncode(content); 120 | 121 | content = 122 | readMePattern.Replace(content, capture => 123 | { 124 | var value = capture.Groups[0] 125 | .Value 126 | .Replace(string.Concat("```", capture.Groups["language"]), string.Empty) 127 | .Replace("```", string.Empty) 128 | .Trim(new[] {'\r', '\n'}); 129 | 130 | return string.Concat("
", value, "
"); 131 | }); 132 | 133 | var renderer = 134 | new Markdown(); 135 | 136 | return renderer.Transform(content); 137 | }); 138 | } 139 | 140 | 141 | private string ExtractVersion(string owner, string repositoryName) 142 | { 143 | var relativeFilePath = 144 | string.Format("contents/src/{0}/Properties/AssemblyInfo.cs", repositoryName); 145 | 146 | return this.githubFileContentExtractor.Extract(owner, repositoryName, relativeFilePath, content => 147 | { 148 | return !string.IsNullOrWhiteSpace(content) 149 | ? this.assemblyVersionPattern.Match(content).Groups["version"].Value 150 | : string.Empty; 151 | }); 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Nancy.Demo.Samples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | 8 | 9 | 2.0 10 | {EB6E1B40-53CE-4B0D-AD20-22C44D636FB1} 11 | {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 12 | Library 13 | Properties 14 | Nancy.Demo.Samples 15 | Nancy.Demo.Samples 16 | v4.0 17 | true 18 | 19 | 20 | 21 | 22 | 23 | 24 | true 25 | full 26 | false 27 | bin\ 28 | DEBUG;TRACE 29 | prompt 30 | 4 31 | 32 | 33 | pdbonly 34 | true 35 | bin\ 36 | TRACE 37 | prompt 38 | 4 39 | 40 | 41 | 42 | ..\packages\MarkdownSharp.1.13.0.0\lib\35\MarkdownSharp.dll 43 | 44 | 45 | 46 | ..\packages\mongocsharpdriver.1.7\lib\net35\MongoDB.Bson.dll 47 | 48 | 49 | ..\packages\mongocsharpdriver.1.7\lib\net35\MongoDB.Driver.dll 50 | 51 | 52 | False 53 | ..\packages\Nancy.0.16.1\lib\net40\Nancy.dll 54 | 55 | 56 | ..\packages\Nancy.Authentication.Forms.0.16.1\lib\net40\Nancy.Authentication.Forms.dll 57 | 58 | 59 | ..\packages\Nancy.Hosting.Aspnet.0.16.1\lib\net40\Nancy.Hosting.Aspnet.dll 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | Designer 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | Web.config 135 | 136 | 137 | Web.config 138 | 139 | 140 | 141 | 142 | 143 | 144 | 10.0 145 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | True 155 | True 156 | 45579 157 | / 158 | http://localhost:18603/ 159 | False 160 | False 161 | 162 | 163 | False 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 179 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/js/moment.min.js: -------------------------------------------------------------------------------- 1 | // moment.js 2 | // version : 1.7.2 3 | // author : Tim Wood 4 | // license : MIT 5 | // momentjs.com 6 | (function(a){function E(a,b,c,d){var e=c.lang();return e[a].call?e[a](c,d):e[a][b]}function F(a,b){return function(c){return K(a.call(this,c),b)}}function G(a){return function(b){var c=a.call(this,b);return c+this.lang().ordinal(c)}}function H(a,b,c){this._d=a,this._isUTC=!!b,this._a=a._a||null,this._lang=c||!1}function I(a){var b=this._data={},c=a.years||a.y||0,d=a.months||a.M||0,e=a.weeks||a.w||0,f=a.days||a.d||0,g=a.hours||a.h||0,h=a.minutes||a.m||0,i=a.seconds||a.s||0,j=a.milliseconds||a.ms||0;this._milliseconds=j+i*1e3+h*6e4+g*36e5,this._days=f+e*7,this._months=d+c*12,b.milliseconds=j%1e3,i+=J(j/1e3),b.seconds=i%60,h+=J(i/60),b.minutes=h%60,g+=J(h/60),b.hours=g%24,f+=J(g/24),f+=e*7,b.days=f%30,d+=J(f/30),b.months=d%12,c+=J(d/12),b.years=c,this._lang=!1}function J(a){return a<0?Math.ceil(a):Math.floor(a)}function K(a,b){var c=a+"";while(c.length70?1900:2e3);break;case"YYYY":c[0]=~~Math.abs(b);break;case"a":case"A":d.isPm=(b+"").toLowerCase()==="pm";break;case"H":case"HH":case"h":case"hh":c[3]=~~b;break;case"m":case"mm":c[4]=~~b;break;case"s":case"ss":c[5]=~~b;break;case"S":case"SS":case"SSS":c[6]=~~(("0."+b)*1e3);break;case"Z":case"ZZ":d.isUTC=!0,e=(b+"").match(x),e&&e[1]&&(d.tzh=~~e[1]),e&&e[2]&&(d.tzm=~~e[2]),e&&e[0]==="+"&&(d.tzh=-d.tzh,d.tzm=-d.tzm)}b==null&&(c[8]=!1)}function W(a,b){var c=[0,0,1,0,0,0,0],d={tzh:0,tzm:0},e=b.match(k),f,g;for(f=0;f0,j[4]=c,Z.apply({},j)}function _(a,c){b.fn[a]=function(a){var b=this._isUTC?"UTC":"";return a!=null?(this._d["set"+b+c](a),this):this._d["get"+b+c]()}}function ab(a){b.duration.fn[a]=function(){return this._data[a]}}function bb(a,c){b.duration.fn["as"+a]=function(){return+this/c}}var b,c="1.7.2",d=Math.round,e,f={},g="en",h=typeof module!="undefined"&&module.exports,i="months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem".split("|"),j=/^\/?Date\((\-?\d+)/i,k=/(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,l=/(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,m=/([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,n=/\d\d?/,o=/\d{1,3}/,p=/\d{3}/,q=/\d{1,4}/,r=/[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i,s=/Z|[\+\-]\d\d:?\d\d/i,t=/T/i,u=/^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,v="YYYY-MM-DDTHH:mm:ssZ",w=[["HH:mm:ss.S",/T\d\d:\d\d:\d\d\.\d{1,3}/],["HH:mm:ss",/T\d\d:\d\d:\d\d/],["HH:mm",/T\d\d:\d\d/],["HH",/T\d\d/]],x=/([\+\-]|\d\d)/gi,y="Month|Date|Hours|Minutes|Seconds|Milliseconds".split("|"),z={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},A={},B="DDD w M D d".split(" "),C="M D H h m s w".split(" "),D={M:function(){return this.month()+1},MMM:function(a){return E("monthsShort",this.month(),this,a)},MMMM:function(a){return E("months",this.month(),this,a)},D:function(){return this.date()},DDD:function(){var a=new Date(this.year(),this.month(),this.date()),b=new Date(this.year(),0,1);return~~((a-b)/864e5+1.5)},d:function(){return this.day()},dd:function(a){return E("weekdaysMin",this.day(),this,a)},ddd:function(a){return E("weekdaysShort",this.day(),this,a)},dddd:function(a){return E("weekdays",this.day(),this,a)},w:function(){var a=new Date(this.year(),this.month(),this.date()-this.day()+5),b=new Date(a.getFullYear(),0,4);return~~((a-b)/864e5/7+1.5)},YY:function(){return K(this.year()%100,2)},YYYY:function(){return K(this.year(),4)},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return~~(this.milliseconds()/100)},SS:function(){return K(~~(this.milliseconds()/10),2)},SSS:function(){return K(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(a/60),2)+":"+K(~~a%60,2)},ZZ:function(){var a=-this.zone(),b="+";return a<0&&(a=-a,b="-"),b+K(~~(10*a/6),4)}};while(B.length)e=B.pop(),D[e+"o"]=G(D[e]);while(C.length)e=C.pop(),D[e+e]=F(D[e],2);D.DDDD=F(D.DDD,3),b=function(c,d){if(c===null||c==="")return null;var e,f;return b.isMoment(c)?new H(new Date(+c._d),c._isUTC,c._lang):(d?M(d)?e=X(c,d):e=W(c,d):(f=j.exec(c),e=c===a?new Date:f?new Date(+f[1]):c instanceof Date?c:M(c)?O(c):typeof c=="string"?Y(c):new Date(c)),new H(e))},b.utc=function(a,c){return M(a)?new H(O(a,!0),!0):(typeof a=="string"&&!s.exec(a)&&(a+=" +0000",c&&(c+=" Z")),b(a,c).utc())},b.unix=function(a){return b(a*1e3)},b.duration=function(a,c){var d=b.isDuration(a),e=typeof a=="number",f=d?a._data:e?{}:a,g;return e&&(c?f[c]=a:f.milliseconds=a),g=new I(f),d&&(g._lang=a._lang),g},b.humanizeDuration=function(a,c,d){return b.duration(a,c===!0?null:c).humanize(c===!0?!0:d)},b.version=c,b.defaultFormat=v,b.lang=function(a,c){var d;if(!a)return g;(c||!f[a])&&P(a,c);if(f[a]){for(d=0;d11?c?"pm":"PM":c?"am":"AM"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10;return~~(a%100/10)===1?"th":b===1?"st":b===2?"nd":b===3?"rd":"th"}}),b.fn=H.prototype={clone:function(){return b(this)},valueOf:function(){return+this._d},unix:function(){return Math.floor(+this._d/1e3)},toString:function(){return this._d.toString()},toDate:function(){return this._d},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds(),!!this._isUTC]},isValid:function(){return this._a?this._a[8]!=null?!!this._a[8]:!N(this._a,(this._a[7]?b.utc(this._a):b(this._a)).toArray()):!isNaN(this._d.getTime())},utc:function(){return this._isUTC=!0,this},local:function(){return this._isUTC=!1,this},format:function(a){return T(this,a?a:b.defaultFormat)},add:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,1),this},subtract:function(a,c){var d=c?b.duration(+c,a):b.duration(a);return L(this,d,-1),this},diff:function(a,c,e){var f=this._isUTC?b(a).utc():b(a).local(),g=(this.zone()-f.zone())*6e4,h=this._d-f._d-g,i=this.year()-f.year(),j=this.month()-f.month(),k=this.date()-f.date(),l;return c==="months"?l=i*12+j+k/30:c==="years"?l=i+(j+k/30)/12:l=c==="seconds"?h/1e3:c==="minutes"?h/6e4:c==="hours"?h/36e5:c==="days"?h/864e5:c==="weeks"?h/6048e5:h,e?l:d(l)},from:function(a,c){return b.duration(this.diff(a)).lang(this._lang).humanize(!c)},fromNow:function(a){return this.from(b(),a)},calendar:function(){var a=this.diff(b().sod(),"days",!0),c=this.lang().calendar,d=c.sameElse,e=a<-6?d:a<-1?c.lastWeek:a<0?c.lastDay:a<1?c.sameDay:a<2?c.nextDay:a<7?c.nextWeek:d;return this.format(typeof e=="function"?e.apply(this):e)},isLeapYear:function(){var a=this.year();return a%4===0&&a%100!==0||a%400===0},isDST:function(){return this.zone() GetAsyncAwaitSample(CancellationToken cancellationToken = default(CancellationToken)) 70 | { 71 | var httpHelper = new HttpHelper("https://graph.facebook.com/4"); 72 | 73 | using (var stream = await httpHelper.OpenReadTaskAsync(cancellationToken)) 74 | { 75 | using (var reader = new StreamReader(stream)) 76 | { 77 | return reader.ReadToEnd(); 78 | } 79 | } 80 | } 81 | ``` 82 | 83 | #### Asynchronous Sample with Task Parallel Library (TPL) 84 | 85 | *Available only in .NET 4.0+, SL5 and WinRT (Windows Metro Apps)* 86 | 87 | Make an asynchrounous GET request to https://graph.facebook.com/4 and return the response as task of string. 88 | 89 | `HTTPHELPER_TPL` conditional compilation symbol must be defined in order to use XTaskAsync methods. 90 | 91 | ```csharp 92 | public static Task GetAsyncTaskSample(CancellationToken cancellationToken = default(CancellationToken)) 93 | { 94 | var httpHelper = new HttpHelper("https://graph.facebook.com/4"); 95 | 96 | return httpHelper 97 | .OpenReadTaskAsync(cancellationToken) 98 | .ContinueWith(t => 99 | { 100 | // propagate previous task exceptions correctly. 101 | if (t.IsFaulted || t.IsCanceled) t.Wait(); 102 | 103 | using (var stream = t.Result) 104 | { 105 | using (var reader = new StreamReader(stream)) 106 | { 107 | return reader.ReadToEnd(); 108 | } 109 | } 110 | }); 111 | } 112 | ``` 113 | 114 | #### Asynchronous Sample with Event Programming Model (EPM) 115 | 116 | *Available in all .NET plaforms.* 117 | 118 | Make an asynchrounous GET request to https://graph.facebook.com/4 and call the callback on completion. 119 | `Action` is mapped to response string, userState, isCancelled and Exception. 120 | 121 | ```csharp 122 | public static void GetAsyncSample(Action callback = null, object userState = null) 123 | { 124 | var httpHelper = new HttpHelper("https://graph.facebook.com/4"); 125 | 126 | httpHelper.OpenReadCompleted += 127 | (o, e) => 128 | { 129 | if (callback == null) 130 | { 131 | // make sure to dispose the response stream 132 | if(!e.Cancelled && e.Error != null) 133 | using (var stream = e.Result) { } 134 | return; 135 | } 136 | 137 | if (e.Cancelled) 138 | callback(null, e.UserState, true, null); 139 | else if (e.Error != null) 140 | callback(null, e.UserState, false, e.Error); 141 | else 142 | { 143 | try 144 | { 145 | using (var stream = e.Result) 146 | { 147 | using (var reader = new StreamReader(stream)) 148 | { 149 | callback(reader.ReadToEnd(), e.UserState, false, null); 150 | } 151 | } 152 | } 153 | catch (Exception ex) 154 | { 155 | callback(null, e.UserState, false, ex); 156 | } 157 | } 158 | }; 159 | 160 | httpHelper.OpenReadAsync(userState); 161 | } 162 | ``` 163 | 164 | You can cancel the asynchronous requests for EPM using `httpHelper.CancelAsync()` method. 165 | 166 | ### HTTP POST 167 | 168 | #### Synchronous Sample 169 | 170 | *Synchronous methods are not supported in Silverlight/Windows Phone/WinRT (Windows Metro Apps)* 171 | 172 | Make a POST request to https://graph.facebook.com/me/feed and return the response as string. 173 | For the below sample you can get the `access_token` from http://developers.facebook.com/tools/explorer/ 174 | Make sure you have `publish_stream` extended permission which is required to post to your facebook wall. 175 | 176 | `HTTPHELPER_URLENCODING` conditional compilation symbol must be defined in order to use 177 | `HttpHelper.UrlEncode` or `HttpHelper.UrlDecode` methods. 178 | 179 | Windows Phone and WinRT (Windows Metro Apps) do not have the property ContentLength for HttpWebRequest. In order to reduce 180 | the `#if (WINDOWS_PHONE || NETFX_CORE)` you can use the `TrySetContentLength` method. 181 | 182 | ```csharp 183 | public static string PostSyncSample(IEnumerable> parameters) 184 | { 185 | var httpHelper = new HttpHelper("https://graph.facebook.com/me/feed"); 186 | var request = httpHelper.HttpWebRequest; 187 | request.Method = "POST"; 188 | request.ContentType = "application/form-url-encoded"; 189 | 190 | var bodyString = new StringBuilder(); 191 | foreach (var kvp in parameters) 192 | bodyString.AppendFormat("{0}={1}&", HttpHelper.UrlEncode(kvp.Key), HttpHelper.UrlEncode(kvp.Value)); 193 | if (bodyString.Length > 0) 194 | bodyString.Length -= 1; 195 | 196 | var bodyByteArray = Encoding.UTF8.GetBytes(bodyString.ToString()); 197 | request.TrySetContentLength(bodyByteArray.Length); 198 | 199 | // write to request body only if we have data, otherwise directly open the read stream 200 | if (bodyByteArray.Length > 0) 201 | { 202 | using (var stream = httpHelper.OpenWrite()) 203 | { 204 | stream.Write(bodyByteArray, 0, bodyByteArray.Length); 205 | } 206 | } 207 | 208 | using (var stream = httpHelper.OpenRead()) 209 | { 210 | using (var reader = new StreamReader(stream)) 211 | { 212 | return reader.ReadToEnd(); 213 | } 214 | } 215 | } 216 | 217 | var parameters = new Dictionary(); 218 | parameters["message"] = "Hi from HttpHelper"; 219 | parameters["access_token"] = ""; 220 | var result = PostSyncSample(parameters); 221 | Console.WriteLine(result); 222 | ``` 223 | 224 | ## Twitter OAuth Sample 225 | 226 | HttpHelper includes some basic helper methods for oauth 1.0. 227 | 228 | Here is a sample on getting the request token from twitter. 229 | 230 | *Note: `GenerateOAuthAuthenticationHeader` will auto generate timestamps/oauth nonce values if you pass it as null. You can either manually pass your own value or use the helper methods such as `HttpHelper.GenerateOAuthNonce()`, `HttpHelper.GenerateOAuthTimestamp`. Since HMAC-SHA1 is not avaialble in the portable library, you will need to add reference to [Portable Library Contrib project](http://pclcontrib.codeplex.com/) and pass the appropriate `HmacSha1Delegate`.* 231 | 232 | *Make sure add `#define HTTPHELPER_TPL` if you want to use `OpenReadTaskAsync` method.* 233 | 234 | ```csharp 235 | public static async Task> GetRequestToken(string consumerKey, string consumerSecret, CancellationToken cancellationToken = default (CancellationToken)) 236 | { 237 | var requestTokenUri = new Uri("https://api.twitter.com/oauth/request_token"); 238 | 239 | var httHelper = new HttpHelper(requestTokenUri); 240 | var request = httHelper.HttpWebRequest; 241 | request.Method = "POST"; 242 | request.ContentType = "application/json"; 243 | 244 | request.Headers["Authorization"] = HttpHelper.GenerateOAuthAuthenticationHeader( 245 | "POST", requestTokenUri, null, 246 | consumerKey, consumerSecret, 247 | null, null, 248 | "HMAC-SHA1", null, null, null, null); 249 | 250 | using (var stream = await httHelper.OpenReadTaskAsync(cancellationToken)) 251 | { 252 | using (var reader = new StreamReader(stream)) 253 | { 254 | var response = await reader.ReadToEndAsync(); 255 | 256 | var kvp = response.Split('&'); 257 | var dict = new Dictionary(); 258 | foreach (var s in kvp) 259 | { 260 | var pair = s.Split('='); 261 | if (pair.Length == 2) 262 | dict[pair[0]] = pair[1]; 263 | } 264 | 265 | return dict; 266 | } 267 | } 268 | } 269 | ``` 270 | 271 | Then generate the login url and open it in the browser. 272 | 273 | ```csharp 274 | var requestTokenResult = await GetRequestToken("consumerKey", "consumerSecret"); 275 | 276 | string token = requestTokenResult["oauth_token"]; 277 | string tokenSecret = requestTokenResult["oauth_token_secret"]; 278 | 279 | Process.Start("https://api.twitter.com/oauth/authorize?oauth_token=" + token); 280 | ``` 281 | 282 | Once you have granted access you will get some random pin number. Then get the access token use the pin. 283 | 284 | ```csharp 285 | public static async Task> GetAccessToken(string consumerKey, string consumerSecret, string token, string tokenSecret, string oauthVerifierPin, CancellationToken cancellationToken = default (CancellationToken)) 286 | { 287 | var requestTokenUri = new Uri("https://api.twitter.com/oauth/access_token"); 288 | 289 | var httHelper = new HttpHelper(requestTokenUri); 290 | var request = httHelper.HttpWebRequest; 291 | request.Method = "POST"; 292 | request.ContentType = HttpHelper.ApplicationXWWWFormUrlEncodedContentType; 293 | var data = Encoding.UTF8.GetBytes(string.Concat("oauth_verifier=", oauthVerifierPin)); 294 | request.TrySetContentLength(data.Length); 295 | 296 | var parameters = new Dictionary(); 297 | parameters["oauth_verifier"] = oauthVerifierPin; 298 | 299 | request.Headers["Authorization"] = HttpHelper.GenerateOAuthAuthenticationHeader( 300 | "POST", requestTokenUri, parameters, 301 | consumerKey, consumerSecret, 302 | token, tokenSecret, 303 | "HMAC-SHA1", null, null, null, null); 304 | 305 | using (var stream = await httHelper.OpenWriteTaskAsync(cancellationToken)) 306 | { 307 | await stream.WriteAsync(data, 0, data.Length, cancellationToken); 308 | } 309 | 310 | using (var stream = await httHelper.OpenReadTaskAsync(cancellationToken)) 311 | { 312 | using (var reader = new StreamReader(stream)) 313 | { 314 | var response = await reader.ReadToEndAsync(); 315 | 316 | var kvp = response.Split('&'); 317 | var dict = new Dictionary(); 318 | foreach (var s in kvp) 319 | { 320 | var pair = s.Split('='); 321 | if (pair.Length == 2) 322 | dict[pair[0]] = pair[1]; 323 | } 324 | 325 | return dict; 326 | } 327 | } 328 | } 329 | 330 | string pin = "..."; 331 | 332 | var accessTokenResult = await GetAccessToken(consumerKey, consumerSecret, token, tokenSecret, pin); 333 | var oauthToken = accessTokenResult["oauth_token"]; 334 | var oauthTokenSecret = accessTokenResult["oauth_token_secret"]; 335 | var userId = accessTokenResult["user_id"]; 336 | var screenName = accessTokenResult["screen_name"]; 337 | 338 | ``` 339 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/css/font-awesome.css: -------------------------------------------------------------------------------- 1 | /* Font Awesome 2 | the iconic font designed for use with Twitter Bootstrap 3 | ------------------------------------------------------- 4 | The full suite of pictographic icons, examples, and documentation 5 | can be found at: http://fortawesome.github.com/Font-Awesome/ 6 | 7 | License 8 | ------------------------------------------------------- 9 | The Font Awesome webfont, CSS, and LESS files are licensed under CC BY 3.0: 10 | http://creativecommons.org/licenses/by/3.0/ A mention of 11 | 'Font Awesome - http://fortawesome.github.com/Font-Awesome' in human-readable 12 | source code is considered acceptable attribution (most common on the web). 13 | If human readable source code is not available to the end user, a mention in 14 | an 'About' or 'Credits' screen is considered acceptable (most common in desktop 15 | or mobile software). 16 | 17 | Contact 18 | ------------------------------------------------------- 19 | Email: dave@davegandy.com 20 | Twitter: http://twitter.com/fortaweso_me 21 | Work: http://lemonwi.se co-founder 22 | 23 | */ 24 | @font-face { 25 | font-family: "FontAwesome"; 26 | src: url('../font/fontawesome-webfont.eot'); 27 | src: url('../font/fontawesome-webfont.eot?#iefix') format('eot'), url('../font/fontawesome-webfont.woff') format('woff'), url('../font/fontawesome-webfont.ttf') format('truetype'), url('../font/fontawesome-webfont.svg#FontAwesome') format('svg'); 28 | font-weight: normal; 29 | font-style: normal; 30 | } 31 | 32 | /* Font Awesome styles 33 | ------------------------------------------------------- */ 34 | [class^="icon-"]:before, [class*=" icon-"]:before { 35 | font-family: FontAwesome; 36 | font-weight: normal; 37 | font-style: normal; 38 | display: inline-block; 39 | text-decoration: inherit; 40 | } 41 | a [class^="icon-"], a [class*=" icon-"] { 42 | display: inline-block; 43 | text-decoration: inherit; 44 | } 45 | /* makes the font 33% larger relative to the icon container */ 46 | .icon-large:before { 47 | vertical-align: top; 48 | font-size: 1.3333333333333333em; 49 | } 50 | .btn [class^="icon-"], .btn [class*=" icon-"] { 51 | /* keeps button heights with and without icons the same */ 52 | 53 | line-height: .9em; 54 | } 55 | li [class^="icon-"], li [class*=" icon-"] { 56 | display: inline-block; 57 | width: 1.25em; 58 | text-align: center; 59 | } 60 | li .icon-large[class^="icon-"], li .icon-large[class*=" icon-"] { 61 | /* 1.5 increased font size for icon-large * 1.25 width */ 62 | 63 | width: 1.875em; 64 | } 65 | li[class^="icon-"], li[class*=" icon-"] { 66 | margin-left: 0; 67 | list-style-type: none; 68 | } 69 | li[class^="icon-"]:before, li[class*=" icon-"]:before { 70 | text-indent: -2em; 71 | text-align: center; 72 | } 73 | li[class^="icon-"].icon-large:before, li[class*=" icon-"].icon-large:before { 74 | text-indent: -1.3333333333333333em; 75 | } 76 | /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen 77 | readers do not read off random characters that represent icons */ 78 | .icon-glass:before { content: "\f000"; } 79 | .icon-music:before { content: "\f001"; } 80 | .icon-search:before { content: "\f002"; } 81 | .icon-envelope:before { content: "\f003"; } 82 | .icon-heart:before { content: "\f004"; } 83 | .icon-star:before { content: "\f005"; } 84 | .icon-star-empty:before { content: "\f006"; } 85 | .icon-user:before { content: "\f007"; } 86 | .icon-film:before { content: "\f008"; } 87 | .icon-th-large:before { content: "\f009"; } 88 | .icon-th:before { content: "\f00a"; } 89 | .icon-th-list:before { content: "\f00b"; } 90 | .icon-ok:before { content: "\f00c"; } 91 | .icon-remove:before { content: "\f00d"; } 92 | .icon-zoom-in:before { content: "\f00e"; } 93 | 94 | .icon-zoom-out:before { content: "\f010"; } 95 | .icon-off:before { content: "\f011"; } 96 | .icon-signal:before { content: "\f012"; } 97 | .icon-cog:before { content: "\f013"; } 98 | .icon-trash:before { content: "\f014"; } 99 | .icon-home:before { content: "\f015"; } 100 | .icon-file:before { content: "\f016"; } 101 | .icon-time:before { content: "\f017"; } 102 | .icon-road:before { content: "\f018"; } 103 | .icon-download-alt:before { content: "\f019"; } 104 | .icon-download:before { content: "\f01a"; } 105 | .icon-upload:before { content: "\f01b"; } 106 | .icon-inbox:before { content: "\f01c"; } 107 | .icon-play-circle:before { content: "\f01d"; } 108 | .icon-repeat:before { content: "\f01e"; } 109 | 110 | /* \f020 doesn't work in Safari. all shifted one down */ 111 | .icon-refresh:before { content: "\f021"; } 112 | .icon-list-alt:before { content: "\f022"; } 113 | .icon-lock:before { content: "\f023"; } 114 | .icon-flag:before { content: "\f024"; } 115 | .icon-headphones:before { content: "\f025"; } 116 | .icon-volume-off:before { content: "\f026"; } 117 | .icon-volume-down:before { content: "\f027"; } 118 | .icon-volume-up:before { content: "\f028"; } 119 | .icon-qrcode:before { content: "\f029"; } 120 | .icon-barcode:before { content: "\f02a"; } 121 | .icon-tag:before { content: "\f02b"; } 122 | .icon-tags:before { content: "\f02c"; } 123 | .icon-book:before { content: "\f02d"; } 124 | .icon-bookmark:before { content: "\f02e"; } 125 | .icon-print:before { content: "\f02f"; } 126 | 127 | .icon-camera:before { content: "\f030"; } 128 | .icon-font:before { content: "\f031"; } 129 | .icon-bold:before { content: "\f032"; } 130 | .icon-italic:before { content: "\f033"; } 131 | .icon-text-height:before { content: "\f034"; } 132 | .icon-text-width:before { content: "\f035"; } 133 | .icon-align-left:before { content: "\f036"; } 134 | .icon-align-center:before { content: "\f037"; } 135 | .icon-align-right:before { content: "\f038"; } 136 | .icon-align-justify:before { content: "\f039"; } 137 | .icon-list:before { content: "\f03a"; } 138 | .icon-indent-left:before { content: "\f03b"; } 139 | .icon-indent-right:before { content: "\f03c"; } 140 | .icon-facetime-video:before { content: "\f03d"; } 141 | .icon-picture:before { content: "\f03e"; } 142 | 143 | .icon-pencil:before { content: "\f040"; } 144 | .icon-map-marker:before { content: "\f041"; } 145 | .icon-adjust:before { content: "\f042"; } 146 | .icon-tint:before { content: "\f043"; } 147 | .icon-edit:before { content: "\f044"; } 148 | .icon-share:before { content: "\f045"; } 149 | .icon-check:before { content: "\f046"; } 150 | .icon-move:before { content: "\f047"; } 151 | .icon-step-backward:before { content: "\f048"; } 152 | .icon-fast-backward:before { content: "\f049"; } 153 | .icon-backward:before { content: "\f04a"; } 154 | .icon-play:before { content: "\f04b"; } 155 | .icon-pause:before { content: "\f04c"; } 156 | .icon-stop:before { content: "\f04d"; } 157 | .icon-forward:before { content: "\f04e"; } 158 | 159 | .icon-fast-forward:before { content: "\f050"; } 160 | .icon-step-forward:before { content: "\f051"; } 161 | .icon-eject:before { content: "\f052"; } 162 | .icon-chevron-left:before { content: "\f053"; } 163 | .icon-chevron-right:before { content: "\f054"; } 164 | .icon-plus-sign:before { content: "\f055"; } 165 | .icon-minus-sign:before { content: "\f056"; } 166 | .icon-remove-sign:before { content: "\f057"; } 167 | .icon-ok-sign:before { content: "\f058"; } 168 | .icon-question-sign:before { content: "\f059"; } 169 | .icon-info-sign:before { content: "\f05a"; } 170 | .icon-screenshot:before { content: "\f05b"; } 171 | .icon-remove-circle:before { content: "\f05c"; } 172 | .icon-ok-circle:before { content: "\f05d"; } 173 | .icon-ban-circle:before { content: "\f05e"; } 174 | 175 | .icon-arrow-left:before { content: "\f060"; } 176 | .icon-arrow-right:before { content: "\f061"; } 177 | .icon-arrow-up:before { content: "\f062"; } 178 | .icon-arrow-down:before { content: "\f063"; } 179 | .icon-share-alt:before { content: "\f064"; } 180 | .icon-resize-full:before { content: "\f065"; } 181 | .icon-resize-small:before { content: "\f066"; } 182 | .icon-plus:before { content: "\f067"; } 183 | .icon-minus:before { content: "\f068"; } 184 | .icon-asterisk:before { content: "\f069"; } 185 | .icon-exclamation-sign:before { content: "\f06a"; } 186 | .icon-gift:before { content: "\f06b"; } 187 | .icon-leaf:before { content: "\f06c"; } 188 | .icon-fire:before { content: "\f06d"; } 189 | .icon-eye-open:before { content: "\f06e"; } 190 | 191 | .icon-eye-close:before { content: "\f070"; } 192 | .icon-warning-sign:before { content: "\f071"; } 193 | .icon-plane:before { content: "\f072"; } 194 | .icon-calendar:before { content: "\f073"; } 195 | .icon-random:before { content: "\f074"; } 196 | .icon-comment:before { content: "\f075"; } 197 | .icon-magnet:before { content: "\f076"; } 198 | .icon-chevron-up:before { content: "\f077"; } 199 | .icon-chevron-down:before { content: "\f078"; } 200 | .icon-retweet:before { content: "\f079"; } 201 | .icon-shopping-cart:before { content: "\f07a"; } 202 | .icon-folder-close:before { content: "\f07b"; } 203 | .icon-folder-open:before { content: "\f07c"; } 204 | .icon-resize-vertical:before { content: "\f07d"; } 205 | .icon-resize-horizontal:before { content: "\f07e"; } 206 | 207 | .icon-bar-chart:before { content: "\f080"; } 208 | .icon-twitter-sign:before { content: "\f081"; } 209 | .icon-facebook-sign:before { content: "\f082"; } 210 | .icon-camera-retro:before { content: "\f083"; } 211 | .icon-key:before { content: "\f084"; } 212 | .icon-cogs:before { content: "\f085"; } 213 | .icon-comments:before { content: "\f086"; } 214 | .icon-thumbs-up:before { content: "\f087"; } 215 | .icon-thumbs-down:before { content: "\f088"; } 216 | .icon-star-half:before { content: "\f089"; } 217 | .icon-heart-empty:before { content: "\f08a"; } 218 | .icon-signout:before { content: "\f08b"; } 219 | .icon-linkedin-sign:before { content: "\f08c"; } 220 | .icon-pushpin:before { content: "\f08d"; } 221 | .icon-external-link:before { content: "\f08e"; } 222 | 223 | .icon-signin:before { content: "\f090"; } 224 | .icon-trophy:before { content: "\f091"; } 225 | .icon-github-sign:before { content: "\f092"; } 226 | .icon-upload-alt:before { content: "\f093"; } 227 | .icon-lemon:before { content: "\f094"; } 228 | .icon-phone:before { content: "\f095"; } 229 | .icon-check-empty:before { content: "\f096"; } 230 | .icon-bookmark-empty:before { content: "\f097"; } 231 | .icon-phone-sign:before { content: "\f098"; } 232 | .icon-twitter:before { content: "\f099"; } 233 | .icon-facebook:before { content: "\f09a"; } 234 | .icon-github:before { content: "\f09b"; } 235 | .icon-unlock:before { content: "\f09c"; } 236 | .icon-credit-card:before { content: "\f09d"; } 237 | .icon-rss:before { content: "\f09e"; } 238 | 239 | .icon-hdd:before { content: "\f0a0"; } 240 | .icon-bullhorn:before { content: "\f0a1"; } 241 | .icon-bell:before { content: "\f0a2"; } 242 | .icon-certificate:before { content: "\f0a3"; } 243 | .icon-hand-right:before { content: "\f0a4"; } 244 | .icon-hand-left:before { content: "\f0a5"; } 245 | .icon-hand-up:before { content: "\f0a6"; } 246 | .icon-hand-down:before { content: "\f0a7"; } 247 | .icon-circle-arrow-left:before { content: "\f0a8"; } 248 | .icon-circle-arrow-right:before { content: "\f0a9"; } 249 | .icon-circle-arrow-up:before { content: "\f0aa"; } 250 | .icon-circle-arrow-down:before { content: "\f0ab"; } 251 | .icon-globe:before { content: "\f0ac"; } 252 | .icon-wrench:before { content: "\f0ad"; } 253 | .icon-tasks:before { content: "\f0ae"; } 254 | 255 | .icon-filter:before { content: "\f0b0"; } 256 | .icon-briefcase:before { content: "\f0b1"; } 257 | .icon-fullscreen:before { content: "\f0b2"; } 258 | 259 | .icon-group:before { content: "\f0c0"; } 260 | .icon-link:before { content: "\f0c1"; } 261 | .icon-cloud:before { content: "\f0c2"; } 262 | .icon-beaker:before { content: "\f0c3"; } 263 | .icon-cut:before { content: "\f0c4"; } 264 | .icon-copy:before { content: "\f0c5"; } 265 | .icon-paper-clip:before { content: "\f0c6"; } 266 | .icon-save:before { content: "\f0c7"; } 267 | .icon-sign-blank:before { content: "\f0c8"; } 268 | .icon-reorder:before { content: "\f0c9"; } 269 | .icon-list-ul:before { content: "\f0ca"; } 270 | .icon-list-ol:before { content: "\f0cb"; } 271 | .icon-strikethrough:before { content: "\f0cc"; } 272 | .icon-underline:before { content: "\f0cd"; } 273 | .icon-table:before { content: "\f0ce"; } 274 | 275 | .icon-magic:before { content: "\f0d0"; } 276 | .icon-truck:before { content: "\f0d1"; } 277 | .icon-pinterest:before { content: "\f0d2"; } 278 | .icon-pinterest-sign:before { content: "\f0d3"; } 279 | .icon-google-plus-sign:before { content: "\f0d4"; } 280 | .icon-google-plus:before { content: "\f0d5"; } 281 | .icon-money:before { content: "\f0d6"; } 282 | .icon-caret-down:before { content: "\f0d7"; } 283 | .icon-caret-up:before { content: "\f0d8"; } 284 | .icon-caret-left:before { content: "\f0d9"; } 285 | .icon-caret-right:before { content: "\f0da"; } 286 | .icon-columns:before { content: "\f0db"; } 287 | .icon-sort:before { content: "\f0dc"; } 288 | .icon-sort-down:before { content: "\f0dd"; } 289 | .icon-sort-up:before { content: "\f0de"; } 290 | 291 | .icon-envelope-alt:before { content: "\f0e0"; } 292 | .icon-linkedin:before { content: "\f0e1"; } 293 | .icon-undo:before { content: "\f0e2"; } 294 | .icon-legal:before { content: "\f0e3"; } 295 | .icon-dashboard:before { content: "\f0e4"; } 296 | .icon-comment-alt:before { content: "\f0e5"; } 297 | .icon-comments-alt:before { content: "\f0e6"; } 298 | .icon-bolt:before { content: "\f0e7"; } 299 | .icon-sitemap:before { content: "\f0e8"; } 300 | .icon-umbrella:before { content: "\f0e9"; } 301 | .icon-paste:before { content: "\f0ea"; } 302 | 303 | .icon-user-md:before { content: "\f200"; } 304 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/js/jquery.autoellipsis.js: -------------------------------------------------------------------------------- 1 | /*! 2 | 3 | Copyright (c) 2011 Peter van der Spek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | */ 24 | 25 | 26 | (function($) { 27 | 28 | /** 29 | * Hash containing mapping of selectors to settings hashes for target selectors that should be live updated. 30 | * 31 | * @type {Object.} 32 | * @private 33 | */ 34 | var liveUpdatingTargetSelectors = {}; 35 | 36 | /** 37 | * Interval ID for live updater. Contains interval ID when the live updater interval is active, or is undefined 38 | * otherwise. 39 | * 40 | * @type {number} 41 | * @private 42 | */ 43 | var liveUpdaterIntervalId; 44 | 45 | /** 46 | * Boolean indicating whether the live updater is running. 47 | * 48 | * @type {boolean} 49 | * @private 50 | */ 51 | var liveUpdaterRunning = false; 52 | 53 | /** 54 | * Set of default settings. 55 | * 56 | * @type {Object.} 57 | * @private 58 | */ 59 | var defaultSettings = { 60 | ellipsis: '...', 61 | setTitle: 'never', 62 | live: false 63 | }; 64 | 65 | /** 66 | * Perform ellipsis on selected elements. 67 | * 68 | * @param {string} selector the inner selector of elements that ellipsis may work on. Inner elements not referred to by this 69 | * selector are left untouched. 70 | * @param {Object.=} options optional options to override default settings. 71 | * @return {jQuery} the current jQuery object for chaining purposes. 72 | * @this {jQuery} the current jQuery object. 73 | */ 74 | $.fn.ellipsis = function(selector, options) { 75 | var subjectElements, settings; 76 | 77 | subjectElements = $(this); 78 | 79 | // Check for options argument only. 80 | if (typeof selector !== 'string') { 81 | options = selector; 82 | selector = undefined; 83 | } 84 | 85 | // Create the settings from the given options and the default settings. 86 | settings = $.extend({}, defaultSettings, options); 87 | 88 | // If selector is not set, work on immediate children (default behaviour). 89 | settings.selector = selector; 90 | 91 | // Do ellipsis on each subject element. 92 | subjectElements.each(function() { 93 | var elem = $(this); 94 | 95 | // Do ellipsis on subject element. 96 | ellipsisOnElement(elem, settings); 97 | }); 98 | 99 | // If live option is enabled, add subject elements to live updater. Otherwise remove from live updater. 100 | if (settings.live) { 101 | addToLiveUpdater(subjectElements.selector, settings); 102 | 103 | } else { 104 | removeFromLiveUpdater(subjectElements.selector); 105 | } 106 | 107 | // Return jQuery object for chaining. 108 | return this; 109 | }; 110 | 111 | 112 | /** 113 | * Perform ellipsis on the given container. 114 | * 115 | * @param {jQuery} containerElement jQuery object containing one DOM element to perform ellipsis on. 116 | * @param {Object.} settings the settings for this ellipsis operation. 117 | * @private 118 | */ 119 | function ellipsisOnElement(containerElement, settings) { 120 | var containerData = containerElement.data('jqae'); 121 | if (!containerData) containerData = {}; 122 | 123 | // Check if wrapper div was already created and bound to the container element. 124 | var wrapperElement = containerData.wrapperElement; 125 | 126 | // If not, create wrapper element. 127 | if (!wrapperElement) { 128 | wrapperElement = containerElement.wrapInner('
').find('>div'); 129 | 130 | // Wrapper div should not add extra size. 131 | wrapperElement.css({ 132 | margin: 0, 133 | padding: 0, 134 | border: 0 135 | }); 136 | } 137 | 138 | // Check if the original wrapper element content was already bound to the wrapper element. 139 | var wrapperElementData = wrapperElement.data('jqae'); 140 | if (!wrapperElementData) wrapperElementData = {}; 141 | 142 | var wrapperOriginalContent = wrapperElementData.originalContent; 143 | 144 | // If so, clone the original content, re-bind the original wrapper content to the clone, and replace the 145 | // wrapper with the clone. 146 | if (wrapperOriginalContent) { 147 | wrapperElement = wrapperElementData.originalContent.clone(true) 148 | .data('jqae', {originalContent: wrapperOriginalContent}).replaceAll(wrapperElement); 149 | 150 | } else { 151 | // Otherwise, clone the current wrapper element and bind it as original content to the wrapper element. 152 | 153 | wrapperElement.data('jqae', {originalContent: wrapperElement.clone(true)}); 154 | } 155 | 156 | // Bind the wrapper element and current container width and height to the container element. Current container 157 | // width and height are stored to detect changes to the container size. 158 | containerElement.data('jqae', { 159 | wrapperElement: wrapperElement, 160 | containerWidth: containerElement.width(), 161 | containerHeight: containerElement.height() 162 | }); 163 | 164 | // Calculate with current container element height. 165 | var containerElementHeight = containerElement.height(); 166 | 167 | // Calculate wrapper offset. 168 | var wrapperOffset = (parseInt(containerElement.css('padding-top'), 10) || 0) + (parseInt(containerElement.css('border-top-width'), 10) || 0) - (wrapperElement.offset().top - containerElement.offset().top); 169 | 170 | // Normally the ellipsis characters are applied to the last non-empty text-node in the selected element. If the 171 | // selected element becomes empty during ellipsis iteration, the ellipsis characters cannot be applied to that 172 | // selected element, and must be deferred to the previous selected element. This parameter keeps track of that. 173 | var deferAppendEllipsis = false; 174 | 175 | // Loop through all selected elements in reverse order. 176 | var selectedElements = wrapperElement; 177 | if (settings.selector) selectedElements = $(wrapperElement.find(settings.selector).get().reverse()); 178 | 179 | selectedElements.each(function() { 180 | var selectedElement = $(this), 181 | originalText = selectedElement.text(), 182 | ellipsisApplied = false; 183 | 184 | // Check if we can safely remove the selected element. This saves a lot of unnecessary iterations. 185 | if (wrapperElement.innerHeight() - selectedElement.innerHeight() > containerElementHeight + wrapperOffset) { 186 | selectedElement.remove(); 187 | 188 | } else { 189 | // Reverse recursively remove empty elements, until the element that contains a non-empty text-node. 190 | removeLastEmptyElements(selectedElement); 191 | 192 | // If the selected element has not become empty, start ellipsis iterations on the selected element. 193 | if (selectedElement.contents().length) { 194 | 195 | // If a deffered ellipsis is still pending, apply it now to the last text-node. 196 | if (deferAppendEllipsis) { 197 | getLastTextNode(selectedElement).get(0).nodeValue += settings.ellipsis; 198 | deferAppendEllipsis = false; 199 | } 200 | 201 | // Iterate until wrapper element height is less than or equal to the original container element 202 | // height plus possible wrapperOffset. 203 | while (wrapperElement.innerHeight() > containerElementHeight + wrapperOffset) { 204 | // Apply ellipsis on last text node, by removing one word. 205 | ellipsisApplied = ellipsisOnLastTextNode(selectedElement); 206 | 207 | // If ellipsis was succesfully applied, remove any remaining empty last elements and append the 208 | // ellipsis characters. 209 | if (ellipsisApplied) { 210 | removeLastEmptyElements(selectedElement); 211 | 212 | // If the selected element is not empty, append the ellipsis characters. 213 | if (selectedElement.contents().length) { 214 | getLastTextNode(selectedElement).get(0).nodeValue += settings.ellipsis; 215 | 216 | } else { 217 | // If the selected element has become empty, defer the appending of the ellipsis characters 218 | // to the previous selected element. 219 | deferAppendEllipsis = true; 220 | selectedElement.remove(); 221 | break; 222 | } 223 | 224 | } else { 225 | // If ellipsis could not be applied, defer the appending of the ellipsis characters to the 226 | // previous selected element. 227 | deferAppendEllipsis = true; 228 | selectedElement.remove(); 229 | break; 230 | } 231 | } 232 | 233 | // If the "setTitle" property is set to "onEllipsis" and the ellipsis has been applied, or if the 234 | // property is set to "always", the add the "title" attribute with the original text. Else remove the 235 | // "title" attribute. When the "setTitle" property is set to "never" we do not touch the "title" 236 | // attribute. 237 | if (((settings.setTitle == 'onEllipsis') && ellipsisApplied) || (settings.setTitle == 'always')) { 238 | selectedElement.attr('title', originalText); 239 | 240 | } else if (settings.setTitle != 'never') { 241 | selectedElement.removeAttr('title'); 242 | } 243 | } 244 | } 245 | }); 246 | } 247 | 248 | /** 249 | * Performs ellipsis on the last text node of the given element. Ellipsis is done by removing a full word. 250 | * 251 | * @param {jQuery} element jQuery object containing a single DOM element. 252 | * @return {boolean} true when ellipsis has been done, false otherwise. 253 | * @private 254 | */ 255 | function ellipsisOnLastTextNode(element) { 256 | var lastTextNode = getLastTextNode(element); 257 | 258 | // If the last text node is found, do ellipsis on that node. 259 | if (lastTextNode.length) { 260 | var text = lastTextNode.get(0).nodeValue; 261 | 262 | // Find last space character, and remove text from there. If no space is found the full remaining text is 263 | // removed. 264 | var pos = text.lastIndexOf(' '); 265 | if (pos > -1) { 266 | text = $.trim(text.substring(0, pos)); 267 | lastTextNode.get(0).nodeValue = text; 268 | 269 | } else { 270 | lastTextNode.get(0).nodeValue = ''; 271 | } 272 | 273 | return true; 274 | } 275 | 276 | return false; 277 | } 278 | 279 | /** 280 | * Get last text node of the given element. 281 | * 282 | * @param {jQuery} element jQuery object containing a single element. 283 | * @return {jQuery} jQuery object containing a single text node. 284 | * @private 285 | */ 286 | function getLastTextNode(element) { 287 | if (element.contents().length) { 288 | 289 | // Get last child node. 290 | var contents = element.contents(); 291 | var lastNode = contents.eq(contents.length - 1); 292 | 293 | // If last node is a text node, return it. 294 | if (lastNode.filter(textNodeFilter).length) { 295 | return lastNode; 296 | 297 | } else { 298 | // Else it is an element node, and we recurse into it. 299 | 300 | return getLastTextNode(lastNode); 301 | } 302 | 303 | } else { 304 | // If there is no last child node, we append an empty text node and return that. Normally this should not 305 | // happen, as we test for emptiness before calling getLastTextNode. 306 | 307 | element.append(''); 308 | var contents = element.contents(); 309 | return contents.eq(contents.length - 1); 310 | } 311 | } 312 | 313 | /** 314 | * Remove last empty elements. This is done recursively until the last element contains a non-empty text node. 315 | * 316 | * @param {jQuery} element jQuery object containing a single element. 317 | * @return {boolean} true when elements have been removed, false otherwise. 318 | * @private 319 | */ 320 | function removeLastEmptyElements(element) { 321 | if (element.contents().length) { 322 | 323 | // Get last child node. 324 | var contents = element.contents(); 325 | var lastNode = contents.eq(contents.length - 1); 326 | 327 | // If last child node is a text node, check for emptiness. 328 | if (lastNode.filter(textNodeFilter).length) { 329 | var text = lastNode.get(0).nodeValue; 330 | text = $.trim(text); 331 | 332 | if (text == '') { 333 | // If empty, remove the text node. 334 | lastNode.remove(); 335 | 336 | return true; 337 | 338 | } else { 339 | return false; 340 | } 341 | 342 | } else { 343 | // If the last child node is an element node, remove the last empty child nodes on that node. 344 | while (removeLastEmptyElements(lastNode)) { 345 | } 346 | 347 | // If the last child node contains no more child nodes, remove the last child node. 348 | if (lastNode.contents().length) { 349 | return false; 350 | 351 | } else { 352 | lastNode.remove(); 353 | 354 | return true; 355 | } 356 | } 357 | } 358 | 359 | return false; 360 | } 361 | 362 | /** 363 | * Filter for testing on text nodes. 364 | * 365 | * @return {boolean} true when this node is a text node, false otherwise. 366 | * @this {Node} 367 | * @private 368 | */ 369 | function textNodeFilter() { 370 | return this.nodeType === 3; 371 | } 372 | 373 | /** 374 | * Add target selector to hash of target selectors. If this is the first target selector added, start the live 375 | * updater. 376 | * 377 | * @param {string} targetSelector the target selector to run the live updater for. 378 | * @param {Object.} settings the settings to apply on this target selector. 379 | * @private 380 | */ 381 | function addToLiveUpdater(targetSelector, settings) { 382 | // Store target selector with its settings. 383 | liveUpdatingTargetSelectors[targetSelector] = settings; 384 | 385 | // If the live updater has not yet been started, start it now. 386 | if (!liveUpdaterIntervalId) { 387 | liveUpdaterIntervalId = window.setInterval(function() { 388 | doLiveUpdater(); 389 | }, 200); 390 | } 391 | } 392 | 393 | /** 394 | * Remove the target selector from the hash of target selectors. It this is the last remaining target selector 395 | * being removed, stop the live updater. 396 | * 397 | * @param {string} targetSelector the target selector to stop running the live updater for. 398 | * @private 399 | */ 400 | function removeFromLiveUpdater(targetSelector) { 401 | // If the hash contains the target selector, remove it. 402 | if (liveUpdatingTargetSelectors[targetSelector]) { 403 | delete liveUpdatingTargetSelectors[targetSelector]; 404 | 405 | // If no more target selectors are in the hash, stop the live updater. 406 | if (!liveUpdatingTargetSelectors.length) { 407 | if (liveUpdaterIntervalId) { 408 | window.clearInterval(liveUpdaterIntervalId); 409 | liveUpdaterIntervalId = undefined; 410 | } 411 | } 412 | } 413 | }; 414 | 415 | /** 416 | * Run the live updater. The live updater is periodically run to check if its monitored target selectors require 417 | * re-applying of the ellipsis. 418 | * 419 | * @private 420 | */ 421 | function doLiveUpdater() { 422 | // If the live updater is already running, skip this time. We only want one instance running at a time. 423 | if (!liveUpdaterRunning) { 424 | liveUpdaterRunning = true; 425 | 426 | // Loop through target selectors. 427 | for (var targetSelector in liveUpdatingTargetSelectors) { 428 | $(targetSelector).each(function() { 429 | var containerElement, containerData; 430 | 431 | containerElement = $(this); 432 | containerData = containerElement.data('jqae'); 433 | 434 | // If container element dimensions have changed, or the container element is new, run ellipsis on 435 | // that container element. 436 | if ((containerData.containerWidth != containerElement.width()) || 437 | (containerData.containerHeight != containerElement.height())) { 438 | ellipsisOnElement(containerElement, liveUpdatingTargetSelectors[targetSelector]); 439 | } 440 | }); 441 | } 442 | 443 | liveUpdaterRunning = false; 444 | } 445 | }; 446 | 447 | })(jQuery); -------------------------------------------------------------------------------- /src/packages/MarkdownSharp.1.13.0.0/lib/35/MarkdownSharp.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | MarkdownSharp 5 | 6 | 7 | 8 | 9 | when true, (most) bare plain URLs are auto-hyperlinked 10 | WARNING: this is a significant deviation from the markdown spec 11 | 12 | 13 | 14 | 15 | when true, RETURN becomes a literal newline 16 | WARNING: this is a significant deviation from the markdown spec 17 | 18 | 19 | 20 | 21 | use ">" for HTML output, or " />" for XHTML output 22 | 23 | 24 | 25 | 26 | when true, problematic URL characters like [, ], (, and so forth will be encoded 27 | WARNING: this is a significant deviation from the markdown spec 28 | 29 | 30 | 31 | 32 | when false, email addresses will never be auto-linked 33 | WARNING: this is a significant deviation from the markdown spec 34 | 35 | 36 | 37 | 38 | when true, bold and italic require non-word characters on either side 39 | WARNING: this is a significant deviation from the markdown spec 40 | 41 | 42 | 43 | 44 | Markdown is a text-to-HTML conversion tool for web writers. 45 | Markdown allows you to write using an easy-to-read, easy-to-write plain text format, 46 | then convert it to structurally valid XHTML (or HTML). 47 | 48 | 49 | 50 | 51 | maximum nested depth of [] and () supported by the transform; implementation detail 52 | 53 | 54 | 55 | 56 | Tabs are automatically converted to spaces as part of the transform 57 | this constant determines how "wide" those tabs become in spaces 58 | 59 | 60 | 61 | 62 | Create a new Markdown instance using default options 63 | 64 | 65 | 66 | 67 | Create a new Markdown instance and optionally load options from the supplied options parameter. 68 | 69 | 70 | 71 | 72 | Create a new Markdown instance and optionally load options from a configuration 73 | file. There they should be stored in the appSettings section, available options are: 74 | 75 | Markdown.StrictBoldItalic (true/false) 76 | Markdown.EmptyElementSuffix (">" or " />" without the quotes) 77 | Markdown.LinkEmails (true/false) 78 | Markdown.AutoNewLines (true/false) 79 | Markdown.AutoHyperlink (true/false) 80 | Markdown.EncodeProblemUrlCharacters (true/false) 81 | 82 | 83 | 84 | 85 | In the static constuctor we'll initialize what stays the same across all transforms. 86 | 87 | 88 | 89 | 90 | Transforms the provided Markdown-formatted text to HTML; 91 | see http://en.wikipedia.org/wiki/Markdown 92 | 93 | 94 | The order in which other subs are called here is 95 | essential. Link and image substitutions need to happen before 96 | EscapeSpecialChars(), so that any *'s or _'s in the a 97 | and img tags get encoded. 98 | 99 | 100 | 101 | 102 | Perform transformations that form block-level tags like paragraphs, headers, and list items. 103 | 104 | 105 | 106 | 107 | Perform transformations that occur *within* block-level tags like paragraphs, headers, and list items. 108 | 109 | 110 | 111 | 112 | splits on two or more newlines, to form "paragraphs"; 113 | each paragraph is then unhashed (if it is a hash) or wrapped in HTML p tag 114 | 115 | 116 | 117 | 118 | Reusable pattern to match balanced [brackets]. See Friedl's 119 | "Mastering Regular Expressions", 2nd Ed., pp. 328-331. 120 | 121 | 122 | 123 | 124 | Reusable pattern to match balanced (parens). See Friedl's 125 | "Mastering Regular Expressions", 2nd Ed., pp. 328-331. 126 | 127 | 128 | 129 | 130 | Strips link definitions from text, stores the URLs and titles in hash references. 131 | 132 | 133 | ^[id]: url "optional title" 134 | 135 | 136 | 137 | 138 | derived pretty much verbatim from PHP Markdown 139 | 140 | 141 | 142 | 143 | replaces any block-level HTML blocks with hash entries 144 | 145 | 146 | 147 | 148 | returns an array of HTML tokens comprising the input string. Each token is 149 | either a tag (possibly with nested, tags contained therein, such 150 | as <a href="<MTFoo>">, or a run of text between tags. Each element of the 151 | array is a two-element array; the first is either 'tag' or 'text'; the second is 152 | the actual value. 153 | 154 | 155 | 156 | 157 | Turn Markdown link shortcuts into HTML anchor tags 158 | 159 | 160 | [link text](url "title") 161 | [link text][id] 162 | [id] 163 | 164 | 165 | 166 | 167 | Turn Markdown image shortcuts into HTML img tags. 168 | 169 | 170 | ![alt text][id] 171 | ![alt text](url "optional title") 172 | 173 | 174 | 175 | 176 | Turn Markdown headers into HTML header tags 177 | 178 | 179 | Header 1 180 | ======== 181 | 182 | Header 2 183 | -------- 184 | 185 | # Header 1 186 | ## Header 2 187 | ## Header 2 with closing hashes ## 188 | ... 189 | ###### Header 6 190 | 191 | 192 | 193 | 194 | Turn Markdown horizontal rules into HTML hr tags 195 | 196 | 197 | *** 198 | * * * 199 | --- 200 | - - - 201 | 202 | 203 | 204 | 205 | Turn Markdown lists into HTML ul and ol and li tags 206 | 207 | 208 | 209 | 210 | Process the contents of a single ordered or unordered list, splitting it 211 | into individual list items. 212 | 213 | 214 | 215 | 216 | /// Turn Markdown 4-space indented code into HTML pre code blocks 217 | 218 | 219 | 220 | 221 | Turn Markdown `code spans` into HTML code tags 222 | 223 | 224 | 225 | 226 | Turn Markdown *italics* and **bold** into HTML strong and em tags 227 | 228 | 229 | 230 | 231 | Turn markdown line breaks (two space at end of line) into HTML break tags 232 | 233 | 234 | 235 | 236 | Turn Markdown > quoted blocks into HTML blockquote blocks 237 | 238 | 239 | 240 | 241 | Turn angle-delimited URLs into HTML anchor tags 242 | 243 | 244 | <http://www.example.com> 245 | 246 | 247 | 248 | 249 | Remove one level of line-leading spaces 250 | 251 | 252 | 253 | 254 | encodes email address randomly 255 | roughly 10% raw, 45% hex, 45% dec 256 | note that @ is always encoded and : never is 257 | 258 | 259 | 260 | 261 | Encode/escape certain Markdown characters inside code blocks and spans where they are literals 262 | 263 | 264 | 265 | 266 | Encode any ampersands (that aren't part of an HTML entity) and left or right angle brackets 267 | 268 | 269 | 270 | 271 | Encodes any escaped characters such as \`, \*, \[ etc 272 | 273 | 274 | 275 | 276 | swap back in all the special characters we've hidden 277 | 278 | 279 | 280 | 281 | escapes Bold [ * ] and Italic [ _ ] characters 282 | 283 | 284 | 285 | 286 | hex-encodes some unusual "problem" chars in URLs to avoid URL detection problems 287 | 288 | 289 | 290 | 291 | Within tags -- meaning between < and > -- encode [\ ` * _] so they 292 | don't conflict with their use in Markdown for code, italics and strong. 293 | We're replacing each such character with its corresponding hash 294 | value; this is likely overkill, but it should prevent us from colliding 295 | with the escape values by accident. 296 | 297 | 298 | 299 | 300 | convert all tabs to _tabWidth spaces; 301 | standardizes line endings from DOS (CR LF) or Mac (CR) to UNIX (LF); 302 | makes sure text ends with a couple of newlines; 303 | removes any blank lines (only spaces) in the text 304 | 305 | 306 | 307 | 308 | this is to emulate what's evailable in PHP 309 | 310 | 311 | 312 | 313 | current version of MarkdownSharp; 314 | see http://code.google.com/p/markdownsharp/ for the latest code or to contribute 315 | 316 | 317 | 318 | 319 | Static constructor 320 | 321 | 322 | In the static constuctor we'll initialize what stays the same across all transforms. 323 | 324 | 325 | 326 | 327 | 328 | Strips link definitions from text, stores the URLs and titles in hash references. 329 | 330 | Link defs are in the form: ^[id]: url "optional title" 331 | 332 | 333 | 334 | Hashify HTML blocks 335 | 336 | 337 | 338 | 339 | These are all the transformations that form block-level 340 | tags like paragraphs, headers, and list items. 341 | 342 | 343 | 344 | 345 | These are all the transformations that occur *within* block-level 346 | tags like paragraphs, headers, and list items. 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | Process the contents of a single ordered or unordered list, splitting it 355 | into individual list items. 356 | 357 | 358 | 359 | 360 | Encode/escape certain characters inside Markdown code runs. 361 | 362 | 363 | The point is that in code, these characters are literals, and lose their 364 | special Markdown meanings. 365 | 366 | 367 | 368 | 369 | Smart processing for ampersands and angle brackets that need to be encoded. 370 | 371 | 372 | 373 | 374 | Swap back in all the special characters we've hidden. 375 | 376 | 377 | 378 | 379 | Remove one level of line-leading tabs or spaces 380 | 381 | 382 | 383 | 384 | This is to emulate what's evailable in PHP 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | Calculate an MD5 hash of an arbitrary string 393 | 394 | 395 | 396 | 397 | 398 | 399 | when true, (most) bare plain URLs are auto-hyperlinked 400 | WARNING: this is a significant deviation from the markdown spec 401 | 402 | 403 | 404 | 405 | when true, RETURN becomes a literal newline 406 | WARNING: this is a significant deviation from the markdown spec 407 | 408 | 409 | 410 | 411 | use ">" for HTML output, or " />" for XHTML output 412 | 413 | 414 | 415 | 416 | when true, problematic URL characters like [, ], (, and so forth will be encoded 417 | WARNING: this is a significant deviation from the markdown spec 418 | 419 | 420 | 421 | 422 | when false, email addresses will never be auto-linked 423 | WARNING: this is a significant deviation from the markdown spec 424 | 425 | 426 | 427 | 428 | when true, bold and italic require non-word characters on either side 429 | WARNING: this is a significant deviation from the markdown spec 430 | 431 | 432 | 433 | 434 | -------------------------------------------------------------------------------- /src/Nancy.Demo.Samples/Content/js/jquery.fancybox.pack.js: -------------------------------------------------------------------------------- 1 | /*! fancyBox v2.1.3 fancyapps.com | fancyapps.com/fancybox/#license */ 2 | (function(B,x,f,q){var r=f(B),m=f(x),b=f.fancybox=function(){b.open.apply(this,arguments)},u=null,n=x.createTouch!==q,s=function(a){return a&&a.hasOwnProperty&&a instanceof f},p=function(a){return a&&"string"===f.type(a)},E=function(a){return p(a)&&0
',image:'',iframe:'",error:'

The requested content cannot be loaded.
Please try again later.

',closeBtn:'',next:'',prev:''},openEffect:"fade",openSpeed:250,openEasing:"swing", 6 | openOpacity:!0,openMethod:"zoomIn",closeEffect:"fade",closeSpeed:250,closeEasing:"swing",closeOpacity:!0,closeMethod:"zoomOut",nextEffect:"elastic",nextSpeed:250,nextEasing:"swing",nextMethod:"changeIn",prevEffect:"elastic",prevSpeed:250,prevEasing:"swing",prevMethod:"changeOut",helpers:{overlay:!0,title:!0},onCancel:f.noop,beforeLoad:f.noop,afterLoad:f.noop,beforeShow:f.noop,afterShow:f.noop,beforeChange:f.noop,beforeClose:f.noop,afterClose:f.noop},group:{},opts:{},previous:null,coming:null,current:null, 7 | isActive:!1,isOpen:!1,isOpened:!1,wrap:null,skin:null,outer:null,inner:null,player:{timer:null,isActive:!1},ajaxLoad:null,imgPreload:null,transitions:{},helpers:{},open:function(a,d){if(a&&(f.isPlainObject(d)||(d={}),!1!==b.close(!0)))return f.isArray(a)||(a=s(a)?f(a).get():[a]),f.each(a,function(e,c){var j={},g,h,i,l,k;"object"===f.type(c)&&(c.nodeType&&(c=f(c)),s(c)?(j={href:c.data("fancybox-href")||c.attr("href"),title:c.data("fancybox-title")||c.attr("title"),isDom:!0,element:c},f.metadata&&f.extend(!0, 8 | j,c.metadata())):j=c);g=d.href||j.href||(p(c)?c:null);h=d.title!==q?d.title:j.title||"";l=(i=d.content||j.content)?"html":d.type||j.type;!l&&j.isDom&&(l=c.data("fancybox-type"),l||(l=(l=c.prop("class").match(/fancybox\.(\w+)/))?l[1]:null));p(g)&&(l||(b.isImage(g)?l="image":b.isSWF(g)?l="swf":"#"===g.charAt(0)?l="inline":p(c)&&(l="html",i=c)),"ajax"===l&&(k=g.split(/\s+/,2),g=k.shift(),k=k.shift()));i||("inline"===l?g?i=f(p(g)?g.replace(/.*(?=#[^\s]+$)/,""):g):j.isDom&&(i=c):"html"===l?i=g:!l&&(!g&& 9 | j.isDom)&&(l="inline",i=c));f.extend(j,{href:g,type:l,content:i,title:h,selector:k});a[e]=j}),b.opts=f.extend(!0,{},b.defaults,d),d.keys!==q&&(b.opts.keys=d.keys?f.extend({},b.defaults.keys,d.keys):!1),b.group=a,b._start(b.opts.index)},cancel:function(){var a=b.coming;a&&!1!==b.trigger("onCancel")&&(b.hideLoading(),b.ajaxLoad&&b.ajaxLoad.abort(),b.ajaxLoad=null,b.imgPreload&&(b.imgPreload.onload=b.imgPreload.onerror=null),a.wrap&&a.wrap.stop(!0,!0).trigger("onReset").remove(),b.coming=null,b.current|| 10 | b._afterZoomOut(a))},close:function(a){b.cancel();!1!==b.trigger("beforeClose")&&(b.unbindEvents(),b.isActive&&(!b.isOpen||!0===a?(f(".fancybox-wrap").stop(!0).trigger("onReset").remove(),b._afterZoomOut()):(b.isOpen=b.isOpened=!1,b.isClosing=!0,f(".fancybox-item, .fancybox-nav").remove(),b.wrap.stop(!0,!0).removeClass("fancybox-opened"),b.transitions[b.current.closeMethod]())))},play:function(a){var d=function(){clearTimeout(b.player.timer)},e=function(){d();b.current&&b.player.isActive&&(b.player.timer= 11 | setTimeout(b.next,b.current.playSpeed))},c=function(){d();f("body").unbind(".player");b.player.isActive=!1;b.trigger("onPlayEnd")};if(!0===a||!b.player.isActive&&!1!==a){if(b.current&&(b.current.loop||b.current.index=c.index?"next":"prev"],b.router=e||"jumpto",c.loop&&(0>a&&(a=c.group.length+a%c.group.length),a%=c.group.length),c.group[a]!==q&&(b.cancel(),b._start(a)))},reposition:function(a,d){var e=b.current,c=e?e.wrap:null,j;c&&(j=b._getPosition(d),a&&"scroll"===a.type?(delete j.position,c.stop(!0,!0).animate(j,200)):(c.css(j),e.pos=f.extend({}, 13 | e.dim,j)))},update:function(a){var d=a&&a.type,e=!d||"orientationchange"===d;e&&(clearTimeout(u),u=null);b.isOpen&&!u&&(u=setTimeout(function(){var c=b.current;c&&!b.isClosing&&(b.wrap.removeClass("fancybox-tmp"),(e||"load"===d||"resize"===d&&c.autoResize)&&b._setDimension(),"scroll"===d&&c.canShrink||b.reposition(a),b.trigger("onUpdate"),u=null)},e&&!n?0:300))},toggle:function(a){b.isOpen&&(b.current.fitToView="boolean"===f.type(a)?a:!b.current.fitToView,n&&(b.wrap.removeAttr("style").addClass("fancybox-tmp"), 14 | b.trigger("onUpdate")),b.update())},hideLoading:function(){m.unbind(".loading");f("#fancybox-loading").remove()},showLoading:function(){var a,d;b.hideLoading();a=f('
').click(b.cancel).appendTo("body");m.bind("keydown.loading",function(a){if(27===(a.which||a.keyCode))a.preventDefault(),b.cancel()});b.defaults.fixed||(d=b.getViewport(),a.css({position:"absolute",top:0.5*d.h+d.y,left:0.5*d.w+d.x}))},getViewport:function(){var a=b.current&&b.current.locked|| 15 | !1,d={x:r.scrollLeft(),y:r.scrollTop()};a?(d.w=a[0].clientWidth,d.h=a[0].clientHeight):(d.w=n&&B.innerWidth?B.innerWidth:r.width(),d.h=n&&B.innerHeight?B.innerHeight:r.height());return d},unbindEvents:function(){b.wrap&&s(b.wrap)&&b.wrap.unbind(".fb");m.unbind(".fb");r.unbind(".fb")},bindEvents:function(){var a=b.current,d;a&&(r.bind("orientationchange.fb"+(n?"":" resize.fb")+(a.autoCenter&&!a.locked?" scroll.fb":""),b.update),(d=a.keys)&&m.bind("keydown.fb",function(e){var c=e.which||e.keyCode,j= 16 | e.target||e.srcElement;if(27===c&&b.coming)return!1;!e.ctrlKey&&(!e.altKey&&!e.shiftKey&&!e.metaKey&&(!j||!j.type&&!f(j).is("[contenteditable]")))&&f.each(d,function(d,j){if(1h[0].clientWidth||h[0].clientHeight&&h[0].scrollHeight>h[0].clientHeight),h=f(h).parent();if(0!==c&&!i&&1g||0>j)b.next(0>g?"up":"right");d.preventDefault()}}))},trigger:function(a,d){var e,c=d||b.coming||b.current;if(c){f.isFunction(c[a])&&(e=c[a].apply(c,Array.prototype.slice.call(arguments,1)));if(!1===e)return!1;c.helpers&&f.each(c.helpers,function(d, 18 | e){e&&(b.helpers[d]&&f.isFunction(b.helpers[d][a]))&&(e=f.extend(!0,{},b.helpers[d].defaults,e),b.helpers[d][a](e,c))});f.event.trigger(a+".fb")}},isImage:function(a){return p(a)&&a.match(/(^data:image\/.*,)|(\.(jp(e|g|eg)|gif|png|bmp|webp)((\?|#).*)?$)/i)},isSWF:function(a){return p(a)&&a.match(/\.(swf)((\?|#).*)?$/i)},_start:function(a){var d={},e,c,a=k(a);e=b.group[a]||null;if(!e)return!1;d=f.extend(!0,{},b.opts,e);e=d.margin;c=d.padding;"number"===f.type(e)&&(d.margin=[e,e,e,e]);"number"===f.type(c)&& 19 | (d.padding=[c,c,c,c]);d.modal&&f.extend(!0,d,{closeBtn:!1,closeClick:!1,nextClick:!1,arrows:!1,mouseWheel:!1,keys:null,helpers:{overlay:{closeClick:!1}}});d.autoSize&&(d.autoWidth=d.autoHeight=!0);"auto"===d.width&&(d.autoWidth=!0);"auto"===d.height&&(d.autoHeight=!0);d.group=b.group;d.index=a;b.coming=d;if(!1===b.trigger("beforeLoad"))b.coming=null;else{c=d.type;e=d.href;if(!c)return b.coming=null,b.current&&b.router&&"jumpto"!==b.router?(b.current.index=a,b[b.router](b.direction)):!1;b.isActive= 20 | !0;if("image"===c||"swf"===c)d.autoHeight=d.autoWidth=!1,d.scrolling="visible";"image"===c&&(d.aspectRatio=!0);"iframe"===c&&n&&(d.scrolling="scroll");d.wrap=f(d.tpl.wrap).addClass("fancybox-"+(n?"mobile":"desktop")+" fancybox-type-"+c+" fancybox-tmp "+d.wrapCSS).appendTo(d.parent||"body");f.extend(d,{skin:f(".fancybox-skin",d.wrap),outer:f(".fancybox-outer",d.wrap),inner:f(".fancybox-inner",d.wrap)});f.each(["Top","Right","Bottom","Left"],function(a,b){d.skin.css("padding"+b,v(d.padding[a]))});b.trigger("onReady"); 21 | if("inline"===c||"html"===c){if(!d.content||!d.content.length)return b._error("content")}else if(!e)return b._error("href");"image"===c?b._loadImage():"ajax"===c?b._loadAjax():"iframe"===c?b._loadIframe():b._afterLoad()}},_error:function(a){f.extend(b.coming,{type:"html",autoWidth:!0,autoHeight:!0,minWidth:0,minHeight:0,scrolling:"no",hasError:a,content:b.coming.tpl.error});b._afterLoad()},_loadImage:function(){var a=b.imgPreload=new Image;a.onload=function(){this.onload=this.onerror=null;b.coming.width= 22 | this.width;b.coming.height=this.height;b._afterLoad()};a.onerror=function(){this.onload=this.onerror=null;b._error("image")};a.src=b.coming.href;!0!==a.complete&&b.showLoading()},_loadAjax:function(){var a=b.coming;b.showLoading();b.ajaxLoad=f.ajax(f.extend({},a.ajax,{url:a.href,error:function(a,e){b.coming&&"abort"!==e?b._error("ajax",a):b.hideLoading()},success:function(d,e){"success"===e&&(a.content=d,b._afterLoad())}}))},_loadIframe:function(){var a=b.coming,d=f(a.tpl.iframe.replace(/\{rnd\}/g, 23 | (new Date).getTime())).attr("scrolling",n?"auto":a.iframe.scrolling).attr("src",a.href);f(a.wrap).bind("onReset",function(){try{f(this).find("iframe").hide().attr("src","//about:blank").end().empty()}catch(a){}});a.iframe.preload&&(b.showLoading(),d.one("load",function(){f(this).data("ready",1);n||f(this).bind("load.fb",b.update);f(this).parents(".fancybox-wrap").width("100%").removeClass("fancybox-tmp").show();b._afterLoad()}));a.content=d.appendTo(a.inner);a.iframe.preload||b._afterLoad()},_preloadImages:function(){var a= 24 | b.group,d=b.current,e=a.length,c=d.preload?Math.min(d.preload,e-1):0,f,g;for(g=1;g<=c;g+=1)f=a[(d.index+g)%e],"image"===f.type&&f.href&&((new Image).src=f.href)},_afterLoad:function(){var a=b.coming,d=b.current,e,c,j,g,h;b.hideLoading();if(a&&!1!==b.isActive)if(!1===b.trigger("afterLoad",a,d))a.wrap.stop(!0).trigger("onReset").remove(),b.coming=null;else{d&&(b.trigger("beforeChange",d),d.wrap.stop(!0).removeClass("fancybox-opened").find(".fancybox-item, .fancybox-nav").remove());b.unbindEvents(); 25 | e=a.content;c=a.type;j=a.scrolling;f.extend(b,{wrap:a.wrap,skin:a.skin,outer:a.outer,inner:a.inner,current:a,previous:d});g=a.href;switch(c){case "inline":case "ajax":case "html":a.selector?e=f("
").html(e).find(a.selector):s(e)&&(e.data("fancybox-placeholder")||e.data("fancybox-placeholder",f('
').insertAfter(e).hide()),e=e.show().detach(),a.wrap.bind("onReset",function(){f(this).find(e).length&&e.hide().replaceAll(e.data("fancybox-placeholder")).data("fancybox-placeholder", 26 | !1)}));break;case "image":e=a.tpl.image.replace("{href}",g);break;case "swf":e='',h="",f.each(a.swf,function(a,b){e+='';h+=" "+a+'="'+b+'"'}),e+='"}(!s(e)||!e.parent().is(a.inner))&&a.inner.append(e);b.trigger("beforeShow"); 27 | a.inner.css("overflow","yes"===j?"scroll":"no"===j?"hidden":j);b._setDimension();b.reposition();b.isOpen=!1;b.coming=null;b.bindEvents();if(b.isOpened){if(d.prevMethod)b.transitions[d.prevMethod]()}else f(".fancybox-wrap").not(a.wrap).stop(!0).trigger("onReset").remove();b.transitions[b.isOpened?a.nextMethod:a.openMethod]();b._preloadImages()}},_setDimension:function(){var a=b.getViewport(),d=0,e=!1,c=!1,e=b.wrap,j=b.skin,g=b.inner,h=b.current,c=h.width,i=h.height,l=h.minWidth,t=h.minHeight,m=h.maxWidth, 28 | n=h.maxHeight,r=h.scrolling,p=h.scrollOutside?h.scrollbarWidth:0,w=h.margin,y=k(w[1]+w[3]),q=k(w[0]+w[2]),x,z,s,C,A,F,B,D,u;e.add(j).add(g).width("auto").height("auto").removeClass("fancybox-tmp");w=k(j.outerWidth(!0)-j.width());x=k(j.outerHeight(!0)-j.height());z=y+w;s=q+x;C=E(c)?(a.w-z)*k(c)/100:c;A=E(i)?(a.h-s)*k(i)/100:i;if("iframe"===h.type){if(u=h.content,h.autoHeight&&1===u.data("ready"))try{u[0].contentWindow.document.location&&(g.width(C).height(9999),F=u.contents().find("body"),p&&F.css("overflow-x", 29 | "hidden"),A=F.height())}catch(G){}}else if(h.autoWidth||h.autoHeight)g.addClass("fancybox-tmp"),h.autoWidth||g.width(C),h.autoHeight||g.height(A),h.autoWidth&&(C=g.width()),h.autoHeight&&(A=g.height()),g.removeClass("fancybox-tmp");c=k(C);i=k(A);D=C/A;l=k(E(l)?k(l,"w")-z:l);m=k(E(m)?k(m,"w")-z:m);t=k(E(t)?k(t,"h")-s:t);n=k(E(n)?k(n,"h")-s:n);F=m;B=n;h.fitToView&&(m=Math.min(a.w-z,m),n=Math.min(a.h-s,n));z=a.w-y;q=a.h-q;h.aspectRatio?(c>m&&(c=m,i=k(c/D)),i>n&&(i=n,c=k(i*D)),cz||y>q)&&(c>l&&i>t)&&!(19m&&(c=m,i=k(c/D)),g.width(c).height(i),e.width(c+w),a=e.width(),y=e.height();else c=Math.max(l,Math.min(c,c-(a-z))),i=Math.max(t,Math.min(i,i-(y-q)));p&&("auto"===r&&iz||y>q)&&c>l&&i>t;c=h.aspectRatio?ct&&i
').appendTo("body");this.fixed=!1;a.fixed&&b.defaults.fixed&&(this.overlay.addClass("fancybox-overlay-fixed"),this.fixed=!0)},open:function(a){var d=this,a=f.extend({},this.defaults,a);this.overlay?this.overlay.unbind(".overlay").width("auto").height("auto"):this.create(a);this.fixed||(r.bind("resize.overlay",f.proxy(this.update,this)),this.update());a.closeClick&&this.overlay.bind("click.overlay",function(a){f(a.target).hasClass("fancybox-overlay")&& 40 | (b.isActive?b.close():d.close())});this.overlay.css(a.css).show()},close:function(){f(".fancybox-overlay").remove();r.unbind("resize.overlay");this.overlay=null;!1!==this.margin&&(f("body").css("margin-right",this.margin),this.margin=!1);this.el&&this.el.removeClass("fancybox-lock")},update:function(){var a="100%",b;this.overlay.width(a).height("100%");f.browser.msie?(b=Math.max(x.documentElement.offsetWidth,x.body.offsetWidth),m.width()>b&&(a=m.width())):m.width()>r.width()&&(a=m.width());this.overlay.width(a).height(m.height())}, 41 | onReady:function(a,b){f(".fancybox-overlay").stop(!0,!0);this.overlay||(this.margin=m.height()>r.height()||"scroll"===f("body").css("overflow-y")?f("body").css("margin-right"):!1,this.el=x.all&&!x.querySelector?f("html"):f("body"),this.create(a));a.locked&&this.fixed&&(b.locked=this.overlay.append(b.wrap),b.fixed=!1);!0===a.showEarly&&this.beforeShow.apply(this,arguments)},beforeShow:function(a,b){b.locked&&(this.el.addClass("fancybox-lock"),!1!==this.margin&&f("body").css("margin-right",k(this.margin)+ 42 | b.scrollbarWidth));this.open(a)},onUpdate:function(){this.fixed||this.update()},afterClose:function(a){this.overlay&&!b.isActive&&this.overlay.fadeOut(a.speedOut,f.proxy(this.close,this))}};b.helpers.title={defaults:{type:"float",position:"bottom"},beforeShow:function(a){var d=b.current,e=d.title,c=a.type;f.isFunction(e)&&(e=e.call(d.element,d));if(p(e)&&""!==f.trim(e)){d=f('
'+e+"
");switch(c){case "inside":c=b.skin;break;case "outside":c= 43 | b.wrap;break;case "over":c=b.inner;break;default:c=b.skin,d.appendTo("body"),f.browser.msie&&d.width(d.width()),d.wrapInner(''),b.current.margin[2]+=Math.abs(k(d.css("margin-bottom")))}d["top"===a.position?"prependTo":"appendTo"](c)}}};f.fn.fancybox=function(a){var d,e=f(this),c=this.selector||"",j=function(g){var h=f(this).blur(),i=d,j,k;!g.ctrlKey&&(!g.altKey&&!g.shiftKey&&!g.metaKey)&&!h.is(".fancybox-wrap")&&(j=a.groupAttr||"data-fancybox-group",k=h.attr(j),k||(j="rel", 44 | k=h.get(0)[j]),k&&(""!==k&&"nofollow"!==k)&&(h=c.length?f(c):e,h=h.filter("["+j+'="'+k+'"]'),i=h.index(this)),a.index=i,!1!==b.open(h,a)&&g.preventDefault())},a=a||{};d=a.index||0;!c||!1===a.live?e.unbind("click.fb-start").bind("click.fb-start",j):m.undelegate(c,"click.fb-start").delegate(c+":not('.fancybox-item, .fancybox-nav')","click.fb-start",j);this.filter("[data-fancybox-start=1]").trigger("click");return this};m.ready(function(){f.scrollbarWidth===q&&(f.scrollbarWidth=function(){var a=f('
').appendTo("body"), 45 | b=a.children(),b=b.innerWidth()-b.height(99).innerWidth();a.remove();return b});if(f.support.fixedPosition===q){var a=f.support,d=f('
').appendTo("body"),e=20===d[0].offsetTop||15===d[0].offsetTop;d.remove();a.fixedPosition=e}f.extend(b.defaults,{scrollbarWidth:f.scrollbarWidth(),fixed:f.support.fixedPosition,parent:f("body")})})})(window,document,jQuery); --------------------------------------------------------------------------------