Welcome to websocket-sharp!
websocket-sharp supports:
@@ -101,9 +82,11 @@- -Security Sandbox of the Webplayer (server doesn't work in the webplayer) +Security Sandbox of the Webplayer (the server doesn't work in the webplayer)
- .NET Socket Support for iOS/Android (requires iOS/Android Pro) +
- +Limited support for the System.IO.Compression (the compression extension isn't available on Windows)
- .NET API 2.0 compatibility level for iOS/Android
Creating a new instance of the WebSocket
class with the WebSocket URL to connect.
using (var ws = new WebSocket ("ws://example.com")) {
+using (var ws = new WebSocket ("ws://example.com")) {
...
}
@@ -245,15 +228,15 @@
- Step 5Sending a data to the WebSocket server.
+Sending data to the WebSocket server.
ws.Send (data);
The WebSocket.Send
method is overloaded.
-You can use the WebSocket.Send (string)
, WebSocket.Send (byte[])
, or WebSocket.Send (System.IO.FileInfo)
method to send a data.
+You can use the WebSocket.Send (string)
, WebSocket.Send (byte[])
, or WebSocket.Send (System.IO.FileInfo)
method to send the data.
-If you would like to send a data asynchronously, you should use the WebSocket.SendAsync
method.
+If you would like to send the data asynchronously, you should use the WebSocket.SendAsync
method.
ws.SendAsync (data, completed);
@@ -283,24 +266,24 @@
namespace Example
{
- public class Laputa : WebSocketBehavior
+ public class Laputa : WebSocketBehavior
{
- protected override void OnMessage (MessageEventArgs e)
+ protected override void OnMessage (MessageEventArgs e)
{
- var msg = e.Data == "BALUS"
- ? "I've been balused already..."
- : "I'm not available now.";
+ var msg = e.Data == "BALUS"
+ ? "I've been balused already..."
+ : "I'm not available now.";
Send (msg);
}
}
- public class Program
+ public class Program
{
- public static void Main (string[] args)
+ public static void Main (string[] args)
{
- var wssv = new WebSocketServer ("ws://dragonsnest.far");
- wssv.AddWebSocketService<Laputa> ("/Laputa");
+ var wssv = new WebSocketServer ("ws://dragonsnest.far");
+ wssv.AddWebSocketService<Laputa> ("/Laputa");
wssv.Start ();
Console.ReadKey (true);
wssv.Stop ();
@@ -328,9 +311,9 @@
using WebSocketSharp;
using WebSocketSharp.Server;
-public class Echo : WebSocketBehavior
+public class Echo : WebSocketBehavior
{
- protected override void OnMessage (MessageEventArgs e)
+ protected override void OnMessage (MessageEventArgs e)
{
Send (e.Data);
}
@@ -342,21 +325,21 @@
using WebSocketSharp;
using WebSocketSharp.Server;
-public class Chat : WebSocketBehavior
+public class Chat : WebSocketBehavior
{
- private string _suffix;
+ private string _suffix;
- public Chat ()
+ public Chat ()
: this (null)
{
}
- public Chat (string suffix)
+ public Chat (string suffix)
{
_suffix = suffix ?? String.Empty;
}
- protected override void OnMessage (MessageEventArgs e)
+ protected override void OnMessage (MessageEventArgs e)
{
Sessions.Broadcast (e.Data + _suffix);
}
@@ -364,25 +347,25 @@
You can define the behavior of any WebSocket service by creating the class that inherits the WebSocketBehavior
class.
-If you override the WebSocketBehavior.OnMessage (MessageEventArgs)
method, it's called when the WebSocket
used in the current session in the service receives a message.
+If you override the WebSocketBehavior.OnMessage (MessageEventArgs)
method, it's called when the WebSocket
used in a session in the service receives a message.
And if you override the WebSocketBehavior.OnOpen ()
, WebSocketBehavior.OnError (ErrorEventArgs)
, and WebSocketBehavior.OnClose (CloseEventArgs)
methods, each of them is called when each event of the WebSocket
(the OnOpen
, OnError
, and OnClose
events) occurs.
-The WebSocketBehavior.Send
method sends a data to the client on the current session in the service.
+The WebSocketBehavior.Send
method sends data to the client on a session in the service.
If you would like to access the sessions in the service, you should use the WebSocketBehavior.Sessions
property (returns a WebSocketSharp.Server.WebSocketSessionManager
).
-The WebSocketBehavior.Sessions.Broadcast
method broadcasts a data to every client in the service.
+The WebSocketBehavior.Sessions.Broadcast
method sends data to every client in the service.
Step 3Creating a new instance of the WebSocketServer
class.
-var wssv = new WebSocketServer (4649);
-wssv.AddWebSocketService<Echo> ("/Echo");
-wssv.AddWebSocketService<Chat> ("/Chat");
-wssv.AddWebSocketService<Chat> ("/ChatWithNyan", () => new Chat (" Nyan!"));
+var wssv = new WebSocketServer (4649);
+wssv.AddWebSocketService<Echo> ("/Echo");
+wssv.AddWebSocketService<Chat> ("/Chat");
+wssv.AddWebSocketService<Chat> ("/ChatWithNyan", () => new Chat (" Nyan!"));
You can add any WebSocket service to your WebSocketServer
with the specified behavior and path to the service, by using the WebSocketServer.AddWebSocketService<TBehaviorWithNew> (string)
or WebSocketServer.AddWebSocketService<TBehavior> (string, Func<TBehavior>)
method.
@@ -424,10 +407,10 @@ wssv.AddWebSocketService<Chat> ("
You can add any WebSocket service to your HttpServer
with the specified behavior and path to the service, by using the HttpServer.AddWebSocketService<TBehaviorWithNew> (string)
or HttpServer.AddWebSocketService<TBehavior> (string, Func<TBehavior>)
method.
-var httpsv = new HttpServer (4649);
-httpsv.AddWebSocketService<Echo> ("/Echo");
-httpsv.AddWebSocketService<Chat> ("/Chat");
-httpsv.AddWebSocketService<Chat> ("/ChatWithNyan", () => new Chat (" Nyan!"));
+var httpsv = new HttpServer (4649);
+httpsv.AddWebSocketService<Echo> ("/Echo");
+httpsv.AddWebSocketService<Chat> ("/Chat");
+httpsv.AddWebSocketService<Chat> ("/ChatWithNyan", () => new Chat (" Nyan!"));
For more information, would you see Example3?
@@ -437,7 +420,7 @@ httpsv.AddWebSocketService<Chat> (
websocket-sharp supports the Per-message Compression extension. (But it doesn't support with the extension parameters.)
+websocket-sharp supports the Per-message Compression extension. (But this doesn't support it with the context take over.)
If you would like to enable this extension as a WebSocket client, you should set such as the following.
@@ -445,10 +428,10 @@ httpsv.AddWebSocketService<Chat> (And then your client will send the following header with the connection request to the server.
-Sec-WebSocket-Extensions: permessage-deflate
+Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover
-If the server supports this extension, it will return the same header. And when your client receives it, this extension will be available.
+If the server accepts this extension, it will return the same header which has the corresponding value. And when your client receives it, this extension will be available.
@@ -457,7 +440,7 @@ httpsv.AddWebSocketService<Chat> ( Secure ConnectionAs a WebSocket Client, you should create a new instance of the WebSocket
class with the wss scheme WebSocket URL.
-using (var ws = new WebSocket ("wss://example.com")) {
+using (var ws = new WebSocket ("wss://example.com")) {
...
}
@@ -475,9 +458,9 @@ httpsv.AddWebSocketService<Chat> (As a WebSocket Server, you should create a new instance of the WebSocketServer
or HttpServer
class with some settings for secure connection, such as the following.
-var wssv = new WebSocketServer (4649, true);
+var wssv = new WebSocketServer (5963, true);
wssv.SslConfiguration.ServerCertificate =
- new X509Certificate2 ("/path/to/cert.pfx", "password for cert.pfx");
+ new X509Certificate2 ("/path/to/cert.pfx", "password for cert.pfx");
@@ -486,7 +469,7 @@ wssv.SslConfiguration.ServerCertificate =
HTTP AuthenticationAs a WebSocket Client, you should set a pair of user name and password for the HTTP authentication, by using the WebSocket.SetCredentials (string, string, bool)
method before connecting.
-ws.SetCredentials ("nobita", "password", preAuth);
+ws.SetCredentials ("nobita", "password", preAuth);
If preAuth
is true
, the WebSocket
sends the Basic authentication credentials with the first connection request to the server.
@@ -495,13 +478,13 @@ wssv.SslConfiguration.ServerCertificate =
As a WebSocket Server, you should set an HTTP authentication scheme, a realm, and any function to find the user credentials before starting, such as the following.
wssv.AuthenticationSchemes = AuthenticationSchemes.Basic;
-wssv.Realm = "WebSocket Test";
+wssv.Realm = "WebSocket Test";
wssv.UserCredentialsFinder = id => {
var name = id.Name;
// Return user name, password, and roles.
- return name == "nobita"
- ? new NetworkCredential (name, "password", "gunfighter")
+ return name == "nobita"
+ ? new NetworkCredential (name, "password", "gunfighter")
: null; // If the user credentials aren't found.
};
@@ -514,28 +497,28 @@ wssv.UserCredentialsFinder = id => {
As a WebSocket Client, if you would like to send the Query String with the WebSocket connection request to the server, you should create a new instance of the WebSocket
class with the WebSocket URL that includes the Query string parameters.
-using (var ws = new WebSocket ("ws://example.com/?name=nobita")) {
+using (var ws = new WebSocket ("ws://example.com/?name=nobita")) {
...
}
And if you would like to send the Origin header with the WebSocket connection request to the server, you should set the WebSocket.Origin
property to an allowable value as the Origin header before connecting, such as the following.
-ws.Origin = "http://example.com";
+ws.Origin = "http://example.com";
And also if you would like to send the Cookies with the WebSocket connection request to the server, you should set any cookie by using the WebSocket.SetCookie (WebSocketSharp.Net.Cookie)
method before connecting, such as the following.
-ws.SetCookie (new Cookie ("name", "nobita"));
+ws.SetCookie (new Cookie ("name", "nobita"));
As a WebSocket Server, if you would like to get the Query String included in each WebSocket connection request, you should access the WebSocketBehavior.Context.QueryString
property, such as the following.
-public class Chat : WebSocketBehavior
+public class Chat : WebSocketBehavior
{
- private string _name;
+ private string _name;
...
- protected override void OnOpen ()
+ protected override void OnOpen ()
{
- _name = Context.QueryString["name"];
+ _name = Context.QueryString["name"];
}
...
@@ -544,14 +527,14 @@ wssv.UserCredentialsFinder = id => {
And if you would like to validate the Origin header, Cookies, or both included in each WebSocket connection request, you should set each validation with your WebSocketBehavior
, for example, by using the AddWebSocketService<TBehavior> (string, Func<TBehavior>)
method with initializing, such as the following.
wssv.AddWebSocketService<Chat> (
- "/Chat",
- () => new Chat () {
+ "/Chat",
+ () => new Chat () {
OriginValidator = val => {
// Check the value of the Origin header, and return true if valid.
Uri origin;
return !val.IsNullOrEmpty () &&
Uri.TryCreate (val, UriKind.Absolute, out origin) &&
- origin.Host == "example.com";
+ origin.Host == "example.com";
},
CookiesValidator = (req, res) => {
// Check the Cookies in 'req', and set the Cookies to send to the client with 'res'
@@ -574,8 +557,8 @@ wssv.UserCredentialsFinder = id => {
If you would like to connect to a WebSocket server through the HTTP Proxy server, you should set the proxy server URL, and if necessary, a pair of user name and password for the proxy server authentication (Basic/Digest), by using the WebSocket.SetProxy (string, string, string)
method before connecting.
-var ws = new WebSocket ("ws://example.com");
-ws.SetProxy ("http://localhost:3128", "nobita", "password");
+var ws = new WebSocket ("ws://example.com");
+ws.SetProxy ("http://localhost:3128", "nobita", "password");
I tested this with the Squid. And it's necessary to disable the following configuration option in squid.conf (e.g. /etc/squid/squid.conf
).
@@ -598,7 +581,7 @@ ws.SetProxy ("http://localhost:3
And if you would like to output a log, you should use any of the output methods. The following outputs a log with LogLevel.Debug
.
-ws.Log.Debug ("This is a debug message.");
+ws.Log.Debug ("This is a debug message.");
The WebSocketServer
and HttpServer
classes include the same logging function.
@@ -639,7 +622,7 @@ ws.SetProxy ("http://localhost:3
- The WebSocket Protocol
- The WebSocket API
-- Compression Extensions for WebSocket
+- Compression Extensions for WebSocket
Thanks for translating to japanese.
@@ -653,11 +636,16 @@ ws.SetProxy ("http://localhost:3
License
websocket-sharp is provided under The MIT License.
-
-
-
-
@@ -669,4 +657,5 @@ ws.SetProxy ("http://localhost:3
-
\ No newline at end of file
+
+
diff --git a/params.json b/params.json
index 684453b2..ef4ea0a7 100644
--- a/params.json
+++ b/params.json
@@ -1 +1 @@
-{"name":"websocket-sharp","tagline":"A C# implementation of the WebSocket protocol client and server","body":"## Welcome to websocket-sharp! ##\r\n\r\n**websocket-sharp** supports:\r\n\r\n- **[RFC 6455](#supported-websocket-specifications)**\r\n- **[WebSocket Client](#websocket-client)** and **[Server](#websocket-server)**\r\n- **[Per-message Compression](#per-message-compression)** extension\r\n- **[Secure Connection](#secure-connection)**\r\n- **[HTTP Authentication](#http-authentication)**\r\n- **[Query String, Origin header and Cookies](#query-string-origin-header-and-cookies)**\r\n- **[Connecting through the HTTP Proxy server](#connecting-through-the-http-proxy-server)**\r\n- .NET **3.5** or later (includes compatible)\r\n\r\n## Build ##\r\n\r\nwebsocket-sharp is built as a single assembly, **websocket-sharp.dll**.\r\n\r\nwebsocket-sharp is developed with **[MonoDevelop]**. So the simple way to build is to open **websocket-sharp.sln** and run build for **websocket-sharp project** with any of the build configurations (e.g. `Debug`) in MonoDevelop.\r\n\r\n## Install ##\r\n\r\n### Self Build ###\r\n\r\nYou should add your **websocket-sharp.dll** (e.g. `/path/to/websocket-sharp/bin/Debug/websocket-sharp.dll`) to the library references of your project.\r\n\r\nIf you would like to use that dll in your **[Unity]** project, you should add it to any folder of your project (e.g. `Assets/Plugins`) in **Unity Editor**.\r\n\r\n### NuGet Gallery ###\r\n\r\nwebsocket-sharp is available on the **[NuGet Gallery]**, as still a **prerelease** version.\r\n\r\n- **[NuGet Gallery: websocket-sharp]**\r\n\r\nYou can add websocket-sharp to your project with the **NuGet Package Manager**, by using the following command in the **Package Manager Console**.\r\n\r\n PM> Install-Package WebSocketSharp -Pre\r\n\r\n### Unity Asset Store ###\r\n\r\nwebsocket-sharp is available on the **Unity Asset Store**.\r\n\r\n- **[WebSocket-Sharp for Unity]**\r\n\r\nIt works with **Unity Free**, but there are some limitations:\r\n\r\n- **[Security Sandbox of the Webplayer]** (server doesn't work in the webplayer)\r\n- **[.NET Socket Support for iOS/Android][Unity Licenses Comparison]** (requires iOS/Android Pro)\r\n- **.NET API 2.0 compatibility level for iOS/Android**\r\n\r\nUsing **.NET API 2.0 compatibility level for iOS/Android** requires to fix lack of some features for later than .NET 2.0, such as the `System.Func<...>` delegates (so i've fixed it in the asset package).\r\n\r\nAnd it's priced at **US$15**. I think your $15 makes this project more better and accelerated, **Thank you!**\r\n\r\n## Usage ##\r\n\r\n### WebSocket Client ###\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\n\r\nnamespace Example\r\n{\r\n public class Program\r\n {\r\n public static void Main (string[] args)\r\n {\r\n using (var ws = new WebSocket (\"ws://dragonsnest.far/Laputa\")) {\r\n ws.OnMessage += (sender, e) =>\r\n Console.WriteLine (\"Laputa says: \" + e.Data);\r\n\r\n ws.Connect ();\r\n ws.Send (\"BALUS\");\r\n Console.ReadKey (true);\r\n }\r\n }\r\n }\r\n}\r\n```\r\n\r\n#### Step 1 ####\r\n\r\nRequired namespace.\r\n\r\n```csharp\r\nusing WebSocketSharp;\r\n```\r\n\r\nThe `WebSocket` class exists in the `WebSocketSharp` namespace.\r\n\r\n#### Step 2 ####\r\n\r\nCreating a new instance of the `WebSocket` class with the WebSocket URL to connect.\r\n\r\n```csharp\r\nusing (var ws = new WebSocket (\"ws://example.com\")) {\r\n ...\r\n}\r\n```\r\n\r\nThe `WebSocket` class inherits the `System.IDisposable` interface, so you can use the `using` statement. And the WebSocket connection will be closed with close status `1001` (going away) when the control leaves the `using` block.\r\n\r\n#### Step 3 ####\r\n\r\nSetting the `WebSocket` events.\r\n\r\n##### WebSocket.OnOpen Event #####\r\n\r\nA `WebSocket.OnOpen` event occurs when the WebSocket connection has been established.\r\n\r\n```csharp\r\nws.OnOpen += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as the `System.EventArgs.Empty`, so you don't need to use it.\r\n\r\n##### WebSocket.OnMessage Event #####\r\n\r\nA `WebSocket.OnMessage` event occurs when the `WebSocket` receives a message.\r\n\r\n```csharp\r\nws.OnMessage += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as a `WebSocketSharp.MessageEventArgs`.\r\n\r\n`e.Type` property returns either `WebSocketSharp.Opcode.Text` or `WebSocketSharp.Opcode.Binary` that represents the type of the message. So by checking it, you can determine which item you should use.\r\n\r\nIf it returns `Opcode.Text`, you should use `e.Data` property that returns a `string` (represents the **Text** message).\r\n\r\nOr if it returns `Opcode.Binary`, you should use `e.RawData` property that returns a `byte[]` (represents the **Binary** message).\r\n\r\n```csharp\r\nif (e.Type == Opcode.Text) {\r\n // Do something with e.Data.\r\n ...\r\n\r\n return;\r\n}\r\n\r\nif (e.Type == Opcode.Binary) {\r\n // Do something with e.RawData.\r\n ...\r\n\r\n return;\r\n}\r\n```\r\n\r\n##### WebSocket.OnError Event #####\r\n\r\nA `WebSocket.OnError` event occurs when the `WebSocket` gets an error.\r\n\r\n```csharp\r\nws.OnError += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as a `WebSocketSharp.ErrorEventArgs`.\r\n\r\n`e.Message` property returns a `string` that represents the error message.\r\n\r\nIf the error is due to an exception, `e.Exception` property returns a `System.Exception` instance that caused the error.\r\n\r\n##### WebSocket.OnClose Event #####\r\n\r\nA `WebSocket.OnClose` event occurs when the WebSocket connection has been closed.\r\n\r\n```csharp\r\nws.OnClose += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as a `WebSocketSharp.CloseEventArgs`.\r\n\r\n`e.Code` property returns a `ushort` that represents the status code indicating the reason for the close, and `e.Reason` property returns a `string` that represents the reason for the close.\r\n\r\n#### Step 4 ####\r\n\r\nConnecting to the WebSocket server.\r\n\r\n```csharp\r\nws.Connect ();\r\n```\r\n\r\nIf you would like to connect to the server asynchronously, you should use the `WebSocket.ConnectAsync ()` method.\r\n\r\n#### Step 5 ####\r\n\r\nSending a data to the WebSocket server.\r\n\r\n```csharp\r\nws.Send (data);\r\n```\r\n\r\nThe `WebSocket.Send` method is overloaded.\r\n\r\nYou can use the `WebSocket.Send (string)`, `WebSocket.Send (byte[])`, or `WebSocket.Send (System.IO.FileInfo)` method to send a data.\r\n\r\nIf you would like to send a data asynchronously, you should use the `WebSocket.SendAsync` method.\r\n\r\n```csharp\r\nws.SendAsync (data, completed);\r\n```\r\n\r\nAnd also if you would like to do something when the send is complete, you should set `completed` to any `Action` delegate.\r\n\r\n#### Step 6 ####\r\n\r\nClosing the WebSocket connection.\r\n\r\n```csharp\r\nws.Close (code, reason);\r\n```\r\n\r\nIf you would like to close the connection explicitly, you should use the `WebSocket.Close` method.\r\n\r\nThe `WebSocket.Close` method is overloaded.\r\n\r\nYou can use the `WebSocket.Close ()`, `WebSocket.Close (ushort)`, `WebSocket.Close (WebSocketSharp.CloseStatusCode)`, `WebSocket.Close (ushort, string)`, or `WebSocket.Close (WebSocketSharp.CloseStatusCode, string)` method to close the connection.\r\n\r\nIf you would like to close the connection asynchronously, you should use the `WebSocket.CloseAsync` method.\r\n\r\n### WebSocket Server ###\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\nusing WebSocketSharp.Server;\r\n\r\nnamespace Example\r\n{\r\n public class Laputa : WebSocketBehavior\r\n {\r\n protected override void OnMessage (MessageEventArgs e)\r\n {\r\n var msg = e.Data == \"BALUS\"\r\n ? \"I've been balused already...\"\r\n : \"I'm not available now.\";\r\n\r\n Send (msg);\r\n }\r\n }\r\n\r\n public class Program\r\n {\r\n public static void Main (string[] args)\r\n {\r\n var wssv = new WebSocketServer (\"ws://dragonsnest.far\");\r\n wssv.AddWebSocketService (\"/Laputa\");\r\n wssv.Start ();\r\n Console.ReadKey (true);\r\n wssv.Stop ();\r\n }\r\n }\r\n}\r\n```\r\n\r\n#### Step 1 ####\r\n\r\nRequired namespace.\r\n\r\n```csharp\r\nusing WebSocketSharp.Server;\r\n```\r\n\r\nThe `WebSocketBehavior` and `WebSocketServer` classes exist in the `WebSocketSharp.Server` namespace.\r\n\r\n#### Step 2 ####\r\n\r\nCreating the class that inherits the `WebSocketBehavior` class.\r\n\r\nFor example, if you would like to provide an echo service,\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\nusing WebSocketSharp.Server;\r\n\r\npublic class Echo : WebSocketBehavior\r\n{\r\n protected override void OnMessage (MessageEventArgs e)\r\n {\r\n Send (e.Data);\r\n }\r\n}\r\n```\r\n\r\nAnd if you would like to provide a chat service,\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\nusing WebSocketSharp.Server;\r\n\r\npublic class Chat : WebSocketBehavior\r\n{\r\n private string _suffix;\r\n\r\n public Chat ()\r\n : this (null)\r\n {\r\n }\r\n\r\n public Chat (string suffix)\r\n {\r\n _suffix = suffix ?? String.Empty;\r\n }\r\n\r\n protected override void OnMessage (MessageEventArgs e)\r\n {\r\n Sessions.Broadcast (e.Data + _suffix);\r\n }\r\n}\r\n```\r\n\r\nYou can define the behavior of any WebSocket service by creating the class that inherits the `WebSocketBehavior` class.\r\n\r\nIf you override the `WebSocketBehavior.OnMessage (MessageEventArgs)` method, it's called when the `WebSocket` used in the current session in the service receives a message.\r\n\r\nAnd if you override the `WebSocketBehavior.OnOpen ()`, `WebSocketBehavior.OnError (ErrorEventArgs)`, and `WebSocketBehavior.OnClose (CloseEventArgs)` methods, each of them is called when each event of the `WebSocket` (the `OnOpen`, `OnError`, and `OnClose` events) occurs.\r\n\r\nThe `WebSocketBehavior.Send` method sends a data to the client on the current session in the service.\r\n\r\nIf you would like to access the sessions in the service, you should use the `WebSocketBehavior.Sessions` property (returns a `WebSocketSharp.Server.WebSocketSessionManager`).\r\n\r\nThe `WebSocketBehavior.Sessions.Broadcast` method broadcasts a data to every client in the service.\r\n\r\n#### Step 3 ####\r\n\r\nCreating a new instance of the `WebSocketServer` class.\r\n\r\n```csharp\r\nvar wssv = new WebSocketServer (4649);\r\nwssv.AddWebSocketService (\"/Echo\");\r\nwssv.AddWebSocketService (\"/Chat\");\r\nwssv.AddWebSocketService (\"/ChatWithNyan\", () => new Chat (\" Nyan!\"));\r\n```\r\n\r\nYou can add any WebSocket service to your `WebSocketServer` with the specified behavior and path to the service, by using the `WebSocketServer.AddWebSocketService (string)` or `WebSocketServer.AddWebSocketService (string, Func)` method.\r\n\r\nThe type of `TBehaviorWithNew` must inherit the `WebSocketBehavior` class, and must have a public parameterless constructor.\r\n\r\nAnd also the type of `TBehavior` must inherit the `WebSocketBehavior` class.\r\n\r\nSo you can use the classes created in **Step 2** to add the service.\r\n\r\nIf you create a instance of the `WebSocketServer` class without a port number, the `WebSocketServer` class set the port number to **80** automatically. So it's necessary to run with root permission.\r\n\r\n $ sudo mono example2.exe\r\n\r\n#### Step 4 ####\r\n\r\nStarting the WebSocket server.\r\n\r\n```csharp\r\nwssv.Start ();\r\n```\r\n\r\n#### Step 5 ####\r\n\r\nStopping the WebSocket server.\r\n\r\n```csharp\r\nwssv.Stop (code, reason);\r\n```\r\n\r\nThe `WebSocketServer.Stop` method is overloaded.\r\n\r\nYou can use the `WebSocketServer.Stop ()`, `WebSocketServer.Stop (ushort, string)`, or `WebSocketServer.Stop (WebSocketSharp.CloseStatusCode, string)` method to stop the server.\r\n\r\n### HTTP Server with the WebSocket ###\r\n\r\nI modified the `System.Net.HttpListener`, `System.Net.HttpListenerContext`, and some other classes of **[Mono]** to create the HTTP server that allows to accept the WebSocket connection requests.\r\n\r\nSo websocket-sharp provides the `WebSocketSharp.Server.HttpServer` class.\r\n\r\nYou can add any WebSocket service to your `HttpServer` with the specified behavior and path to the service, by using the `HttpServer.AddWebSocketService (string)` or `HttpServer.AddWebSocketService (string, Func)` method.\r\n\r\n```csharp\r\nvar httpsv = new HttpServer (4649);\r\nhttpsv.AddWebSocketService (\"/Echo\");\r\nhttpsv.AddWebSocketService (\"/Chat\");\r\nhttpsv.AddWebSocketService (\"/ChatWithNyan\", () => new Chat (\" Nyan!\"));\r\n```\r\n\r\nFor more information, would you see **[Example3]**?\r\n\r\n### WebSocket Extensions ###\r\n\r\n#### Per-message Compression ####\r\n\r\nwebsocket-sharp supports the **[Per-message Compression][compression]** extension. (But it doesn't support with the [extension parameters].)\r\n\r\nIf you would like to enable this extension as a WebSocket client, you should set such as the following.\r\n\r\n```csharp\r\nws.Compression = CompressionMethod.Deflate;\r\n```\r\n\r\nAnd then your client will send the following header with the connection request to the server.\r\n\r\n Sec-WebSocket-Extensions: permessage-deflate\r\n\r\nIf the server supports this extension, it will return the same header. And when your client receives it, this extension will be available.\r\n\r\n### Secure Connection ###\r\n\r\nwebsocket-sharp supports the **Secure Connection** with **SSL/TLS**.\r\n\r\nAs a **WebSocket Client**, you should create a new instance of the `WebSocket` class with the **wss** scheme WebSocket URL.\r\n\r\n```csharp\r\nusing (var ws = new WebSocket (\"wss://example.com\")) {\r\n ...\r\n}\r\n```\r\n\r\nAnd if you would like to use the custom validation for the server certificate, you should set the `WebSocket.SslConfiguration.ServerCertificateValidationCallback` property.\r\n\r\n```csharp\r\nws.SslConfiguration.ServerCertificateValidationCallback =\r\n (sender, certificate, chain, sslPolicyErrors) => {\r\n // Do something to validate the server certificate.\r\n ...\r\n\r\n return true; // If the server certificate is valid.\r\n };\r\n```\r\n\r\nIf you set this property to nothing, the validation does nothing with the server certificate, and returns `true`.\r\n\r\nAs a **WebSocket Server**, you should create a new instance of the `WebSocketServer` or `HttpServer` class with some settings for secure connection, such as the following.\r\n\r\n```csharp\r\nvar wssv = new WebSocketServer (4649, true);\r\nwssv.SslConfiguration.ServerCertificate =\r\n new X509Certificate2 (\"/path/to/cert.pfx\", \"password for cert.pfx\");\r\n```\r\n\r\n### HTTP Authentication ###\r\n\r\nwebsocket-sharp supports the **[HTTP Authentication (Basic/Digest)][rfc2617]**.\r\n\r\nAs a **WebSocket Client**, you should set a pair of user name and password for the HTTP authentication, by using the `WebSocket.SetCredentials (string, string, bool)` method before connecting.\r\n\r\n```csharp\r\nws.SetCredentials (\"nobita\", \"password\", preAuth);\r\n```\r\n\r\nIf `preAuth` is `true`, the `WebSocket` sends the Basic authentication credentials with the first connection request to the server.\r\n\r\nOr if `preAuth` is `false`, the `WebSocket` sends either the Basic or Digest (determined by the unauthorized response to the first connection request) authentication credentials with the second connection request to the server.\r\n\r\nAs a **WebSocket Server**, you should set an HTTP authentication scheme, a realm, and any function to find the user credentials before starting, such as the following.\r\n\r\n```csharp\r\nwssv.AuthenticationSchemes = AuthenticationSchemes.Basic;\r\nwssv.Realm = \"WebSocket Test\";\r\nwssv.UserCredentialsFinder = id => {\r\n var name = id.Name;\r\n\r\n // Return user name, password, and roles.\r\n return name == \"nobita\"\r\n ? new NetworkCredential (name, \"password\", \"gunfighter\")\r\n : null; // If the user credentials aren't found.\r\n};\r\n```\r\n\r\nIf you would like to provide the Digest authentication, you should set such as the following.\r\n\r\n```csharp\r\nwssv.AuthenticationSchemes = AuthenticationSchemes.Digest;\r\n```\r\n\r\n### Query String, Origin header and Cookies ###\r\n\r\nAs a **WebSocket Client**, if you would like to send the **Query String** with the WebSocket connection request to the server, you should create a new instance of the `WebSocket` class with the WebSocket URL that includes the [Query] string parameters.\r\n\r\n```csharp\r\nusing (var ws = new WebSocket (\"ws://example.com/?name=nobita\")) {\r\n ...\r\n}\r\n```\r\n\r\nAnd if you would like to send the **Origin header** with the WebSocket connection request to the server, you should set the `WebSocket.Origin` property to an allowable value as the [Origin header] before connecting, such as the following.\r\n\r\n```csharp\r\nws.Origin = \"http://example.com\";\r\n```\r\n\r\nAnd also if you would like to send the **Cookies** with the WebSocket connection request to the server, you should set any cookie by using the `WebSocket.SetCookie (WebSocketSharp.Net.Cookie)` method before connecting, such as the following.\r\n\r\n```csharp\r\nws.SetCookie (new Cookie (\"name\", \"nobita\"));\r\n```\r\n\r\nAs a **WebSocket Server**, if you would like to get the **Query String** included in each WebSocket connection request, you should access the `WebSocketBehavior.Context.QueryString` property, such as the following.\r\n\r\n```csharp\r\npublic class Chat : WebSocketBehavior\r\n{\r\n private string _name;\r\n ...\r\n\r\n protected override void OnOpen ()\r\n {\r\n _name = Context.QueryString[\"name\"];\r\n }\r\n\r\n ...\r\n}\r\n```\r\n\r\nAnd if you would like to validate the **Origin header**, **Cookies**, or both included in each WebSocket connection request, you should set each validation with your `WebSocketBehavior`, for example, by using the `AddWebSocketService (string, Func)` method with initializing, such as the following.\r\n\r\n```csharp\r\nwssv.AddWebSocketService (\r\n \"/Chat\",\r\n () => new Chat () {\r\n OriginValidator = val => {\r\n // Check the value of the Origin header, and return true if valid.\r\n Uri origin;\r\n return !val.IsNullOrEmpty () &&\r\n Uri.TryCreate (val, UriKind.Absolute, out origin) &&\r\n origin.Host == \"example.com\";\r\n },\r\n CookiesValidator = (req, res) => {\r\n // Check the Cookies in 'req', and set the Cookies to send to the client with 'res'\r\n // if necessary.\r\n foreach (Cookie cookie in req) {\r\n cookie.Expired = true;\r\n res.Add (cookie);\r\n }\r\n\r\n return true; // If valid.\r\n }\r\n });\r\n```\r\n\r\nAnd also if you would like to get each value of the Origin header and cookies, you should access each of the `WebSocketBehavior.Context.Origin` and `WebSocketBehavior.Context.CookieCollection` properties.\r\n\r\n### Connecting through the HTTP Proxy server ###\r\n\r\nwebsocket-sharp supports to connect through the **HTTP Proxy** server.\r\n\r\nIf you would like to connect to a WebSocket server through the HTTP Proxy server, you should set the proxy server URL, and if necessary, a pair of user name and password for the proxy server authentication (Basic/Digest), by using the `WebSocket.SetProxy (string, string, string)` method before connecting.\r\n\r\n```csharp\r\nvar ws = new WebSocket (\"ws://example.com\");\r\nws.SetProxy (\"http://localhost:3128\", \"nobita\", \"password\");\r\n```\r\n\r\nI tested this with the [Squid]. And it's necessary to disable the following configuration option in **squid.conf** (e.g. `/etc/squid/squid.conf`).\r\n\r\n```\r\n# Deny CONNECT to other than SSL ports\r\n#http_access deny CONNECT !SSL_ports\r\n```\r\n\r\n### Logging ###\r\n\r\nThe `WebSocket` class includes the own logging function.\r\n\r\nYou can use it with the `WebSocket.Log` property (returns a `WebSocketSharp.Logger`).\r\n\r\nSo if you would like to change the current logging level (`WebSocketSharp.LogLevel.Error` as the default), you should set the `WebSocket.Log.Level` property to any of the `LogLevel` enum values.\r\n\r\n```csharp\r\nws.Log.Level = LogLevel.Debug;\r\n```\r\n\r\nThe above means a log with lower than `LogLevel.Debug` cannot be outputted.\r\n\r\nAnd if you would like to output a log, you should use any of the output methods. The following outputs a log with `LogLevel.Debug`.\r\n\r\n```csharp\r\nws.Log.Debug (\"This is a debug message.\");\r\n```\r\n\r\nThe `WebSocketServer` and `HttpServer` classes include the same logging function.\r\n\r\n## Examples ##\r\n\r\nExamples using websocket-sharp.\r\n\r\n### Example ###\r\n\r\n**[Example]** connects to the **[Echo server]** with the WebSocket.\r\n\r\n### Example1 ###\r\n\r\n**[Example1]** connects to the **[Audio Data delivery server]** with the WebSocket. (But it's only implemented the chat feature, still unfinished.)\r\n\r\nAnd Example1 uses **[Json.NET]**.\r\n\r\n### Example2 ###\r\n\r\n**[Example2]** starts a WebSocket server.\r\n\r\n### Example3 ###\r\n\r\n**[Example3]** starts an HTTP server that allows to accept the WebSocket connection requests.\r\n\r\nWould you access to [http://localhost:4649](http://localhost:4649) to do **WebSocket Echo Test** with your web browser after Example3 running?\r\n\r\n## Supported WebSocket Specifications ##\r\n\r\nwebsocket-sharp supports **[RFC 6455][rfc6455]**, and it's based on the following WebSocket references:\r\n\r\n- **[The WebSocket Protocol][rfc6455]**\r\n- **[The WebSocket API][api]**\r\n- **[Compression Extensions for WebSocket][compression]**\r\n\r\nThanks for translating to japanese.\r\n\r\n- **[The WebSocket Protocol 日本語訳][rfc6455_ja]**\r\n- **[The WebSocket API 日本語訳][api_ja]**\r\n\r\n## License ##\r\n\r\nwebsocket-sharp is provided under **[The MIT License]**.\r\n\r\n\r\n[Audio Data delivery server]: http://agektmr.node-ninja.com:3000\r\n[Echo server]: http://www.websocket.org/echo.html\r\n[Example]: https://github.com/sta/websocket-sharp/tree/master/Example\r\n[Example1]: https://github.com/sta/websocket-sharp/tree/master/Example1\r\n[Example2]: https://github.com/sta/websocket-sharp/tree/master/Example2\r\n[Example3]: https://github.com/sta/websocket-sharp/tree/master/Example3\r\n[Json.NET]: http://james.newtonking.com/projects/json-net.aspx\r\n[Mono]: http://www.mono-project.com\r\n[MonoDevelop]: http://monodevelop.com\r\n[NuGet Gallery]: http://www.nuget.org\r\n[NuGet Gallery: websocket-sharp]: http://www.nuget.org/packages/WebSocketSharp\r\n[Origin header]: http://tools.ietf.org/html/rfc6454#section-7\r\n[Query]: http://tools.ietf.org/html/rfc3986#section-3.4\r\n[Security Sandbox of the Webplayer]: http://docs.unity3d.com/Manual/SecuritySandbox.html\r\n[Squid]: http://www.squid-cache.org\r\n[The MIT License]: https://raw.github.com/sta/websocket-sharp/master/LICENSE.txt\r\n[Unity]: http://unity3d.com\r\n[Unity Licenses Comparison]: http://unity3d.com/unity/licenses\r\n[WebSocket-Sharp for Unity]: http://u3d.as/content/sta-blockhead/websocket-sharp-for-unity\r\n[api]: http://www.w3.org/TR/websockets\r\n[api_ja]: http://www.hcn.zaq.ne.jp/___/WEB/WebSocket-ja.html\r\n[compression]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-09\r\n[extension parameters]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-09#section-8.1\r\n[rfc2617]: http://tools.ietf.org/html/rfc2617\r\n[rfc6455]: http://tools.ietf.org/html/rfc6455\r\n[rfc6455_ja]: http://www.hcn.zaq.ne.jp/___/WEB/RFC6455-ja.html\r\n","google":"UA-9752433-2","note":"Don't delete this file! It's used internally to help with page regeneration."}
\ No newline at end of file
+{"name":"websocket-sharp","tagline":"A C# implementation of the WebSocket protocol client and server","body":"## Welcome to websocket-sharp! ##\r\n\r\n**websocket-sharp** supports:\r\n\r\n- **[RFC 6455](#supported-websocket-specifications)**\r\n- **[WebSocket Client](#websocket-client)** and **[Server](#websocket-server)**\r\n- **[Per-message Compression](#per-message-compression)** extension\r\n- **[Secure Connection](#secure-connection)**\r\n- **[HTTP Authentication](#http-authentication)**\r\n- **[Query String, Origin header and Cookies](#query-string-origin-header-and-cookies)**\r\n- **[Connecting through the HTTP Proxy server](#connecting-through-the-http-proxy-server)**\r\n- .NET **3.5** or later (includes compatible)\r\n\r\n## Build ##\r\n\r\nwebsocket-sharp is built as a single assembly, **websocket-sharp.dll**.\r\n\r\nwebsocket-sharp is developed with **[MonoDevelop]**. So the simple way to build is to open **websocket-sharp.sln** and run build for **websocket-sharp project** with any of the build configurations (e.g. `Debug`) in MonoDevelop.\r\n\r\n## Install ##\r\n\r\n### Self Build ###\r\n\r\nYou should add your **websocket-sharp.dll** (e.g. `/path/to/websocket-sharp/bin/Debug/websocket-sharp.dll`) to the library references of your project.\r\n\r\nIf you would like to use that dll in your **[Unity]** project, you should add it to any folder of your project (e.g. `Assets/Plugins`) in **Unity Editor**.\r\n\r\n### NuGet Gallery ###\r\n\r\nwebsocket-sharp is available on the **[NuGet Gallery]**, as still a **prerelease** version.\r\n\r\n- **[NuGet Gallery: websocket-sharp]**\r\n\r\nYou can add websocket-sharp to your project with the **NuGet Package Manager**, by using the following command in the **Package Manager Console**.\r\n\r\n PM> Install-Package WebSocketSharp -Pre\r\n\r\n### Unity Asset Store ###\r\n\r\nwebsocket-sharp is available on the **Unity Asset Store**.\r\n\r\n- **[WebSocket-Sharp for Unity]**\r\n\r\nIt works with **Unity Free**, but there are some limitations:\r\n\r\n- **[Security Sandbox of the Webplayer]** (the server doesn't work in the webplayer)\r\n- **[.NET Socket Support for iOS/Android][Unity Licenses Comparison]** (requires iOS/Android Pro)\r\n- **Limited support for the System.IO.Compression** (the compression extension isn't available on Windows)\r\n- **.NET API 2.0 compatibility level for iOS/Android**\r\n\r\nUsing **.NET API 2.0 compatibility level for iOS/Android** requires to fix lack of some features for later than .NET 2.0, such as the `System.Func<...>` delegates (so i've fixed it in the asset package).\r\n\r\nAnd it's priced at **US$15**. I think your $15 makes this project more better and accelerated, **Thank you!**\r\n\r\n## Usage ##\r\n\r\n### WebSocket Client ###\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\n\r\nnamespace Example\r\n{\r\n public class Program\r\n {\r\n public static void Main (string[] args)\r\n {\r\n using (var ws = new WebSocket (\"ws://dragonsnest.far/Laputa\")) {\r\n ws.OnMessage += (sender, e) =>\r\n Console.WriteLine (\"Laputa says: \" + e.Data);\r\n\r\n ws.Connect ();\r\n ws.Send (\"BALUS\");\r\n Console.ReadKey (true);\r\n }\r\n }\r\n }\r\n}\r\n```\r\n\r\n#### Step 1 ####\r\n\r\nRequired namespace.\r\n\r\n```csharp\r\nusing WebSocketSharp;\r\n```\r\n\r\nThe `WebSocket` class exists in the `WebSocketSharp` namespace.\r\n\r\n#### Step 2 ####\r\n\r\nCreating a new instance of the `WebSocket` class with the WebSocket URL to connect.\r\n\r\n```csharp\r\nusing (var ws = new WebSocket (\"ws://example.com\")) {\r\n ...\r\n}\r\n```\r\n\r\nThe `WebSocket` class inherits the `System.IDisposable` interface, so you can use the `using` statement. And the WebSocket connection will be closed with close status `1001` (going away) when the control leaves the `using` block.\r\n\r\n#### Step 3 ####\r\n\r\nSetting the `WebSocket` events.\r\n\r\n##### WebSocket.OnOpen Event #####\r\n\r\nA `WebSocket.OnOpen` event occurs when the WebSocket connection has been established.\r\n\r\n```csharp\r\nws.OnOpen += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as the `System.EventArgs.Empty`, so you don't need to use it.\r\n\r\n##### WebSocket.OnMessage Event #####\r\n\r\nA `WebSocket.OnMessage` event occurs when the `WebSocket` receives a message.\r\n\r\n```csharp\r\nws.OnMessage += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as a `WebSocketSharp.MessageEventArgs`.\r\n\r\n`e.Type` property returns either `WebSocketSharp.Opcode.Text` or `WebSocketSharp.Opcode.Binary` that represents the type of the message. So by checking it, you can determine which item you should use.\r\n\r\nIf it returns `Opcode.Text`, you should use `e.Data` property that returns a `string` (represents the **Text** message).\r\n\r\nOr if it returns `Opcode.Binary`, you should use `e.RawData` property that returns a `byte[]` (represents the **Binary** message).\r\n\r\n```csharp\r\nif (e.Type == Opcode.Text) {\r\n // Do something with e.Data.\r\n ...\r\n\r\n return;\r\n}\r\n\r\nif (e.Type == Opcode.Binary) {\r\n // Do something with e.RawData.\r\n ...\r\n\r\n return;\r\n}\r\n```\r\n\r\n##### WebSocket.OnError Event #####\r\n\r\nA `WebSocket.OnError` event occurs when the `WebSocket` gets an error.\r\n\r\n```csharp\r\nws.OnError += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as a `WebSocketSharp.ErrorEventArgs`.\r\n\r\n`e.Message` property returns a `string` that represents the error message.\r\n\r\nIf the error is due to an exception, `e.Exception` property returns a `System.Exception` instance that caused the error.\r\n\r\n##### WebSocket.OnClose Event #####\r\n\r\nA `WebSocket.OnClose` event occurs when the WebSocket connection has been closed.\r\n\r\n```csharp\r\nws.OnClose += (sender, e) => {\r\n ...\r\n};\r\n```\r\n\r\n`e` has passed as a `WebSocketSharp.CloseEventArgs`.\r\n\r\n`e.Code` property returns a `ushort` that represents the status code indicating the reason for the close, and `e.Reason` property returns a `string` that represents the reason for the close.\r\n\r\n#### Step 4 ####\r\n\r\nConnecting to the WebSocket server.\r\n\r\n```csharp\r\nws.Connect ();\r\n```\r\n\r\nIf you would like to connect to the server asynchronously, you should use the `WebSocket.ConnectAsync ()` method.\r\n\r\n#### Step 5 ####\r\n\r\nSending data to the WebSocket server.\r\n\r\n```csharp\r\nws.Send (data);\r\n```\r\n\r\nThe `WebSocket.Send` method is overloaded.\r\n\r\nYou can use the `WebSocket.Send (string)`, `WebSocket.Send (byte[])`, or `WebSocket.Send (System.IO.FileInfo)` method to send the data.\r\n\r\nIf you would like to send the data asynchronously, you should use the `WebSocket.SendAsync` method.\r\n\r\n```csharp\r\nws.SendAsync (data, completed);\r\n```\r\n\r\nAnd also if you would like to do something when the send is complete, you should set `completed` to any `Action` delegate.\r\n\r\n#### Step 6 ####\r\n\r\nClosing the WebSocket connection.\r\n\r\n```csharp\r\nws.Close (code, reason);\r\n```\r\n\r\nIf you would like to close the connection explicitly, you should use the `WebSocket.Close` method.\r\n\r\nThe `WebSocket.Close` method is overloaded.\r\n\r\nYou can use the `WebSocket.Close ()`, `WebSocket.Close (ushort)`, `WebSocket.Close (WebSocketSharp.CloseStatusCode)`, `WebSocket.Close (ushort, string)`, or `WebSocket.Close (WebSocketSharp.CloseStatusCode, string)` method to close the connection.\r\n\r\nIf you would like to close the connection asynchronously, you should use the `WebSocket.CloseAsync` method.\r\n\r\n### WebSocket Server ###\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\nusing WebSocketSharp.Server;\r\n\r\nnamespace Example\r\n{\r\n public class Laputa : WebSocketBehavior\r\n {\r\n protected override void OnMessage (MessageEventArgs e)\r\n {\r\n var msg = e.Data == \"BALUS\"\r\n ? \"I've been balused already...\"\r\n : \"I'm not available now.\";\r\n\r\n Send (msg);\r\n }\r\n }\r\n\r\n public class Program\r\n {\r\n public static void Main (string[] args)\r\n {\r\n var wssv = new WebSocketServer (\"ws://dragonsnest.far\");\r\n wssv.AddWebSocketService (\"/Laputa\");\r\n wssv.Start ();\r\n Console.ReadKey (true);\r\n wssv.Stop ();\r\n }\r\n }\r\n}\r\n```\r\n\r\n#### Step 1 ####\r\n\r\nRequired namespace.\r\n\r\n```csharp\r\nusing WebSocketSharp.Server;\r\n```\r\n\r\nThe `WebSocketBehavior` and `WebSocketServer` classes exist in the `WebSocketSharp.Server` namespace.\r\n\r\n#### Step 2 ####\r\n\r\nCreating the class that inherits the `WebSocketBehavior` class.\r\n\r\nFor example, if you would like to provide an echo service,\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\nusing WebSocketSharp.Server;\r\n\r\npublic class Echo : WebSocketBehavior\r\n{\r\n protected override void OnMessage (MessageEventArgs e)\r\n {\r\n Send (e.Data);\r\n }\r\n}\r\n```\r\n\r\nAnd if you would like to provide a chat service,\r\n\r\n```csharp\r\nusing System;\r\nusing WebSocketSharp;\r\nusing WebSocketSharp.Server;\r\n\r\npublic class Chat : WebSocketBehavior\r\n{\r\n private string _suffix;\r\n\r\n public Chat ()\r\n : this (null)\r\n {\r\n }\r\n\r\n public Chat (string suffix)\r\n {\r\n _suffix = suffix ?? String.Empty;\r\n }\r\n\r\n protected override void OnMessage (MessageEventArgs e)\r\n {\r\n Sessions.Broadcast (e.Data + _suffix);\r\n }\r\n}\r\n```\r\n\r\nYou can define the behavior of any WebSocket service by creating the class that inherits the `WebSocketBehavior` class.\r\n\r\nIf you override the `WebSocketBehavior.OnMessage (MessageEventArgs)` method, it's called when the `WebSocket` used in a session in the service receives a message.\r\n\r\nAnd if you override the `WebSocketBehavior.OnOpen ()`, `WebSocketBehavior.OnError (ErrorEventArgs)`, and `WebSocketBehavior.OnClose (CloseEventArgs)` methods, each of them is called when each event of the `WebSocket` (the `OnOpen`, `OnError`, and `OnClose` events) occurs.\r\n\r\nThe `WebSocketBehavior.Send` method sends data to the client on a session in the service.\r\n\r\nIf you would like to access the sessions in the service, you should use the `WebSocketBehavior.Sessions` property (returns a `WebSocketSharp.Server.WebSocketSessionManager`).\r\n\r\nThe `WebSocketBehavior.Sessions.Broadcast` method sends data to every client in the service.\r\n\r\n#### Step 3 ####\r\n\r\nCreating a new instance of the `WebSocketServer` class.\r\n\r\n```csharp\r\nvar wssv = new WebSocketServer (4649);\r\nwssv.AddWebSocketService (\"/Echo\");\r\nwssv.AddWebSocketService (\"/Chat\");\r\nwssv.AddWebSocketService (\"/ChatWithNyan\", () => new Chat (\" Nyan!\"));\r\n```\r\n\r\nYou can add any WebSocket service to your `WebSocketServer` with the specified behavior and path to the service, by using the `WebSocketServer.AddWebSocketService (string)` or `WebSocketServer.AddWebSocketService (string, Func)` method.\r\n\r\nThe type of `TBehaviorWithNew` must inherit the `WebSocketBehavior` class, and must have a public parameterless constructor.\r\n\r\nAnd also the type of `TBehavior` must inherit the `WebSocketBehavior` class.\r\n\r\nSo you can use the classes created in **Step 2** to add the service.\r\n\r\nIf you create a instance of the `WebSocketServer` class without a port number, the `WebSocketServer` class set the port number to **80** automatically. So it's necessary to run with root permission.\r\n\r\n $ sudo mono example2.exe\r\n\r\n#### Step 4 ####\r\n\r\nStarting the WebSocket server.\r\n\r\n```csharp\r\nwssv.Start ();\r\n```\r\n\r\n#### Step 5 ####\r\n\r\nStopping the WebSocket server.\r\n\r\n```csharp\r\nwssv.Stop (code, reason);\r\n```\r\n\r\nThe `WebSocketServer.Stop` method is overloaded.\r\n\r\nYou can use the `WebSocketServer.Stop ()`, `WebSocketServer.Stop (ushort, string)`, or `WebSocketServer.Stop (WebSocketSharp.CloseStatusCode, string)` method to stop the server.\r\n\r\n### HTTP Server with the WebSocket ###\r\n\r\nI modified the `System.Net.HttpListener`, `System.Net.HttpListenerContext`, and some other classes of **[Mono]** to create the HTTP server that allows to accept the WebSocket connection requests.\r\n\r\nSo websocket-sharp provides the `WebSocketSharp.Server.HttpServer` class.\r\n\r\nYou can add any WebSocket service to your `HttpServer` with the specified behavior and path to the service, by using the `HttpServer.AddWebSocketService (string)` or `HttpServer.AddWebSocketService (string, Func)` method.\r\n\r\n```csharp\r\nvar httpsv = new HttpServer (4649);\r\nhttpsv.AddWebSocketService (\"/Echo\");\r\nhttpsv.AddWebSocketService (\"/Chat\");\r\nhttpsv.AddWebSocketService (\"/ChatWithNyan\", () => new Chat (\" Nyan!\"));\r\n```\r\n\r\nFor more information, would you see **[Example3]**?\r\n\r\n### WebSocket Extensions ###\r\n\r\n#### Per-message Compression ####\r\n\r\nwebsocket-sharp supports the **[Per-message Compression][compression]** extension. (But this doesn't support it with the [context take over].)\r\n\r\nIf you would like to enable this extension as a WebSocket client, you should set such as the following.\r\n\r\n```csharp\r\nws.Compression = CompressionMethod.Deflate;\r\n```\r\n\r\nAnd then your client will send the following header with the connection request to the server.\r\n\r\n Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r\n\r\nIf the server accepts this extension, it will return the same header which has the corresponding value. And when your client receives it, this extension will be available.\r\n\r\n### Secure Connection ###\r\n\r\nwebsocket-sharp supports the **Secure Connection** with **SSL/TLS**.\r\n\r\nAs a **WebSocket Client**, you should create a new instance of the `WebSocket` class with the **wss** scheme WebSocket URL.\r\n\r\n```csharp\r\nusing (var ws = new WebSocket (\"wss://example.com\")) {\r\n ...\r\n}\r\n```\r\n\r\nAnd if you would like to use the custom validation for the server certificate, you should set the `WebSocket.SslConfiguration.ServerCertificateValidationCallback` property.\r\n\r\n```csharp\r\nws.SslConfiguration.ServerCertificateValidationCallback =\r\n (sender, certificate, chain, sslPolicyErrors) => {\r\n // Do something to validate the server certificate.\r\n ...\r\n\r\n return true; // If the server certificate is valid.\r\n };\r\n```\r\n\r\nIf you set this property to nothing, the validation does nothing with the server certificate, and returns `true`.\r\n\r\nAs a **WebSocket Server**, you should create a new instance of the `WebSocketServer` or `HttpServer` class with some settings for secure connection, such as the following.\r\n\r\n```csharp\r\nvar wssv = new WebSocketServer (5963, true);\r\nwssv.SslConfiguration.ServerCertificate =\r\n new X509Certificate2 (\"/path/to/cert.pfx\", \"password for cert.pfx\");\r\n```\r\n\r\n### HTTP Authentication ###\r\n\r\nwebsocket-sharp supports the **[HTTP Authentication (Basic/Digest)][rfc2617]**.\r\n\r\nAs a **WebSocket Client**, you should set a pair of user name and password for the HTTP authentication, by using the `WebSocket.SetCredentials (string, string, bool)` method before connecting.\r\n\r\n```csharp\r\nws.SetCredentials (\"nobita\", \"password\", preAuth);\r\n```\r\n\r\nIf `preAuth` is `true`, the `WebSocket` sends the Basic authentication credentials with the first connection request to the server.\r\n\r\nOr if `preAuth` is `false`, the `WebSocket` sends either the Basic or Digest (determined by the unauthorized response to the first connection request) authentication credentials with the second connection request to the server.\r\n\r\nAs a **WebSocket Server**, you should set an HTTP authentication scheme, a realm, and any function to find the user credentials before starting, such as the following.\r\n\r\n```csharp\r\nwssv.AuthenticationSchemes = AuthenticationSchemes.Basic;\r\nwssv.Realm = \"WebSocket Test\";\r\nwssv.UserCredentialsFinder = id => {\r\n var name = id.Name;\r\n\r\n // Return user name, password, and roles.\r\n return name == \"nobita\"\r\n ? new NetworkCredential (name, \"password\", \"gunfighter\")\r\n : null; // If the user credentials aren't found.\r\n};\r\n```\r\n\r\nIf you would like to provide the Digest authentication, you should set such as the following.\r\n\r\n```csharp\r\nwssv.AuthenticationSchemes = AuthenticationSchemes.Digest;\r\n```\r\n\r\n### Query String, Origin header and Cookies ###\r\n\r\nAs a **WebSocket Client**, if you would like to send the **Query String** with the WebSocket connection request to the server, you should create a new instance of the `WebSocket` class with the WebSocket URL that includes the [Query] string parameters.\r\n\r\n```csharp\r\nusing (var ws = new WebSocket (\"ws://example.com/?name=nobita\")) {\r\n ...\r\n}\r\n```\r\n\r\nAnd if you would like to send the **Origin header** with the WebSocket connection request to the server, you should set the `WebSocket.Origin` property to an allowable value as the [Origin header] before connecting, such as the following.\r\n\r\n```csharp\r\nws.Origin = \"http://example.com\";\r\n```\r\n\r\nAnd also if you would like to send the **Cookies** with the WebSocket connection request to the server, you should set any cookie by using the `WebSocket.SetCookie (WebSocketSharp.Net.Cookie)` method before connecting, such as the following.\r\n\r\n```csharp\r\nws.SetCookie (new Cookie (\"name\", \"nobita\"));\r\n```\r\n\r\nAs a **WebSocket Server**, if you would like to get the **Query String** included in each WebSocket connection request, you should access the `WebSocketBehavior.Context.QueryString` property, such as the following.\r\n\r\n```csharp\r\npublic class Chat : WebSocketBehavior\r\n{\r\n private string _name;\r\n ...\r\n\r\n protected override void OnOpen ()\r\n {\r\n _name = Context.QueryString[\"name\"];\r\n }\r\n\r\n ...\r\n}\r\n```\r\n\r\nAnd if you would like to validate the **Origin header**, **Cookies**, or both included in each WebSocket connection request, you should set each validation with your `WebSocketBehavior`, for example, by using the `AddWebSocketService (string, Func)` method with initializing, such as the following.\r\n\r\n```csharp\r\nwssv.AddWebSocketService (\r\n \"/Chat\",\r\n () => new Chat () {\r\n OriginValidator = val => {\r\n // Check the value of the Origin header, and return true if valid.\r\n Uri origin;\r\n return !val.IsNullOrEmpty () &&\r\n Uri.TryCreate (val, UriKind.Absolute, out origin) &&\r\n origin.Host == \"example.com\";\r\n },\r\n CookiesValidator = (req, res) => {\r\n // Check the Cookies in 'req', and set the Cookies to send to the client with 'res'\r\n // if necessary.\r\n foreach (Cookie cookie in req) {\r\n cookie.Expired = true;\r\n res.Add (cookie);\r\n }\r\n\r\n return true; // If valid.\r\n }\r\n });\r\n```\r\n\r\nAnd also if you would like to get each value of the Origin header and cookies, you should access each of the `WebSocketBehavior.Context.Origin` and `WebSocketBehavior.Context.CookieCollection` properties.\r\n\r\n### Connecting through the HTTP Proxy server ###\r\n\r\nwebsocket-sharp supports to connect through the **HTTP Proxy** server.\r\n\r\nIf you would like to connect to a WebSocket server through the HTTP Proxy server, you should set the proxy server URL, and if necessary, a pair of user name and password for the proxy server authentication (Basic/Digest), by using the `WebSocket.SetProxy (string, string, string)` method before connecting.\r\n\r\n```csharp\r\nvar ws = new WebSocket (\"ws://example.com\");\r\nws.SetProxy (\"http://localhost:3128\", \"nobita\", \"password\");\r\n```\r\n\r\nI tested this with the [Squid]. And it's necessary to disable the following configuration option in **squid.conf** (e.g. `/etc/squid/squid.conf`).\r\n\r\n```\r\n# Deny CONNECT to other than SSL ports\r\n#http_access deny CONNECT !SSL_ports\r\n```\r\n\r\n### Logging ###\r\n\r\nThe `WebSocket` class includes the own logging function.\r\n\r\nYou can use it with the `WebSocket.Log` property (returns a `WebSocketSharp.Logger`).\r\n\r\nSo if you would like to change the current logging level (`WebSocketSharp.LogLevel.Error` as the default), you should set the `WebSocket.Log.Level` property to any of the `LogLevel` enum values.\r\n\r\n```csharp\r\nws.Log.Level = LogLevel.Debug;\r\n```\r\n\r\nThe above means a log with lower than `LogLevel.Debug` cannot be outputted.\r\n\r\nAnd if you would like to output a log, you should use any of the output methods. The following outputs a log with `LogLevel.Debug`.\r\n\r\n```csharp\r\nws.Log.Debug (\"This is a debug message.\");\r\n```\r\n\r\nThe `WebSocketServer` and `HttpServer` classes include the same logging function.\r\n\r\n## Examples ##\r\n\r\nExamples using websocket-sharp.\r\n\r\n### Example ###\r\n\r\n**[Example]** connects to the **[Echo server]** with the WebSocket.\r\n\r\n### Example1 ###\r\n\r\n**[Example1]** connects to the **[Audio Data delivery server]** with the WebSocket. (But it's only implemented the chat feature, still unfinished.)\r\n\r\nAnd Example1 uses **[Json.NET]**.\r\n\r\n### Example2 ###\r\n\r\n**[Example2]** starts a WebSocket server.\r\n\r\n### Example3 ###\r\n\r\n**[Example3]** starts an HTTP server that allows to accept the WebSocket connection requests.\r\n\r\nWould you access to [http://localhost:4649](http://localhost:4649) to do **WebSocket Echo Test** with your web browser after Example3 running?\r\n\r\n## Supported WebSocket Specifications ##\r\n\r\nwebsocket-sharp supports **[RFC 6455][rfc6455]**, and it's based on the following WebSocket references:\r\n\r\n- **[The WebSocket Protocol][rfc6455]**\r\n- **[The WebSocket API][api]**\r\n- **[Compression Extensions for WebSocket][compression]**\r\n\r\nThanks for translating to japanese.\r\n\r\n- **[The WebSocket Protocol 日本語訳][rfc6455_ja]**\r\n- **[The WebSocket API 日本語訳][api_ja]**\r\n\r\n## License ##\r\n\r\nwebsocket-sharp is provided under **[The MIT License]**.\r\n\r\n\r\n[Audio Data delivery server]: http://agektmr.node-ninja.com:3000\r\n[Echo server]: http://www.websocket.org/echo.html\r\n[Example]: https://github.com/sta/websocket-sharp/tree/master/Example\r\n[Example1]: https://github.com/sta/websocket-sharp/tree/master/Example1\r\n[Example2]: https://github.com/sta/websocket-sharp/tree/master/Example2\r\n[Example3]: https://github.com/sta/websocket-sharp/tree/master/Example3\r\n[Json.NET]: http://james.newtonking.com/projects/json-net.aspx\r\n[Mono]: http://www.mono-project.com\r\n[MonoDevelop]: http://monodevelop.com\r\n[NuGet Gallery]: http://www.nuget.org\r\n[NuGet Gallery: websocket-sharp]: http://www.nuget.org/packages/WebSocketSharp\r\n[Origin header]: http://tools.ietf.org/html/rfc6454#section-7\r\n[Query]: http://tools.ietf.org/html/rfc3986#section-3.4\r\n[Security Sandbox of the Webplayer]: http://docs.unity3d.com/Manual/SecuritySandbox.html\r\n[Squid]: http://www.squid-cache.org\r\n[The MIT License]: https://raw.github.com/sta/websocket-sharp/master/LICENSE.txt\r\n[Unity]: http://unity3d.com\r\n[Unity Licenses Comparison]: http://unity3d.com/unity/licenses\r\n[WebSocket-Sharp for Unity]: http://u3d.as/content/sta-blockhead/websocket-sharp-for-unity\r\n[api]: http://www.w3.org/TR/websockets\r\n[api_ja]: http://www.hcn.zaq.ne.jp/___/WEB/WebSocket-ja.html\r\n[compression]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-19\r\n[context take over]: http://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-19#section-8.1.1\r\n[rfc2617]: http://tools.ietf.org/html/rfc2617\r\n[rfc6455]: http://tools.ietf.org/html/rfc6455\r\n[rfc6455_ja]: http://www.hcn.zaq.ne.jp/___/WEB/RFC6455-ja.html\r\n","google":"UA-9752433-2","note":"Don't delete this file! It's used internally to help with page regeneration."}
\ No newline at end of file
diff --git a/stylesheets/github-light.css b/stylesheets/github-light.css
new file mode 100644
index 00000000..872a6f4b
--- /dev/null
+++ b/stylesheets/github-light.css
@@ -0,0 +1,116 @@
+/*
+ Copyright 2014 GitHub Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+.pl-c /* comment */ {
+ color: #969896;
+}
+
+.pl-c1 /* constant, markup.raw, meta.diff.header, meta.module-reference, meta.property-name, support, support.constant, support.variable, variable.other.constant */,
+.pl-s .pl-v /* string variable */ {
+ color: #0086b3;
+}
+
+.pl-e /* entity */,
+.pl-en /* entity.name */ {
+ color: #795da3;
+}
+
+.pl-s .pl-s1 /* string source */,
+.pl-smi /* storage.modifier.import, storage.modifier.package, storage.type.java, variable.other, variable.parameter.function */ {
+ color: #333;
+}
+
+.pl-ent /* entity.name.tag */ {
+ color: #63a35c;
+}
+
+.pl-k /* keyword, storage, storage.type */ {
+ color: #a71d5d;
+}
+
+.pl-pds /* punctuation.definition.string, string.regexp.character-class */,
+.pl-s /* string */,
+.pl-s .pl-pse .pl-s1 /* string punctuation.section.embedded source */,
+.pl-sr /* string.regexp */,
+.pl-sr .pl-cce /* string.regexp constant.character.escape */,
+.pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */,
+.pl-sr .pl-sre /* string.regexp source.ruby.embedded */ {
+ color: #183691;
+}
+
+.pl-v /* variable */ {
+ color: #ed6a43;
+}
+
+.pl-id /* invalid.deprecated */ {
+ color: #b52a1d;
+}
+
+.pl-ii /* invalid.illegal */ {
+ background-color: #b52a1d;
+ color: #f8f8f8;
+}
+
+.pl-sr .pl-cce /* string.regexp constant.character.escape */ {
+ color: #63a35c;
+ font-weight: bold;
+}
+
+.pl-ml /* markup.list */ {
+ color: #693a17;
+}
+
+.pl-mh /* markup.heading */,
+.pl-mh .pl-en /* markup.heading entity.name */,
+.pl-ms /* meta.separator */ {
+ color: #1d3e81;
+ font-weight: bold;
+}
+
+.pl-mq /* markup.quote */ {
+ color: #008080;
+}
+
+.pl-mi /* markup.italic */ {
+ color: #333;
+ font-style: italic;
+}
+
+.pl-mb /* markup.bold */ {
+ color: #333;
+ font-weight: bold;
+}
+
+.pl-md /* markup.deleted, meta.diff.header.from-file */ {
+ background-color: #ffecec;
+ color: #bd2c00;
+}
+
+.pl-mi1 /* markup.inserted, meta.diff.header.to-file */ {
+ background-color: #eaffea;
+ color: #55a532;
+}
+
+.pl-mdr /* meta.diff.range */ {
+ color: #795da3;
+ font-weight: bold;
+}
+
+.pl-mo /* meta.output */ {
+ color: #1d3e81;
+}
+
diff --git a/stylesheets/normalize.css b/stylesheets/normalize.css
index bc2ba932..30366a6e 100644
--- a/stylesheets/normalize.css
+++ b/stylesheets/normalize.css
@@ -1,10 +1,35 @@
-/* normalize.css 2012-02-07T12:37 UTC - http://github.com/necolas/normalize.css */
-/* =============================================================================
- HTML5 display definitions
- ========================================================================== */
-/*
- * Corrects block display not defined in IE6/7/8/9 & FF3
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+
+/**
+ * 1. Set default font family to sans-serif.
+ * 2. Prevent iOS text size adjust after orientation change, without disabling
+ * user zoom.
*/
+
+html {
+ font-family: sans-serif; /* 1 */
+ -ms-text-size-adjust: 100%; /* 2 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+}
+
+/**
+ * Remove default margin.
+ */
+
+body {
+ margin: 0;
+}
+
+/* HTML5 display definitions
+ ========================================================================== */
+
+/**
+ * Correct `block` display not defined for any HTML5 element in IE 8/9.
+ * Correct `block` display not defined for `details` or `summary` in IE 10/11
+ * and Firefox.
+ * Correct `block` display not defined for `main` in IE 11.
+ */
+
article,
aside,
details,
@@ -13,209 +38,126 @@ figure,
footer,
header,
hgroup,
+main,
+menu,
nav,
section,
summary {
display: block;
}
-/*
- * Corrects inline-block display not defined in IE6/7/8/9 & FF3
+/**
+ * 1. Correct `inline-block` display not defined in IE 8/9.
+ * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
*/
+
audio,
canvas,
+progress,
video {
- display: inline-block;
- *display: inline;
- *zoom: 1;
+ display: inline-block; /* 1 */
+ vertical-align: baseline; /* 2 */
}
-/*
- * Prevents modern browsers from displaying 'audio' without controls
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
*/
+
audio:not([controls]) {
display: none;
+ height: 0;
}
-/*
- * Addresses styling for 'hidden' attribute not present in IE7/8/9, FF3, S4
- * Known issue: no IE6 support
+/**
+ * Address `[hidden]` styling not present in IE 8/9/10.
+ * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
*/
-[hidden] {
+
+[hidden],
+template {
display: none;
}
-/* =============================================================================
- Base
+/* Links
========================================================================== */
-/*
- * 1. Corrects text resizing oddly in IE6/7 when body font-size is set using em units
- * http://clagnut.com/blog/348/#c790
- * 2. Prevents iOS text size adjust after orientation change, without disabling user zoom
- * www.456bereastreet.com/archive/201012/controlling_text_size_in_safari_for_ios_without_disabling_user_zoom/
+
+/**
+ * Remove the gray background color from active links in IE 10.
*/
-html {
- font-size: 100%;
- /* 1 */
- -webkit-text-size-adjust: 100%;
- /* 2 */
- -ms-text-size-adjust: 100%;
- /* 2 */
+
+a {
+ background-color: transparent;
}
-/*
- * Addresses font-family inconsistency between 'textarea' and other form elements.
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
*/
-html,
-button,
-input,
-select,
-textarea {
- font-family: sans-serif;
-}
-/*
- * Addresses margins handled incorrectly in IE6/7
- */
-body {
- margin: 0;
-}
-
-/* =============================================================================
- Links
- ========================================================================== */
-/*
- * Addresses outline displayed oddly in Chrome
- */
-a:focus {
- outline: thin dotted;
-}
-
-/*
- * Improves readability when focused and also mouse hovered in all browsers
- * people.opera.com/patrickl/experiments/keyboard/test
- */
-a:hover,
-a:active {
+a:active,
+a:hover {
outline: 0;
}
-/* =============================================================================
- Typography
+/* Text-level semantics
========================================================================== */
-/*
- * Addresses font sizes and margins set differently in IE6/7
- * Addresses font sizes within 'section' and 'article' in FF4+, Chrome, S5
+
+/**
+ * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
*/
-h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-h2 {
- font-size: 1.5em;
- margin: 0.83em 0;
-}
-
-h3 {
- font-size: 1.17em;
- margin: 1em 0;
-}
-
-h4 {
- font-size: 1em;
- margin: 1.33em 0;
-}
-
-h5 {
- font-size: 0.83em;
- margin: 1.67em 0;
-}
-
-h6 {
- font-size: 0.75em;
- margin: 2.33em 0;
-}
-
-/*
- * Addresses styling not present in IE7/8/9, S5, Chrome
- */
abbr[title] {
border-bottom: 1px dotted;
}
-/*
- * Addresses style set to 'bolder' in FF3+, S4/5, Chrome
-*/
+/**
+ * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
+ */
+
b,
strong {
font-weight: bold;
}
-blockquote {
- margin: 1em 40px;
-}
-
-/*
- * Addresses styling not present in S5, Chrome
+/**
+ * Address styling not present in Safari and Chrome.
*/
+
dfn {
font-style: italic;
}
-/*
- * Addresses styling not present in IE6/7/8/9
+/**
+ * Address variable `h1` font-size and margin within `section` and `article`
+ * contexts in Firefox 4+, Safari, and Chrome.
*/
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+/**
+ * Address styling not present in IE 8/9.
+ */
+
mark {
background: #ff0;
color: #000;
}
-/*
- * Addresses margins set differently in IE6/7
+/**
+ * Address inconsistent and variable font size in all browsers.
*/
-p,
-pre {
- margin: 1em 0;
-}
-
-/*
- * Corrects font family set oddly in IE6, S4/5, Chrome
- * en.wikipedia.org/wiki/User:Davidgothberg/Test59
- */
-pre,
-code,
-kbd,
-samp {
- font-family: monospace, serif;
- _font-family: 'courier new', monospace;
- font-size: 1em;
-}
-
-/*
- * 1. Addresses CSS quotes not supported in IE6/7
- * 2. Addresses quote property not supported in S4
- */
-/* 1 */
-q {
- quotes: none;
-}
-
-/* 2 */
-q:before,
-q:after {
- content: '';
- content: none;
-}
small {
- font-size: 75%;
+ font-size: 80%;
}
-/*
- * Prevents sub and sup affecting line-height in all browsers
- * gist.github.com/413930
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
+
sub,
sup {
font-size: 75%;
@@ -232,228 +174,251 @@ sub {
bottom: -0.25em;
}
-/* =============================================================================
- Lists
+/* Embedded content
========================================================================== */
-/*
- * Addresses margins set differently in IE6/7
- */
-dl,
-menu,
-ol,
-ul {
- margin: 1em 0;
-}
-dd {
- margin: 0 0 0 40px;
-}
-
-/*
- * Addresses paddings set differently in IE6/7
+/**
+ * Remove border when inside `a` element in IE 8/9/10.
*/
-menu,
-ol,
-ul {
- padding: 0 0 0 40px;
-}
-/*
- * Corrects list images handled incorrectly in IE7
- */
-nav ul,
-nav ol {
- list-style: none;
- list-style-image: none;
-}
-
-/* =============================================================================
- Embedded content
- ========================================================================== */
-/*
- * 1. Removes border when inside 'a' element in IE6/7/8/9, FF3
- * 2. Improves image quality when scaled in IE7
- * code.flickr.com/blog/2008/11/12/on-ui-quality-the-little-things-client-side-image-resizing/
- */
img {
border: 0;
- /* 1 */
- -ms-interpolation-mode: bicubic;
- /* 2 */
}
-/*
- * Corrects overflow displayed oddly in IE9
+/**
+ * Correct overflow not hidden in IE 9/10/11.
*/
+
svg:not(:root) {
overflow: hidden;
}
-/* =============================================================================
- Figures
+/* Grouping content
========================================================================== */
-/*
- * Addresses margin not present in IE6/7/8/9, S5, O11
+
+/**
+ * Address margin not present in IE 8/9 and Safari.
*/
+
figure {
- margin: 0;
+ margin: 1em 40px;
}
-/* =============================================================================
- Forms
+/**
+ * Address differences between Firefox and other browsers.
+ */
+
+hr {
+ box-sizing: content-box;
+ height: 0;
+}
+
+/**
+ * Contain overflow in all browsers.
+ */
+
+pre {
+ overflow: auto;
+}
+
+/**
+ * Address odd `em`-unit font size rendering in all browsers.
+ */
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/* Forms
========================================================================== */
-/*
- * Corrects margin displayed oddly in IE6/7
- */
-form {
- margin: 0;
-}
-/*
- * Define consistent border, margin, and padding
+/**
+ * Known limitation: by default, Chrome and Safari on OS X allow very limited
+ * styling of `select`, unless a `border` property is set.
*/
-fieldset {
- border: 1px solid #c0c0c0;
- margin: 0 2px;
- padding: 0.35em 0.625em 0.75em;
-}
-/*
- * 1. Corrects color not being inherited in IE6/7/8/9
- * 2. Corrects text not wrapping in FF3
- * 3. Corrects alignment displayed oddly in IE6/7
+/**
+ * 1. Correct color not being inherited.
+ * Known issue: affects color of disabled elements.
+ * 2. Correct font properties not being inherited.
+ * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
*/
-legend {
- border: 0;
- /* 1 */
- padding: 0;
- white-space: normal;
- /* 2 */
- *margin-left: -7px;
- /* 3 */
-}
-/*
- * 1. Corrects font size not being inherited in all browsers
- * 2. Addresses margins set differently in IE6/7, FF3+, S5, Chrome
- * 3. Improves appearance and consistency in all browsers
- */
button,
input,
+optgroup,
select,
textarea {
- font-size: 100%;
- /* 1 */
- margin: 0;
- /* 2 */
- vertical-align: baseline;
- /* 3 */
- *vertical-align: middle;
- /* 3 */
+ color: inherit; /* 1 */
+ font: inherit; /* 2 */
+ margin: 0; /* 3 */
}
-/*
- * Addresses FF3/4 setting line-height on 'input' using !important in the UA stylesheet
+/**
+ * Address `overflow` set to `hidden` in IE 8/9/10/11.
*/
-button,
-input {
- line-height: normal;
- /* 1 */
+
+button {
+ overflow: visible;
}
-/*
- * 1. Improves usability and consistency of cursor style between image-type 'input' and others
- * 2. Corrects inability to style clickable 'input' types in iOS
- * 3. Removes inner spacing in IE7 without affecting normal text inputs
- * Known issue: inner spacing remains in IE6
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
+ * Correct `select` style inheritance in Firefox.
*/
+
button,
-input[type="button"],
+select {
+ text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ * and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ * `input` and others.
+ */
+
+button,
+html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
- cursor: pointer;
- /* 1 */
- -webkit-appearance: button;
- /* 2 */
- *overflow: visible;
- /* 3 */
+ -webkit-appearance: button; /* 2 */
+ cursor: pointer; /* 3 */
}
-/*
- * Re-set default cursor for disabled elements
+/**
+ * Re-set default cursor for disabled elements.
*/
+
button[disabled],
-input[disabled] {
+html input[disabled] {
cursor: default;
}
-/*
- * 1. Addresses box sizing set to content-box in IE8/9
- * 2. Removes excess padding in IE8/9
- * 3. Removes excess padding in IE7
- Known issue: excess padding remains in IE6
+/**
+ * Remove inner padding and border in Firefox 4+.
*/
-input[type="checkbox"],
-input[type="radio"] {
- box-sizing: border-box;
- /* 1 */
- padding: 0;
- /* 2 */
- *height: 13px;
- /* 3 */
- *width: 13px;
- /* 3 */
-}
-/*
- * 1. Addresses appearance set to searchfield in S5, Chrome
- * 2. Addresses box-sizing set to border-box in S5, Chrome (include -moz to future-proof)
- */
-input[type="search"] {
- -webkit-appearance: textfield;
- /* 1 */
- -moz-box-sizing: content-box;
- -webkit-box-sizing: content-box;
- /* 2 */
- box-sizing: content-box;
-}
-
-/*
- * Removes inner padding and search cancel button in S5, Chrome on OS X
- */
-input[type="search"]::-webkit-search-decoration,
-input[type="search"]::-webkit-search-cancel-button {
- -webkit-appearance: none;
-}
-
-/*
- * Removes inner padding and border in FF3+
- * www.sitepen.com/blog/2008/05/14/the-devils-in-the-details-fixing-dojos-toolbar-buttons/
- */
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
-/*
- * 1. Removes default vertical scrollbar in IE6/7/8/9
- * 2. Improves readability and alignment in all browsers
+/**
+ * Address Firefox 4+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
*/
-textarea {
- overflow: auto;
- /* 1 */
- vertical-align: top;
- /* 2 */
+
+input {
+ line-height: normal;
}
-/* =============================================================================
- Tables
- ========================================================================== */
-/*
- * Remove most spacing between table cells
+/**
+ * It's recommended that you don't attempt to style these elements.
+ * Firefox's implementation doesn't respect box-sizing, padding, or width.
+ *
+ * 1. Address box sizing set to `content-box` in IE 8/9/10.
+ * 2. Remove excess padding in IE 8/9/10.
*/
+
+input[type="checkbox"],
+input[type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Fix the cursor style for Chrome's increment/decrement buttons. For certain
+ * `font-size` values of the `input`, it causes the cursor style of the
+ * decrement button to change from `default` to `text`.
+ */
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
+ * (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+ -webkit-appearance: textfield; /* 1 */ /* 2 */
+ box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari and Chrome on OS X.
+ * Safari (but not Chrome) clips the cancel button when the search input has
+ * padding (and `textfield` appearance).
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct `color` not being inherited in IE 8/9/10/11.
+ * 2. Remove padding so people aren't caught out if they zero out fieldsets.
+ */
+
+legend {
+ border: 0; /* 1 */
+ padding: 0; /* 2 */
+}
+
+/**
+ * Remove default vertical scrollbar in IE 8/9/10/11.
+ */
+
+textarea {
+ overflow: auto;
+}
+
+/**
+ * Don't inherit the `font-weight` (applied by a rule above).
+ * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
+ */
+
+optgroup {
+ font-weight: bold;
+}
+
+/* Tables
+ ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
table {
border-collapse: collapse;
border-spacing: 0;
}
+
+td,
+th {
+ padding: 0;
+}
diff --git a/stylesheets/stylesheet.css b/stylesheets/stylesheet.css
index b6175098..b5f20c23 100644
--- a/stylesheets/stylesheet.css
+++ b/stylesheets/stylesheet.css
@@ -1,479 +1,245 @@
-/* http://meyerweb.com/eric/tools/css/reset/
- v2.0 | 20110126
- License: none (public domain)
-*/
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
-}
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
- display: block;
-}
+* {
+ box-sizing: border-box; }
+
body {
- line-height: 1;
-}
-ol, ul {
- list-style: none;
-}
-blockquote, q {
- quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
- content: '';
- content: none;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-/* LAYOUT STYLES */
-body {
- font-size: 15px;
- line-height: 1.5;
- background: #fafafa url(../images/body-bg.jpg) 0 0 repeat;
- font-family: 'Helvetica Neue', Helvetica, Arial, serif;
- font-weight: 400;
- color: #666;
-}
-
-a {
- color: #2879d0;
-}
-a:hover {
- color: #2268b2;
-}
-
-header {
- padding-top: 40px;
- padding-bottom: 40px;
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
- background: #2e7bcf url(../images/header-bg.jpg) 0 0 repeat-x;
- border-bottom: solid 1px #275da1;
-}
-
-header h1 {
- letter-spacing: -1px;
- font-size: 72px;
- color: #fff;
- line-height: 1;
- margin-bottom: 0.2em;
- width: 540px;
-}
-
-header h2 {
- font-size: 26px;
- color: #9ddcff;
- font-weight: normal;
- line-height: 1.3;
- width: 540px;
- letter-spacing: 0;
-}
-
-.inner {
- position: relative;
- width: 940px;
- margin: 0 auto;
-}
-
-#content-wrapper {
- border-top: solid 1px #fff;
- padding-top: 30px;
-}
-
-#main-content {
- width: 690px;
- float: left;
-}
-
-#main-content img {
- max-width: 100%;
-}
-
-aside#sidebar {
- width: 200px;
- padding-left: 20px;
- min-height: 504px;
- float: right;
- background: transparent url(../images/sidebar-bg.jpg) 0 0 no-repeat;
- font-size: 12px;
- line-height: 1.3;
-}
-
-aside#sidebar p.repo-owner,
-aside#sidebar p.repo-owner a {
- font-weight: bold;
-}
-
-#downloads {
- margin-bottom: 40px;
-}
-
-a.button {
- width: 134px;
- height: 58px;
- line-height: 1.2;
- font-size: 23px;
- color: #fff;
- padding-left: 68px;
- padding-top: 22px;
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
-}
-a.button small {
- display: block;
- font-size: 11px;
-}
-header a.button {
- position: absolute;
- right: 0;
- top: 0;
- background: transparent url(../images/github-button.png) 0 0 no-repeat;
-}
-aside a.button {
- width: 138px;
- padding-left: 64px;
- display: block;
- background: transparent url(../images/download-button.png) 0 0 no-repeat;
- margin-bottom: 20px;
- font-size: 21px;
-}
-
-code, pre {
- font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace;
- color: #222;
- margin-bottom: 30px;
- font-size: 13px;
-}
-
-code {
- background-color: #f2f8fc;
- border: solid 1px #dbe7f3;
- padding: 0 3px;
-}
-
-pre {
- padding: 20px;
- background: #fff;
- text-shadow: none;
- overflow: auto;
- border: solid 1px #f2f2f2;
-}
-pre code {
- color: #2879d0;
- background-color: #fff;
- border: none;
padding: 0;
-}
+ margin: 0;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 16px;
+ line-height: 1.5;
+ color: #606c71; }
-ul, ol, dl {
- margin-bottom: 20px;
-}
-
-
-/* COMMON STYLES */
-
-hr {
- height: 1px;
- line-height: 1px;
- margin-top: 1em;
- padding-bottom: 1em;
- border: none;
- background: transparent url('../images/hr.png') 0 0 no-repeat;
-}
-
-table {
- width: 100%;
- border: 1px solid #ebebeb;
-}
-
-th {
- font-weight: 500;
-}
-
-td {
- border: 1px solid #ebebeb;
- text-align: center;
- font-weight: 300;
-}
-
-form {
- background: #f2f2f2;
- padding: 20px;
-
-}
-
-
-/* GENERAL ELEMENT TYPE STYLES */
-
-#main-content h1 {
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
- font-size: 2.8em;
- letter-spacing: -1px;
- color: #474747;
-}
-
-#main-content h1:before {
- content: "/";
- color: #9ddcff;
- padding-right: 0.3em;
- margin-left: -0.9em;
-}
-
-#main-content h2 {
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
- font-size: 22px;
- font-weight: bold;
- margin-bottom: 8px;
- color: #474747;
-}
-#main-content h2:before {
- content: "//";
- color: #9ddcff;
- padding-right: 0.3em;
- margin-left: -1.5em;
-}
-
-#main-content h3 {
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
- font-size: 18px;
- font-weight: bold;
- margin-top: 24px;
- margin-bottom: 8px;
- color: #474747;
-}
-
-#main-content h3:before {
- content: "///";
- color: #9ddcff;
- padding-right: 0.3em;
- margin-left: -2em;
-}
-
-#main-content h4 {
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
- font-size: 15px;
- font-weight: bold;
- color: #474747;
-}
-
-h4:before {
- content: "////";
- color: #9ddcff;
- padding-right: 0.3em;
- margin-left: -2.8em;
-}
-
-#main-content h5 {
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
- font-size: 14px;
- color: #474747;
-}
-h5:before {
- content: "/////";
- color: #9ddcff;
- padding-right: 0.3em;
- margin-left: -3.2em;
-}
-
-#main-content h6 {
- font-family: 'Architects Daughter', 'Helvetica Neue', Helvetica, Arial, serif;
- font-size: .8em;
- color: #474747;
-}
-h6:before {
- content: "//////";
- color: #9ddcff;
- padding-right: 0.3em;
- margin-left: -3.7em;
-}
-
-p {
- margin-bottom: 20px;
-}
-
a {
+ color: #1e6bb8;
+ text-decoration: none; }
+ a:hover {
+ text-decoration: underline; }
+
+.btn {
+ display: inline-block;
+ margin-bottom: 1rem;
+ color: rgba(255, 255, 255, 0.7);
+ background-color: rgba(255, 255, 255, 0.08);
+ border-color: rgba(255, 255, 255, 0.2);
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0.3rem;
+ transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
+ .btn + .btn {
+ margin-left: 1rem; }
+
+.btn:hover {
+ color: rgba(255, 255, 255, 0.8);
text-decoration: none;
-}
+ background-color: rgba(255, 255, 255, 0.2);
+ border-color: rgba(255, 255, 255, 0.3); }
-p a {
- font-weight: 400;
-}
+@media screen and (min-width: 64em) {
+ .btn {
+ padding: 0.75rem 1rem; } }
-blockquote {
- font-size: 1.6em;
- border-left: 10px solid #e9e9e9;
- margin-bottom: 20px;
- padding: 0 0 0 30px;
-}
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .btn {
+ padding: 0.6rem 0.9rem;
+ font-size: 0.9rem; } }
-ul {
- list-style: disc inside;
- padding-left: 20px;
-}
-
-ol {
- list-style: decimal inside;
- padding-left: 3px;
-}
-
-dl dd {
- font-style: italic;
- font-weight: 100;
-}
-
-footer {
- background: transparent url('../images/hr.png') 0 0 no-repeat;
- margin-top: 40px;
- padding-top: 20px;
- padding-bottom: 30px;
- font-size: 13px;
- color: #aaa;
-}
-
-footer a {
- color: #666;
-}
-footer a:hover {
- color: #444;
-}
-
-/* MISC */
-.clearfix:after {
- clear: both;
- content: '.';
- display: block;
- visibility: hidden;
- height: 0;
-}
-
-.clearfix {display: inline-block;}
-* html .clearfix {height: 1%;}
-.clearfix {display: block;}
-
-/* #Media Queries
-================================================== */
-
-/* Smaller than standard 960 (devices and browsers) */
-@media only screen and (max-width: 959px) {}
-
-/* Tablet Portrait size to standard 960 (devices and browsers) */
-@media only screen and (min-width: 768px) and (max-width: 959px) {
- .inner {
- width: 740px;
- }
- header h1, header h2 {
- width: 340px;
- }
- header h1 {
- font-size: 60px;
- }
- header h2 {
- font-size: 30px;
- }
- #main-content {
- width: 490px;
- }
- #main-content h1:before,
- #main-content h2:before,
- #main-content h3:before,
- #main-content h4:before,
- #main-content h5:before,
- #main-content h6:before {
- content: none;
- padding-right: 0;
- margin-left: 0;
- }
-}
-
-/* All Mobile Sizes (devices and browser) */
-@media only screen and (max-width: 767px) {
- .inner {
- width: 93%;
- }
- header {
- padding: 20px 0;
- }
- header .inner {
- position: relative;
- }
- header h1, header h2 {
+@media screen and (max-width: 42em) {
+ .btn {
+ display: block;
width: 100%;
- }
- header h1 {
- font-size: 48px;
- }
- header h2 {
- font-size: 24px;
- }
- header a.button {
- background-image: none;
- width: auto;
- height: auto;
- display: inline-block;
- margin-top: 15px;
- padding: 5px 10px;
- position: relative;
- text-align: center;
- font-size: 13px;
- line-height: 1;
- background-color: #9ddcff;
- color: #2879d0;
- -moz-border-radius: 5px;
- -webkit-border-radius: 5px;
- border-radius: 5px;
- }
- header a.button small {
- font-size: 13px;
- display: inline;
- }
- #main-content,
- aside#sidebar {
- float: none;
- width: 100% ! important;
- }
- aside#sidebar {
- background-image: none;
- margin-top: 20px;
- border-top: solid 1px #ddd;
- padding: 20px 0;
- min-height: 0;
- }
- aside#sidebar a.button {
- display: none;
- }
- #main-content h1:before,
- #main-content h2:before,
- #main-content h3:before,
- #main-content h4:before,
- #main-content h5:before,
- #main-content h6:before {
- content: none;
- padding-right: 0;
- margin-left: 0;
- }
-}
+ padding: 0.75rem;
+ font-size: 0.9rem; }
+ .btn + .btn {
+ margin-top: 1rem;
+ margin-left: 0; } }
-/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
-@media only screen and (min-width: 480px) and (max-width: 767px) {}
+.page-header {
+ color: #fff;
+ text-align: center;
+ background-color: #159957;
+ background-image: linear-gradient(120deg, #155799, #159957); }
-/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
-@media only screen and (max-width: 479px) {}
+@media screen and (min-width: 64em) {
+ .page-header {
+ padding: 5rem 6rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .page-header {
+ padding: 3rem 4rem; } }
+
+@media screen and (max-width: 42em) {
+ .page-header {
+ padding: 2rem 1rem; } }
+
+.project-name {
+ margin-top: 0;
+ margin-bottom: 0.1rem; }
+
+@media screen and (min-width: 64em) {
+ .project-name {
+ font-size: 3.25rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-name {
+ font-size: 2.25rem; } }
+
+@media screen and (max-width: 42em) {
+ .project-name {
+ font-size: 1.75rem; } }
+
+.project-tagline {
+ margin-bottom: 2rem;
+ font-weight: normal;
+ opacity: 0.7; }
+
+@media screen and (min-width: 64em) {
+ .project-tagline {
+ font-size: 1.25rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .project-tagline {
+ font-size: 1.15rem; } }
+
+@media screen and (max-width: 42em) {
+ .project-tagline {
+ font-size: 1rem; } }
+
+.main-content :first-child {
+ margin-top: 0; }
+.main-content img {
+ max-width: 100%; }
+.main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6 {
+ margin-top: 2rem;
+ margin-bottom: 1rem;
+ font-weight: normal;
+ color: #159957; }
+.main-content p {
+ margin-bottom: 1em; }
+.main-content code {
+ padding: 2px 4px;
+ font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ font-size: 0.9rem;
+ color: #383e41;
+ background-color: #f3f6fa;
+ border-radius: 0.3rem; }
+.main-content pre {
+ padding: 0.8rem;
+ margin-top: 0;
+ margin-bottom: 1rem;
+ font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;
+ color: #567482;
+ word-wrap: normal;
+ background-color: #f3f6fa;
+ border: solid 1px #dce6f0;
+ border-radius: 0.3rem; }
+ .main-content pre > code {
+ padding: 0;
+ margin: 0;
+ font-size: 0.9rem;
+ color: #567482;
+ word-break: normal;
+ white-space: pre;
+ background: transparent;
+ border: 0; }
+.main-content .highlight {
+ margin-bottom: 1rem; }
+ .main-content .highlight pre {
+ margin-bottom: 0;
+ word-break: normal; }
+.main-content .highlight pre, .main-content pre {
+ padding: 0.8rem;
+ overflow: auto;
+ font-size: 0.9rem;
+ line-height: 1.45;
+ border-radius: 0.3rem; }
+.main-content pre code, .main-content pre tt {
+ display: inline;
+ max-width: initial;
+ padding: 0;
+ margin: 0;
+ overflow: initial;
+ line-height: inherit;
+ word-wrap: normal;
+ background-color: transparent;
+ border: 0; }
+ .main-content pre code:before, .main-content pre code:after, .main-content pre tt:before, .main-content pre tt:after {
+ content: normal; }
+.main-content ul, .main-content ol {
+ margin-top: 0; }
+.main-content blockquote {
+ padding: 0 1rem;
+ margin-left: 0;
+ color: #819198;
+ border-left: 0.3rem solid #dce6f0; }
+ .main-content blockquote > :first-child {
+ margin-top: 0; }
+ .main-content blockquote > :last-child {
+ margin-bottom: 0; }
+.main-content table {
+ display: block;
+ width: 100%;
+ overflow: auto;
+ word-break: normal;
+ word-break: keep-all; }
+ .main-content table th {
+ font-weight: bold; }
+ .main-content table th, .main-content table td {
+ padding: 0.5rem 1rem;
+ border: 1px solid #e9ebec; }
+.main-content dl {
+ padding: 0; }
+ .main-content dl dt {
+ padding: 0;
+ margin-top: 1rem;
+ font-size: 1rem;
+ font-weight: bold; }
+ .main-content dl dd {
+ padding: 0;
+ margin-bottom: 1rem; }
+.main-content hr {
+ height: 2px;
+ padding: 0;
+ margin: 1rem 0;
+ background-color: #eff0f1;
+ border: 0; }
+
+@media screen and (min-width: 64em) {
+ .main-content {
+ max-width: 64rem;
+ padding: 2rem 6rem;
+ margin: 0 auto;
+ font-size: 1.1rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .main-content {
+ padding: 2rem 4rem;
+ font-size: 1.1rem; } }
+
+@media screen and (max-width: 42em) {
+ .main-content {
+ padding: 2rem 1rem;
+ font-size: 1rem; } }
+
+.site-footer {
+ padding-top: 2rem;
+ margin-top: 2rem;
+ border-top: solid 1px #eff0f1; }
+
+.site-footer-owner {
+ display: block;
+ font-weight: bold; }
+
+.site-footer-credits {
+ color: #819198; }
+
+@media screen and (min-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
+
+@media screen and (min-width: 42em) and (max-width: 64em) {
+ .site-footer {
+ font-size: 1rem; } }
+
+@media screen and (max-width: 42em) {
+ .site-footer {
+ font-size: 0.9rem; } }
Per-message Compression
-