From 018a81abdfa2b357c986dd4188d503473c4c0b27 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sun, 22 Nov 2015 03:21:08 +0900 Subject: [PATCH] Write document --- README.md | 152 ++++++++++++++++++++++++++++++++++++- REFERENCE.md | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 REFERENCE.md diff --git a/README.md b/README.md index 5e3ab4c7..8b475e7d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,155 @@ # Hamlit -High Performance Haml Implementation +Hamlit is a high performance [Haml](https://github.com/haml/haml) implementation. + +## Introduction + +### What is Hamlit? +Hamlit is another implementation of [Haml](https://github.com/haml/haml) and designed to make Haml language faster than +[Slim](https://github.com/slim-template/slim). With some [limitations](REFERENCE.md#limitations) by +design for performance, Hamlit is **7.16x times faster** than original haml gem in +this benchmark, which is an HTML-escaped version of slim-template/slim's one for fairness. + +![Hamlit Benchmark](http://i.gyazo.com/4fe00ff2ac2fa959dfcf86a5e27dc914.png) + +### Why is Hamlit faster? + +#### Less string concatenation by design +As written in [limitations](REFERENCE.md#limitations), Hamlit drops some not-so-important features which require +works on runtime. With the optimized language design, we can reduce the string concatenation +to build attributes. + +#### Temple optimizers +Hamlit is built with [Temple](https://github.com/judofyr/temple), which is a framework to build +template engines and also used in Slim. By using the framework and its optimizers, Hamlit can +reduce string allocation and concatenation easily. + +#### Static analyzer +Hamlit analyzes Ruby expressions with Ripper and render it on compilation if the expression +is static. + +#### C extension to build attributes +While Hamlit has static analyzer and static attributes are rendered on compilation, +dynamic attributes should be rendered on runtime. So Hamlit optimizes rendering on runtime +with C extension. + +## Usage + +See [REFERENCE.md](REFERENCE.md) for detail features of Hamlit. + +### Rails + +Add this line to your application's Gemfile or just replace `gem "haml"` with `gem "hamlit"`. +It enables rendering by Hamlit for \*.haml automatically. + +```rb +gem 'hamlit' +``` + +If you want to use view generator, consider using [hamlit-rails](https://github.com/mfung/hamlit-rails). + +### Sinatra + +Replace `gem "haml"` with `gem "hamlit"` in Gemfile, and require "hamlit". +See [sample/sinatra](sample/sinatra) for working sample. + +While Haml disables `escape_html` option by default, Hamlit enables it for security. +If you want to disable it, please write: + +```rb +set :haml, { escape_html: false } +``` + + +## Command line interface + +'hamlit' command is available if you install thor gem with `gem install thor`. + +```bash +$ gem install hamlit thor +$ hamlit --help +Commands: + hamlit compile HAML # Show compile result + hamlit help [COMMAND] # Describe available commands or one specific command + hamlit parse HAML # Show parse result + hamlit render HAML # Render haml template + +$ cat in.haml +.foo#bar + +# Show compiled code +$ hamlit compile in.haml +_buf = "
\n" + +# Render html +$ hamlit render in.haml +
+``` + +## Contributing + +### Development + +Contributions are welcomed. + +```bash +$ git clone https://github.com/k0kubun/hamlit +$ cd hamlit +$ bundle install + +# Run all tests +$ bundle exec rake test + +# Run one test +$ bundle exec ruby -Ilib:test -rtest_helper test/hamlit/line_number_test.rb -l 12 + +# Show compiling/rendering result of some template +$ bundle exec exe/hamlit compile in.haml +$ bundle exec exe/hamlit render in.haml + +# Use rails app to debug Hamlit +$ cd sample/rails +$ bundle install +$ bundle exec rails s +``` + +### Reporting an issue + +Please report an issue with following information: + +- Full error backtrace +- Haml template +- Ruby version +- Hamlit version +- Rails/Sinatra version ## License -The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). +MIT License + +Copyright (c) 2015 Takashi Kokubun + +### Parser and Haml tests + +lib/hamlit/parser/\*.rb and test/haml/\* are: + +Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/REFERENCE.md b/REFERENCE.md new file mode 100644 index 00000000..01e3adf4 --- /dev/null +++ b/REFERENCE.md @@ -0,0 +1,211 @@ +# Hamlit + +Basically Hamlit is the same as Haml. +See [Haml's tutorial](http://haml.info/tutorial.html) if you are not familiar with Haml's syntax. + +[REFERENCE - Haml Documentation](http://haml.info/docs/yardoc/file.REFERENCE.html) + +## Supported features + +See [Haml's reference](http://haml.info/docs/yardoc/file.REFERENCE.html) +for full features in original implementation. + +- [x] Using Haml + - [x] Rails XSS Protection + - [x] Ruby Module + - [x] Options + - [ ] Encodings +- [x] Plain Text + - [x] Escaping: \ +- [x] HTML Elements + - [x] Element Name: % + - [x] Attributes: ` + - [x] :class and :id Attributes + - [x] HTML-style Attributes: () + - [x] Ruby 1.9-style Hashes + - [ ] Attribute Methods + - [x] Boolean Attributes + - [x] HTML5 Custom Data Attributes + - [x] Class and ID: . and # + - Implicit Div Elements + - [x] Empty (void) Tags: / + - [x] Whitespace Removal: > and < + - [x] Object Reference: [] +- [x] Doctype: !!! +- [x] Comments + - [x] HTML Comments: / + - [x] Conditional Comments: /[] + - [x] Haml Comments: -# +- [x] Ruby Evaluation + - [x] Inserting Ruby: = + - [x] Running Ruby: - + - [x] Ruby Blocks + - [x] Whitespace Preservation: ~ + - [x] Ruby Interpolation: #{} + - [x] Escaping HTML: &= + - [x] Unescaping HTML: != +- [x] Filters + - [ ] :cdata + - [x] :coffee + - [x] :css + - [x] :erb + - [x] :escaped + - [x] :javascript + - [x] :less + - [x] :markdown + - [ ] :maruku + - [x] :plain + - [x] :preserve + - [x] :ruby + - [x] :sass + - [x] :scss + - [ ] :textile + - [ ] Custom Filters +- [ ] Helper Methods + - [x] surround + - [x] precede + - [x] succeed +- [x] Multiline: | +- [x] Whitespace Preservation +- [ ] Helpers + + +## Limitations + +### No pretty mode +Haml has :pretty mode and :ugly mode. :pretty mode is used on development and indented beautifully. +On production environemnt, :ugly mode is used and Hamlit currently supports only this mode. + +So you'll see difference rendering result on development environment, but it'll be the same on production. + +### No Haml buffer +Hamlit uses Array as buffer for performance. So you can't touch Haml::Buffer from template when using Hamlit. + +### Haml helpers are still in development +At the same time, because some methods in Haml::Buffer requires Haml::Buffer, they are not supported now. +But some helpers are supported on Rails. Some of them are planned to be supported. + +### Limited attributes hyphenation +In Haml, `%a{ foo: { bar: 'baz' } }` is rendered as ``, whatever foo is. +In Hamlit, this feature is supported only for data attribute. Hamlit renders `%a{ data: { foo: 'bar' } }` +as `` because it's data attribute. + +This design allows us to reduce work on runtime and is originally in [Faml](https://github.com/eagletmt/faml). + +### Limited boolean attributes +In Haml, `%a{ foo: false }` is rendered as ``, whatever foo is. +In Hamlit, this feature is supported for only boolean attributes, which is in +http://www.w3.org/TR/xhtml1/guidelines.html https://html.spec.whatwg.org/. +The list is the same as `ActionView::Helpers::TagHelper::BOOLEAN_ATTRIBUTES`. + +Since foo is not boolean attribute, `%a{ foo: false }` is rendered as ``. +This is the same behavior as not Haml but Rails helpers. + +For nil, while Haml and Rails remove the attribute entirely if the value is nil, +Hamlit does not remove non-boolean attributes and render ``. +This design allows us to reduce String concatenation. + +This is the largest difference between Hamlit and Faml. + +## 5 Types of Attributes + +Haml has 3 types of attributes: id, class and others. +In addition, Hamlit treats data and boolean attributes specially. +So there are 5 types of attributes in Hamlit. + +### id attribute +Almost the same behavior as Haml, except no hyphenation and boolean support. +Multiple id specification results in `_`-concatenation. + +```rb +# Input +%div{ id: %w[foo bar] } +#foo{ id: 'bar' } + +# Output +
+
+``` + +### class attribute +Almost the same behavior as Haml, except no hyphenation and boolean support. +Multiple class specification results in unique alphabetical sort. + +```rb +# Input +%div{ class: 'd c b a' } +.d.a(class='b c'){ class: 'c a' } + +# Output +
+
+``` + +### data attribute +Hyphenation is supported but boolean support is for only `data-#{boolean attribute}`. + +```rb +# Input +%div{ data: { disabled: true } } +%div{ data: { foo: 'bar' } } + +# Output +
+
+``` + +### boolean attributes +No hyphenation but complete boolean support. + +```rb +# Input +%div{ disabled: true } +%div{ disabled: false } + +# Output +
+
+``` + +List of boolean attributes is: + +``` +disabled readonly multiple checked autobuffer autoplay controls loop selected hidden scoped async +defer reversed ismap seamless muted required autofocus novalidate formnovalidate open pubdate +itemscope allowfullscreen default inert sortable truespeed typemustmatch +``` + +### other attributes +No hyphenation and boolean support. + +```rb +# Input +%input{ value: true } +%input{ value: false } + +# Output + + +``` + +## Engine options + +| Option | Default | Feature | +|:-------|:--------|:--------| +| escape\_html | true | HTML-escape for Ruby script and interpolation. This is false in Haml. | +| escape\_attrs | true | HTML-escape for Html attributes. | +| format | :html | You can set :xhtml to change boolean attribute's format. | +| attr\_quote | `'` | You can change attribute's wrapper to `"` or something. | + +### Set options for Rails + +```rb +# config/initializers/hamlit.rb or somewhere +Hamlit::RailsTemplate.set_options attr_quote: '"' +``` + +### Set options for Sinatra + +```rb +set :haml, { attr_quote: '"' } +```