From 1dba9efee155ad88faec433cd9f51836922b686a Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 30 Jun 2017 22:00:29 -0400 Subject: [PATCH] point back to dwrensha.github.io --- README.md | 2 +- website/README.md | 9 + website/_config.yml | 4 + website/_includes/footer.html | 9 + website/_includes/header.html | 34 ++ website/_layouts/page.html | 3 + website/_layouts/post.html | 15 + website/_posts/2014-10-13-alpha-release.md | 85 +++++ website/assets/carsales.png | Bin 0 -> 12270 bytes website/assets/catrank.png | Bin 0 -> 12541 bytes website/assets/eval.png | Bin 0 -> 12697 bytes website/images/bg_hr.png | Bin 0 -> 943 bytes website/images/blacktocat.png | Bin 0 -> 1428 bytes website/images/icon_download.png | Bin 0 -> 1162 bytes website/images/sprite_download.png | Bin 0 -> 16799 bytes website/index.md | 295 +++++++++++++++ website/news.html | 19 + website/stylesheets/normalize.css | 406 +++++++++++++++++++++ website/stylesheets/pygment_trac.css | 70 ++++ website/stylesheets/stylesheet.css | 371 +++++++++++++++++++ 20 files changed, 1321 insertions(+), 1 deletion(-) create mode 100644 website/README.md create mode 100644 website/_config.yml create mode 100644 website/_includes/footer.html create mode 100644 website/_includes/header.html create mode 100644 website/_layouts/page.html create mode 100644 website/_layouts/post.html create mode 100644 website/_posts/2014-10-13-alpha-release.md create mode 100644 website/assets/carsales.png create mode 100644 website/assets/catrank.png create mode 100644 website/assets/eval.png create mode 100644 website/images/bg_hr.png create mode 100644 website/images/blacktocat.png create mode 100644 website/images/icon_download.png create mode 100644 website/images/sprite_download.png create mode 100644 website/index.md create mode 100644 website/news.html create mode 100644 website/stylesheets/normalize.css create mode 100644 website/stylesheets/pygment_trac.css create mode 100644 website/stylesheets/stylesheet.css diff --git a/README.md b/README.md index 3fa1c57..ed78753 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,4 @@ and capabilities, and capnproto-java is a work-in-progress pure Java implementation. -[Read more here.](https://capnproto.github.io/capnproto-java/index.html) +[Read more here.](https://dwrensha.github.io/capnproto-java/index.html) diff --git a/website/README.md b/website/README.md new file mode 100644 index 0000000..721e9c0 --- /dev/null +++ b/website/README.md @@ -0,0 +1,9 @@ +Slate +===== +Slate is responsive theme for GitHub Pages. [Fork it](https://github.com/jsncostello/slate/fork_select) and use it on your own site or generate one automatically using [GitHub Pages](http://pages.github.com). + +Slate in use: +![Slate](https://f.cloud.github.com/assets/416727/1730110/c72a2f96-62d3-11e3-9d6f-efc53e24aeb2.png) + + +Slate is available under ther Creative Commons Attribution 3.0 License. Basically, use it, modify it, and remix it. Attribution is not necessary but it is appreciated. \ No newline at end of file diff --git a/website/_config.yml b/website/_config.yml new file mode 100644 index 0000000..a8349bc --- /dev/null +++ b/website/_config.yml @@ -0,0 +1,4 @@ +name: Cap'n Proto for Java +markdown: rdiscount +baseurl: /capnproto-java +url: http://dwrensha.github.io/capnproto-java diff --git a/website/_includes/footer.html b/website/_includes/footer.html new file mode 100644 index 0000000..dd42255 --- /dev/null +++ b/website/_includes/footer.html @@ -0,0 +1,9 @@ + + + + + diff --git a/website/_includes/header.html b/website/_includes/header.html new file mode 100644 index 0000000..b721e49 --- /dev/null +++ b/website/_includes/header.html @@ -0,0 +1,34 @@ + + + + + + + + + + + {{page.title}} + + + + + +
+
+ View on GitHub + +

Cap'n Proto for Java

+

extremely efficient serialization in pure Java

+ + +
+
+ + +
+
diff --git a/website/_layouts/page.html b/website/_layouts/page.html new file mode 100644 index 0000000..4f0db4c --- /dev/null +++ b/website/_layouts/page.html @@ -0,0 +1,3 @@ +{% include header.html %} +{{ content }} +{% include footer.html %} diff --git a/website/_layouts/post.html b/website/_layouts/post.html new file mode 100644 index 0000000..9d97589 --- /dev/null +++ b/website/_layouts/post.html @@ -0,0 +1,15 @@ +{% include header.html %} +

+{{page.title}} +

+

+{{ page.date | date_to_string }} +

+ + +{{content}} + +

+ -- posted by {{ page.author }} +

+{% include footer.html %} diff --git a/website/_posts/2014-10-13-alpha-release.md b/website/_posts/2014-10-13-alpha-release.md new file mode 100644 index 0000000..b192601 --- /dev/null +++ b/website/_posts/2014-10-13-alpha-release.md @@ -0,0 +1,85 @@ +--- +layout: post +title: capnproto-java alpha release with benchmarks +author: dwrensha +--- + +I'm happy to announce that +[capnproto-java](https://github.com/dwrensha/capnproto-java) is now a +mostly complete implementation of +the [Cap'n Proto](http://capnproto.org) serialization protocol. +It supports all of the data features of the Cap'n Proto schema language, +including constants, default values, and arbitrarily nested list types. +Moreover, the runtime and the generated code consist entirely +of platform-independent, safe Java code. + +In the spirit of previous announcements about the +[Rust](http://dwrensha.github.io/capnproto-rust/2014/01/15/benchmark-update.html) +and +[OCaml](http://pelzlpj.github.io/capnp-ocaml/2014/09/02/capnp-ocaml-2.0/) +implementations, +I've made some informal measurements +with the [usual](https://github.com/kentonv/capnproto/tree/master/c%2B%2B/src/benchmark) +toy benchmark suite. +The results show +the Java implementation performing +at worst +3x slower than the C++ and Rust implementations, +and at best about 2x slower. +I find these results promising, +considering how difficult it can be to avoid +heap allocations and redundant bounds-checking +on the JVM. + +I ran each of the three benchmark cases +in five modes. In the "object" mode, +the data is passed in-process without any copying. +In the "bytes" mode, the data +is written to a flat array and then re-read in-process. +In the "pipe" mode, the data is passed +as a byte stream between separate processes. +In the "packed" sub-modes, +a [compression scheme](https://capnproto.org/encoding.html#packing) +is applied to the bytes before they are passed. + +To give the JVM a chance to amortize +the cost of just-in-time compilation, +I ran the benchmarks for +10x more iterations than +in the previous Rust vs. C++ benchmarks. + +Here are the results. + + + +The CarSales case does a lot of +iteration through lists of structs. +One way to improve Java's performance here +might be to implement list iterators +that update in-place, so that we don't +need to allocate a new `StructReader` for each +member of a list. + + + +The CatRank case emphasizes string processing. +One big difficulty faced by Java here is that +it uses UTF-16 encoding, while +Cap'n Proto uses UTF-8; +translating between the two requires +significant copying of memory. + + + +The Eval case seems to confirm that packing +costs proportionally more for Java +than for the other implementations. +There are almost certainly still +some optimizations we could apply to that +part of the Java implementation, +but we may be fundamentally limited +by the fact that Java bounds-checks +every array access. \ No newline at end of file diff --git a/website/assets/carsales.png b/website/assets/carsales.png new file mode 100644 index 0000000000000000000000000000000000000000..cf4e59c6ce9461f75243ee027ca96761d78f84cc GIT binary patch literal 12270 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 literal 0 HcmV?d00001 diff --git a/website/assets/catrank.png b/website/assets/catrank.png new file mode 100644 index 0000000000000000000000000000000000000000..de11871069440ca4eb5885424a7d5c9adc6ffbcf GIT binary patch literal 12541 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 P3kY6b757%o`0@V&?X2|q literal 0 HcmV?d00001 diff --git a/website/assets/eval.png b/website/assets/eval.png new file mode 100644 index 0000000000000000000000000000000000000000..ff69c7cd29c410be78aaab229086866fe68a118b GIT binary patch literal 12697 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 VVmK#1{M!lyr>voruW07?zX0s9Obq}4 literal 0 HcmV?d00001 diff --git a/website/images/bg_hr.png b/website/images/bg_hr.png new file mode 100644 index 0000000000000000000000000000000000000000..7973bd69888c7e10ccad1111d555ceabb7cd99b6 GIT binary patch literal 943 zcmaJ=O^ee&7!FiK7FWCot{@Ck@nrMW&tx0B-6VAbrk1u~FTzffX&bu9#AIsIdef8t z!QZfdz=K}>3m(LO;6X3qN}Y6@>cJYA%)G<%Jn!ec>9im1@7>wsIBwrMF}iHO!q%;8 zSJ@xEd~(FL18NRvkBsOXMVM>4WQc*~qcQGc17IjxRnj!O_^B1gan0x#EWT48PK->5B2>mI;LIx zC*FSw$Nfc!g)WZCEOJ=mM)}lLsOk|$ltg_(&ax_YCWMlBLPDVT%D_gB7o_$YZ`-OB z#1sV%whRq21>W;qwN$N?OUGtQQe;JvOsQrna;+v+j8dth=*?orHHb6waX>S!yXCgT zo!oR3{E&GzaOAzfZYv@_Sf{LdyJInS>TS60&R9%yCs$y>2x(*gYIJtRrYAja$Ceq} z!N&oc_K1!3-Ft`U>`CM;quEbB4KG%!MovB*9_3!QzFhqHwrbwK|Doo-y>auDJNSP6 T=d)j*_4El@X4^PFK7I8YBT*xD literal 0 HcmV?d00001 diff --git a/website/images/blacktocat.png b/website/images/blacktocat.png new file mode 100644 index 0000000000000000000000000000000000000000..6e264fe57a2e35a2855405ac7d4102c3f6ddcdae GIT binary patch literal 1428 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 literal 0 HcmV?d00001 diff --git a/website/index.md b/website/index.md new file mode 100644 index 0000000..ab42067 --- /dev/null +++ b/website/index.md @@ -0,0 +1,295 @@ +--- +layout: page +title: Cap'n Proto for Java +--- + +## Introduction + +This is a Java implementation of [Cap'n Proto](http://capnproto.org). +It has two main components: + +1. A C++ program `capnpc-java` that +generates Java source code from Cap'n Proto [schemas](https://capnproto.org/language.html) +by acting as a +[plugin](https://capnproto.org/otherlang.html#how-to-write-compiler-plugins) +to the Cap'n Proto schema compiler. + +2. A Java package `org.capnproto` that provides runtime support for `capnpc-java`'s generated code. + +These components let you make your data **mobile**, +so that you can manipulate your data in Java +and also easily communicate it +to distributed components written +in other programming languages. +Under the hood, all operations are +backed by `java.nio.ByteBuffer`. +If you, for example, want to communicate over a +network, you can just directly write the bytes to the wire. +There is no encode or decode step! + +We hope eventually to provide support in Java for a +[distributed object-capability layer](https://capnproto.org/rpc.html) +built on top of this serialization layer, +but we have not embarked on that project yet. + + +## Installation + +### Schema Compiler and Plugin + +You will need to [install](http://capnproto.org/install.html) the +latest release of the Cap'n Proto schema compiler. +Then, running `make` should build `capnpc-java`. + +On Windows, you can instead +grab a prebuilt win32 executable from here: + +
https://dwrensha.ws/capnproto/capnpc-java.exe.zip
+ + +For help on how to invoke the schema compiler: + +``` +capnp compile --help +``` + +Note that you'll need to include `java.capnp` so that you can use the `package` and `outerClassname` +annotations. This schema is located in `compiler/src/main/schema`. + +You might find useful [this Maven Plugin](https://github.com/expretio/capnp-maven-plugin). + +### Runtime + +The runtime is available on +[The Central Repository](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22org.capnproto%22). + +We use [sbt](http://scala-sbt.org) for building and testing the Java code. +Running `sbt compile` at the top-level directory should build +`org.capnproto` and `org.capnproto.examples`. +Running `sbt test` should run the test suite. + +## Example + +We can define types in a schema like this: + +``` +@0x9eb32e19f86ee174; +using Java = import "/capnp/java.capnp"; +$Java.package("org.capnproto.examples"); +$Java.outerClassname("Addressbook"); + +struct Person { + id @0 :UInt32; + name @1 :Text; + email @2 :Text; + phones @3 :List(PhoneNumber); + + struct PhoneNumber { + number @0 :Text; + type @1 :Type; + + enum Type { + mobile @0; + home @1; + work @2; + } + } + + employment :union { + unemployed @4 :Void; + employer @5 :Text; + school @6 :Text; + selfEmployed @7 :Void; + # We assume that a person is only one of these. + } +} + +struct AddressBook { + people @0 :List(Person); +} +``` + +Then, after running the schema compiler, +we can then use those types from Java like this: +{% highlight java %} +package org.capnproto.examples; + +import org.capnproto.StructList; +import org.capnproto.examples.Addressbook.AddressBook; +import org.capnproto.examples.Addressbook.Person; + +public class AddressbookMain { + + public static void writeAddressBook() throws java.io.IOException { + org.capnproto.MessageBuilder message = + new org.capnproto.MessageBuilder(); + + AddressBook.Builder addressbook = + message.initRoot(AddressBook.factory); + + StructList.Builder people = + addressbook.initPeople(2); + + Person.Builder alice = people.get(0); + alice.setId(123); + alice.setName("Alice"); + alice.setEmail("alice@example.com"); + + StructList.Builder alicePhones = + alice.initPhones(1); + alicePhones.get(0).setNumber("555-1212"); + alicePhones.get(0).setType(Person.PhoneNumber.Type.MOBILE); + alice.getEmployment().setSchool("MIT"); + + Person.Builder bob = people.get(1); + bob.setId(456); + bob.setName("Bob"); + bob.setEmail("bob@example.com"); + StructList.Builder bobPhones = + bob.initPhones(2); + bobPhones.get(0).setNumber("555-4567"); + bobPhones.get(0).setType(Person.PhoneNumber.Type.HOME); + bobPhones.get(1).setNumber("555-7654"); + bobPhones.get(1).setType(Person.PhoneNumber.Type.WORK); + bob.getEmployment().setUnemployed(org.capnproto.Void.VOID); + + org.capnproto.SerializePacked.writeToUnbuffered( + (new java.io.FileOutputStream( + java.io.FileDescriptor.out)).getChannel(), + message); + } + + public static void printAddressBook() throws java.io.IOException { + org.capnproto.MessageReader message = + org.capnproto.SerializePacked.readFromUnbuffered( + (new java.io.FileInputStream( + java.io.FileDescriptor.in)).getChannel()); + + AddressBook.Reader addressbook = + message.getRoot(AddressBook.factory); + + for(Person.Reader person : addressbook.getPeople()) { + System.out.println(person.getName() + ": " + person.getEmail()); + + for (Person.PhoneNumber.Reader phone : person.getPhones()) { + String typeName = "UNKNOWN"; + switch (phone.getType()) { + case MOBILE: + typeName = "mobile"; break; + case HOME: + typeName = "home"; break; + case WORK: + typeName = "work"; break; + } + System.out.println(" " + typeName + " phone: " + + phone.getNumber()); + } + + Person.Employment.Reader employment = person.getEmployment(); + switch (employment.which()) { + case UNEMPLOYED: + System.out.println(" unemployed"); + break; + case EMPLOYER: + System.out.println(" employer: " + employment.getEmployer()); + break; + case SCHOOL: + System.out.println(" student at: " + employment.getSchool()); + break; + case SELF_EMPLOYED: + System.out.println(" self-employed"); + break; + default : + break; + } + } + } + + public static void usage() { + System.out.println("usage: addressbook [write | read]"); + } + + public static void main(String[] args) { + try { + if (args.length < 1) { + usage(); + } else if (args[0].equals("write")) { + writeAddressBook(); + } else if (args[0].equals("read")) { + printAddressBook(); + } else { + usage(); + } + } catch (java.io.IOException e) { + System.out.println("io exception: " + e); + } + } +} +{% endhighlight %} + + +To read a message: + +``` +$ echo '(people = [(id = 123, name = "Alice",' \ +'email = "alice@example.com", employment = (school = "MIT"))])' \ +| capnp encode --packed examples/src/main/schema/addressbook.capnp \ +AddressBook \ +| java -cp runtime/target/classes:examples/target/classes \ +org.capnproto.examples.AddressbookMain read +``` + +To write a message: + +``` +$ java -cp runtime/target/classes:examples/target/classes \ +org.capnproto.examples.AddressbookMain write \ +| capnp decode --packed examples/src/main/schema/addressbook.capnp \ +AddressBook +``` + +## API + +The classes and methods provided by the +Java runtime and generated code +correspond directly to those +provided by the +[C++ implementation](https://capnproto.org/cxx.html), +with just a few adjustments. + +- Java does not have unsigned integer types, so a `UInt64` +in a schema gets mapped to a `long` in Java, a `UInt32` gets +mapped to an `int` in Java, and so on. +You are responsible for correctly handling +arithmetic on values of these types. Note that Java 8 has +standard functions that can help with this. + +- Because Java generics don't get monomorphized at compile time +like C++ templates do, generic methods +need to have an additional *factory* argument to +allow the proper dispatch to occur. +`MessageReader.getRoot()` and `MessageBuilder.initRoot()` are two examples, +as shown above. + +## Tips + +- The main I/O methods in +`Serialize` and `SerializePacked` are written in terms +of `WritableByteChannel` and `ReadableByteChannel`. +You should be very careful if you try to convert a +`java.io.OutputStream` +to a `WritableByteChannel` with the +`java.nio.channels.Channels.newChannel()` method. +If your `OutputStream` was buffered, the new channel-based +wrapper of it will have no way to flush it! +Note that the stream returned by `Process.getOutputStream()` is buffered. + +## Future Work + +There's a lot left to do, and we'd love to have your help! Here are some missing pieces: + +- [Orphans](https://capnproto.org/cxx.html#orphans). +- [Dynamic reflection](https://capnproto.org/cxx.html#dynamic-reflection). +- Optimizations, e.g. iterators for `StructList` that update in place instead of allocating for each element. +- Improvements for build and packaging, e.g. getting a distribution on Maven. +- The entire [object-capability RPC layer](https://capnproto.org/rpc.html). diff --git a/website/news.html b/website/news.html new file mode 100644 index 0000000..831cd14 --- /dev/null +++ b/website/news.html @@ -0,0 +1,19 @@ +--- +title: News +--- + +{% include header.html %} + +

News

+ +{% for post in site.posts %} +

{{ post.title }}

+

+ {{ post.author }} + on {{ post.date | date_to_string }} +

+{{ post.content }} +{% endfor %} + + +{% include footer.html %} diff --git a/website/stylesheets/normalize.css b/website/stylesheets/normalize.css new file mode 100644 index 0000000..c2de8df --- /dev/null +++ b/website/stylesheets/normalize.css @@ -0,0 +1,406 @@ +/*! normalize.css v2.1.3 | MIT License | git.io/normalize */ + +/* ========================================================================== + HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined in IE 8/9. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section, +summary { + display: block; +} + +/** + * Correct `inline-block` display not defined in IE 8/9. + */ + +audio, +canvas, +video { + display: inline-block; +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9. + * Hide the `template` element in IE, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* ========================================================================== + Base + ========================================================================== */ + +/** + * 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; +} + +/* ========================================================================== + Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background: transparent; +} + +/** + * Address `outline` inconsistency between Chrome and other browsers. + */ + +a:focus { + outline: thin dotted; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* ========================================================================== + Typography + ========================================================================== */ + +/** + * Address variable `h1` font-size and margin within `section` and `article` + * contexts in Firefox 4+, Safari 5, and Chrome. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/** + * Address styling not present in IE 8/9, Safari 5, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari 5 and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Correct font family set oddly in Safari 5 and Chrome. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, serif; + font-size: 1em; +} + +/** + * Improve readability of pre-formatted text in all browsers. + */ + +pre { + white-space: pre-wrap; +} + +/** + * Set consistent quote types. + */ + +q { + quotes: "\201C" "\201D" "\2018" "\2019"; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* ========================================================================== + Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9. + */ + +img { + border: 0; +} + +/** + * Correct overflow displayed oddly in IE 9. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* ========================================================================== + Figures + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari 5. + */ + +figure { + margin: 0; +} + +/* ========================================================================== + Forms + ========================================================================== */ + +/** + * 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. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * 1. Correct font family not being inherited in all browsers. + * 2. Correct font size not being inherited in all browsers. + * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. + */ + +button, +input, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +button, +input { + line-height: normal; +} + +/** + * 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 Chrome, Safari 5+, and IE 8+. + * Correct `select` style inheritance in Firefox 4+ and Opera. + */ + +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"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * 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 */ +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari 5 and 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; +} + +/** + * Remove inner padding and search cancel button in Safari 5 and Chrome + * on OS X. + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * 1. Remove default vertical scrollbar in IE 8/9. + * 2. Improve readability and alignment in all browsers. + */ + +textarea { + overflow: auto; /* 1 */ + vertical-align: top; /* 2 */ +} + +/* ========================================================================== + Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/website/stylesheets/pygment_trac.css b/website/stylesheets/pygment_trac.css new file mode 100644 index 0000000..e65cedf --- /dev/null +++ b/website/stylesheets/pygment_trac.css @@ -0,0 +1,70 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f0f3f3; } +.highlight .c { color: #0099FF; font-style: italic } /* Comment */ +.highlight .err { color: #AA0000; background-color: #FFAAAA } /* Error */ +.highlight .k { color: #006699; font-weight: bold } /* Keyword */ +.highlight .o { color: #555555 } /* Operator */ +.highlight .cm { color: #0099FF; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #009999 } /* Comment.Preproc */ +.highlight .c1 { color: #0099FF; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #0099FF; font-weight: bold; font-style: italic } /* Comment.Special */ +.highlight .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #003300; font-weight: bold } /* Generic.Heading */ +.highlight .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ +.highlight .go { color: #AAAAAA } /* Generic.Output */ +.highlight .gp { color: #000099; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #003300; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #99CC66 } /* Generic.Traceback */ +.highlight .kc { color: #006699; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #006699; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #006699; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #006699 } /* Keyword.Pseudo */ +.highlight .kr { color: #006699; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #007788; font-weight: bold } /* Keyword.Type */ +.highlight .m { color: #FF6600 } /* Literal.Number */ +.highlight .s { color: #CC3300 } /* Literal.String */ +.highlight .na { color: #330099 } /* Name.Attribute */ +.highlight .nb { color: #336666 } /* Name.Builtin */ +.highlight .nc { color: #00AA88; font-weight: bold } /* Name.Class */ +.highlight .no { color: #336600 } /* Name.Constant */ +.highlight .nd { color: #9999FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #CC0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #CC00FF } /* Name.Function */ +.highlight .nl { color: #9999FF } /* Name.Label */ +.highlight .nn { color: #00CCFF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #330099; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #003333 } /* Name.Variable */ +.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #FF6600 } /* Literal.Number.Float */ +.highlight .mh { color: #FF6600 } /* Literal.Number.Hex */ +.highlight .mi { color: #FF6600 } /* Literal.Number.Integer */ +.highlight .mo { color: #FF6600 } /* Literal.Number.Oct */ +.highlight .sb { color: #CC3300 } /* Literal.String.Backtick */ +.highlight .sc { color: #CC3300 } /* Literal.String.Char */ +.highlight .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #CC3300 } /* Literal.String.Double */ +.highlight .se { color: #CC3300; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #CC3300 } /* Literal.String.Heredoc */ +.highlight .si { color: #AA0000 } /* Literal.String.Interpol */ +.highlight .sx { color: #CC3300 } /* Literal.String.Other */ +.highlight .sr { color: #33AAAA } /* Literal.String.Regex */ +.highlight .s1 { color: #CC3300 } /* Literal.String.Single */ +.highlight .ss { color: #FFCC33 } /* Literal.String.Symbol */ +.highlight .bp { color: #336666 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #003333 } /* Name.Variable.Class */ +.highlight .vg { color: #003333 } /* Name.Variable.Global */ +.highlight .vi { color: #003333 } /* Name.Variable.Instance */ +.highlight .il { color: #FF6600 } /* Literal.Number.Integer.Long */ + +.type-csharp .highlight .k { color: #0000FF } +.type-csharp .highlight .kt { color: #0000FF } +.type-csharp .highlight .nf { color: #000000; font-weight: normal } +.type-csharp .highlight .nc { color: #2B91AF } +.type-csharp .highlight .nn { color: #000000 } +.type-csharp .highlight .s { color: #A31515 } +.type-csharp .highlight .sc { color: #A31515 } diff --git a/website/stylesheets/stylesheet.css b/website/stylesheets/stylesheet.css new file mode 100644 index 0000000..ca4db7a --- /dev/null +++ b/website/stylesheets/stylesheet.css @@ -0,0 +1,371 @@ +/******************************************************************************* +Slate Theme for GitHub Pages +by Jason Costello, @jsncostello +*******************************************************************************/ + +@import url(normalize.css); +@import url(pygment_trac.css); + +/******************************************************************************* +Theme Styles +*******************************************************************************/ + +*, *:before, *:after { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +body { + color:#373737; + background: #212121; + font-size: 18px; + font-family: 'Myriad Pro', Calibri, Helvetica, Arial, sans-serif; + line-height: 1.5; + -webkit-font-smoothing: antialiased; +} + +h1, h2, h3, h4, h5, h6 { + margin: 10px 0; + font-weight: 700; + color:#222222; + font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif; + letter-spacing: -1px; +} + +h1 { + font-size: 36px; + font-weight: 700; +} + +h2 { + padding-bottom: 10px; + font-size: 32px; + background: url('../images/bg_hr.png') repeat-x bottom; +} + +h3 { + font-size: 24px; +} + +h4 { + font-size: 21px; +} + +h5 { + font-size: 18px; +} + +h6 { + font-size: 16px; +} + +p { + font-size: 18px; + margin: 10px 0 15px 0; +} + +footer p { + color: #f2f2f2; +} + +a { + text-decoration: none; + color: #007edf; + text-shadow: none; +} + +a:hover, a:focus {text-decoration: underline;} + +footer a { + color: #F2F2F2; + text-decoration: underline; +} + +em { + font-style: italic; +} + +strong { + font-weight: bold; +} + +img { + position: relative; + margin: 0 auto; + max-width: 739px; + padding: 5px; + margin: 10px 0 10px 0; + border: 1px solid #ebebeb; + + box-shadow: 0 0 5px #ebebeb; + -webkit-box-shadow: 0 0 5px #ebebeb; + -moz-box-shadow: 0 0 5px #ebebeb; + -o-box-shadow: 0 0 5px #ebebeb; + -ms-box-shadow: 0 0 5px #ebebeb; +} + +p img { + display: inline; + margin: 0; + padding: 0; + vertical-align: middle; + text-align: center; + border: none; +} + +pre, code { + width: 100%; + color: #222; + background-color: #fff; + + font-family: Monaco, "Bitstream Vera Sans Mono", "Lucida Console", Terminal, monospace; + font-size: 14px; + + border-radius: 2px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + + box-shadow: 0 0 10px rgba(0,0,0,.1); +} + +pre { + padding: 10px; + overflow: auto; +} + +code { + padding: 3px; + margin: 0 3px; +} + +pre code { + display: block; + box-shadow: none; +} + +blockquote { + color: #666; + margin: 0 0 20px 2px; + padding-left: 20px; + border-left: 3px solid #bbb; + font-style: italic; +} + +ul, ol, dl { + margin: 0 0 15px 0; + padding-left: 20px; +} + +dl dt { + font-weight: bold; +} + +dl dd { + margin-left: 0; + padding-left: 0; + font-style: italic; +} + +dl p { + padding-left: 20px; + font-style: italic; +} + +hr { + height: 1px; + margin-bottom: 5px; + border: none; + background: url('../images/bg_hr.png') repeat-x center; +} + +table { + border: 1px solid #373737; + margin-bottom: 20px; + text-align: left; + } + +th { + font-family: 'Lucida Grande', 'Helvetica Neue', Helvetica, Arial, sans-serif; + padding: 10px; + background: #373737; + color: #fff; + } + +td { + padding: 10px; + border: 1px solid #373737; + } + +form { + background: #f2f2f2; + padding: 20px; +} + +/******************************************************************************* +Full-Width Styles +*******************************************************************************/ + +.outer { + width: 100%; +} + +.inner { + position: relative; + max-width: 640px; + padding: 20px 10px; + margin: 0 auto; +} + +#forkme_banner { + display: block; + position: absolute; + top:0; + right: 10px; + z-index: 10; + padding: 10px 50px 10px 10px; + color: #fff; + background: url('../images/blacktocat.png') #0090ff no-repeat 95% 50%; + font-weight: 700; + box-shadow: 0 0 10px rgba(0,0,0,.5); + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} + +#header_wrap { + background: #212121; +} + +#header_wrap .inner { + padding: 50px 10px 30px 10px; +} + +#project_title { + margin: 0; + color: #fff; + font-size: 42px; + font-weight: 700; + text-shadow: #111 0px 0px 10px; +} + +#project_tagline { + color: #fff; + font-size: 24px; + font-weight: 300; + background: none; + text-shadow: #111 0px 0px 10px; +} + +.menu_bar { + color: #fff; + font-size: 20px; + font-weight: 300; + background: none; + text-shadow: #111 0px 0px 10px; +} + +#downloads { + position: absolute; + width: 210px; + z-index: 10; + bottom: -40px; + right: 0; + height: 70px; + background: url('../images/icon_download.png') no-repeat 0% 90%; +} + +.zip_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom left; +} + +.tar_download_link { + display: block; + float: right; + width: 90px; + height:70px; + text-indent: -5000px; + overflow: hidden; + background: url(../images/sprite_download.png) no-repeat bottom right; + margin-left: 10px; +} + +.zip_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top left; +} + +.tar_download_link:hover { + background: url(../images/sprite_download.png) no-repeat top right; +} + +#main_content_wrap { + background: #f2f2f2; + border-top: 1px solid #111; + border-bottom: 1px solid #111; +} + +#main_content { + padding-top: 40px; +} + +#footer_wrap { + background: #212121; +} + +/******************************************************************************* +Small Device Styles +*******************************************************************************/ + +@media screen and (max-width: 480px) { + body { + font-size:14px; + } + + #downloads { + display: none; + } + + .inner { + min-width: 320px; + max-width: 480px; + } + + #project_title { + font-size: 32px; + } + + h1 { + font-size: 28px; + } + + h2 { + font-size: 24px; + } + + h3 { + font-size: 21px; + } + + h4 { + font-size: 18px; + } + + h5 { + font-size: 14px; + } + + h6 { + font-size: 12px; + } + + code, pre { + min-width: 320px; + max-width: 480px; + font-size: 11px; + } +}