hamlit 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +34 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +23 -0
  7. data/README.md +45 -0
  8. data/Rakefile +34 -0
  9. data/benchmarks/benchmark.rb +94 -0
  10. data/benchmarks/context.rb +13 -0
  11. data/benchmarks/view.erb +23 -0
  12. data/benchmarks/view.haml +18 -0
  13. data/benchmarks/view.rbhtml +23 -0
  14. data/benchmarks/view.slim +17 -0
  15. data/bin/hamlit +6 -0
  16. data/hamlit.gemspec +40 -0
  17. data/lib/hamlit/attribute.rb +31 -0
  18. data/lib/hamlit/cli.rb +89 -0
  19. data/lib/hamlit/compiler.rb +24 -0
  20. data/lib/hamlit/compilers/attributes.rb +78 -0
  21. data/lib/hamlit/compilers/comment.rb +13 -0
  22. data/lib/hamlit/compilers/doctype.rb +39 -0
  23. data/lib/hamlit/compilers/dynamic.rb +9 -0
  24. data/lib/hamlit/compilers/filter.rb +53 -0
  25. data/lib/hamlit/compilers/new_attribute.rb +107 -0
  26. data/lib/hamlit/compilers/old_attribute.rb +147 -0
  27. data/lib/hamlit/compilers/preserve.rb +10 -0
  28. data/lib/hamlit/compilers/script.rb +31 -0
  29. data/lib/hamlit/compilers/strip.rb +30 -0
  30. data/lib/hamlit/compilers/text.rb +15 -0
  31. data/lib/hamlit/concerns/attribute_builder.rb +21 -0
  32. data/lib/hamlit/concerns/balanceable.rb +59 -0
  33. data/lib/hamlit/concerns/deprecation.rb +20 -0
  34. data/lib/hamlit/concerns/error.rb +27 -0
  35. data/lib/hamlit/concerns/escapable.rb +17 -0
  36. data/lib/hamlit/concerns/included.rb +28 -0
  37. data/lib/hamlit/concerns/indentable.rb +53 -0
  38. data/lib/hamlit/concerns/line_reader.rb +60 -0
  39. data/lib/hamlit/concerns/registerable.rb +24 -0
  40. data/lib/hamlit/concerns/ripperable.rb +20 -0
  41. data/lib/hamlit/concerns/string_interpolation.rb +48 -0
  42. data/lib/hamlit/engine.rb +42 -0
  43. data/lib/hamlit/filters/base.rb +44 -0
  44. data/lib/hamlit/filters/coffee.rb +12 -0
  45. data/lib/hamlit/filters/css.rb +34 -0
  46. data/lib/hamlit/filters/erb.rb +11 -0
  47. data/lib/hamlit/filters/escaped.rb +19 -0
  48. data/lib/hamlit/filters/javascript.rb +34 -0
  49. data/lib/hamlit/filters/less.rb +12 -0
  50. data/lib/hamlit/filters/markdown.rb +11 -0
  51. data/lib/hamlit/filters/plain.rb +21 -0
  52. data/lib/hamlit/filters/preserve.rb +11 -0
  53. data/lib/hamlit/filters/ruby.rb +11 -0
  54. data/lib/hamlit/filters/sass.rb +12 -0
  55. data/lib/hamlit/filters/scss.rb +12 -0
  56. data/lib/hamlit/filters/tilt.rb +41 -0
  57. data/lib/hamlit/helpers.rb +38 -0
  58. data/lib/hamlit/html/pretty.rb +49 -0
  59. data/lib/hamlit/html/ugly.rb +10 -0
  60. data/lib/hamlit/parser.rb +123 -0
  61. data/lib/hamlit/parsers/attribute.rb +52 -0
  62. data/lib/hamlit/parsers/comment.rb +27 -0
  63. data/lib/hamlit/parsers/doctype.rb +18 -0
  64. data/lib/hamlit/parsers/filter.rb +18 -0
  65. data/lib/hamlit/parsers/multiline.rb +54 -0
  66. data/lib/hamlit/parsers/script.rb +93 -0
  67. data/lib/hamlit/parsers/tag.rb +71 -0
  68. data/lib/hamlit/parsers/text.rb +11 -0
  69. data/lib/hamlit/parsers/whitespace.rb +38 -0
  70. data/lib/hamlit/railtie.rb +21 -0
  71. data/lib/hamlit/template.rb +9 -0
  72. data/lib/hamlit/version.rb +3 -0
  73. data/lib/hamlit.rb +8 -0
  74. data/spec/Rakefile +79 -0
  75. data/spec/hamlit/compilers/script_spec.rb +46 -0
  76. data/spec/hamlit/engine/comment_spec.rb +29 -0
  77. data/spec/hamlit/engine/doctype_spec.rb +19 -0
  78. data/spec/hamlit/engine/error_spec.rb +47 -0
  79. data/spec/hamlit/engine/multiline_spec.rb +44 -0
  80. data/spec/hamlit/engine/new_attribute_spec.rb +19 -0
  81. data/spec/hamlit/engine/old_attributes_spec.rb +85 -0
  82. data/spec/hamlit/engine/preservation_spec.rb +11 -0
  83. data/spec/hamlit/engine/script_spec.rb +87 -0
  84. data/spec/hamlit/engine/silent_script_spec.rb +135 -0
  85. data/spec/hamlit/engine/tag_spec.rb +210 -0
  86. data/spec/hamlit/engine/text_spec.rb +29 -0
  87. data/spec/hamlit/engine_spec.rb +20 -0
  88. data/spec/hamlit/filters/coffee_spec.rb +41 -0
  89. data/spec/hamlit/filters/css_spec.rb +33 -0
  90. data/spec/hamlit/filters/erb_spec.rb +16 -0
  91. data/spec/hamlit/filters/javascript_spec.rb +82 -0
  92. data/spec/hamlit/filters/less_spec.rb +22 -0
  93. data/spec/hamlit/filters/markdown_spec.rb +28 -0
  94. data/spec/hamlit/filters/ruby_spec.rb +24 -0
  95. data/spec/hamlit/filters/sass_spec.rb +37 -0
  96. data/spec/hamlit/filters/scss_spec.rb +21 -0
  97. data/spec/hamlit/ugly_spec.rb +912 -0
  98. data/spec/rails/.gitignore +17 -0
  99. data/spec/rails/.rspec +2 -0
  100. data/spec/rails/Gemfile +19 -0
  101. data/spec/rails/Gemfile.lock +177 -0
  102. data/spec/rails/README.rdoc +28 -0
  103. data/spec/rails/Rakefile +6 -0
  104. data/spec/rails/app/assets/images/.keep +0 -0
  105. data/spec/rails/app/assets/javascripts/application.js +15 -0
  106. data/spec/rails/app/assets/stylesheets/application.css +15 -0
  107. data/spec/rails/app/controllers/application_controller.rb +8 -0
  108. data/spec/rails/app/controllers/concerns/.keep +0 -0
  109. data/spec/rails/app/controllers/users_controller.rb +20 -0
  110. data/spec/rails/app/helpers/application_helper.rb +2 -0
  111. data/spec/rails/app/mailers/.keep +0 -0
  112. data/spec/rails/app/models/.keep +0 -0
  113. data/spec/rails/app/models/concerns/.keep +0 -0
  114. data/spec/rails/app/views/application/index.html.haml +15 -0
  115. data/spec/rails/app/views/layouts/application.html.haml +12 -0
  116. data/spec/rails/app/views/users/capture.html.haml +5 -0
  117. data/spec/rails/app/views/users/capture_haml.html.haml +5 -0
  118. data/spec/rails/app/views/users/form.html.haml +2 -0
  119. data/spec/rails/app/views/users/helpers.html.haml +1 -0
  120. data/spec/rails/app/views/users/index.html.haml +9 -0
  121. data/spec/rails/app/views/users/safe_buffer.html.haml +4 -0
  122. data/spec/rails/bin/bundle +3 -0
  123. data/spec/rails/bin/rails +8 -0
  124. data/spec/rails/bin/rake +8 -0
  125. data/spec/rails/bin/setup +29 -0
  126. data/spec/rails/bin/spring +15 -0
  127. data/spec/rails/config/application.rb +34 -0
  128. data/spec/rails/config/boot.rb +3 -0
  129. data/spec/rails/config/database.yml +25 -0
  130. data/spec/rails/config/environment.rb +5 -0
  131. data/spec/rails/config/environments/development.rb +41 -0
  132. data/spec/rails/config/environments/production.rb +79 -0
  133. data/spec/rails/config/environments/test.rb +42 -0
  134. data/spec/rails/config/initializers/assets.rb +11 -0
  135. data/spec/rails/config/initializers/backtrace_silencers.rb +7 -0
  136. data/spec/rails/config/initializers/cookies_serializer.rb +3 -0
  137. data/spec/rails/config/initializers/filter_parameter_logging.rb +4 -0
  138. data/spec/rails/config/initializers/inflections.rb +16 -0
  139. data/spec/rails/config/initializers/mime_types.rb +4 -0
  140. data/spec/rails/config/initializers/session_store.rb +3 -0
  141. data/spec/rails/config/initializers/wrap_parameters.rb +14 -0
  142. data/spec/rails/config/locales/en.yml +23 -0
  143. data/spec/rails/config/routes.rb +13 -0
  144. data/spec/rails/config/secrets.yml +22 -0
  145. data/spec/rails/config.ru +4 -0
  146. data/spec/rails/db/schema.rb +16 -0
  147. data/spec/rails/db/seeds.rb +7 -0
  148. data/spec/rails/lib/assets/.keep +0 -0
  149. data/spec/rails/lib/tasks/.keep +0 -0
  150. data/spec/rails/log/.keep +0 -0
  151. data/spec/rails/public/404.html +67 -0
  152. data/spec/rails/public/422.html +67 -0
  153. data/spec/rails/public/500.html +66 -0
  154. data/spec/rails/public/favicon.ico +0 -0
  155. data/spec/rails/public/robots.txt +5 -0
  156. data/spec/rails/spec/hamlit_spec.rb +87 -0
  157. data/spec/rails/spec/rails_helper.rb +56 -0
  158. data/spec/rails/spec/spec_helper.rb +91 -0
  159. data/spec/rails/vendor/assets/javascripts/.keep +0 -0
  160. data/spec/rails/vendor/assets/stylesheets/.keep +0 -0
  161. data/spec/spec_helper.rb +48 -0
  162. metadata +560 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8594e7acaa30584a12d923e97b4b7a21b407f054
4
+ data.tar.gz: 03eb5ce30ba76ac8c46df2f7b62dff6674569d22
5
+ SHA512:
6
+ metadata.gz: f32944cc0f55a3f4aad6c4bf0bc52e36e7a1a24dd57963af0bbf575c1fa50d542d6e63d690c9067d65134fa2ae2f9877b770ae96357ae64d5b91977c05b6590a
7
+ data.tar.gz: fb37bdf58c61dfcd68807df744ca705b865225074fd147bbd339560cf4242ec1713977d02b2084d924343e8b4ec08383534934379dc47fd2cc99ade73f486a72
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ *.cache
15
+ mkmf.log
16
+ .sass-cache/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,34 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 2.1
5
+ - 2.2
6
+ sudo: false
7
+ cache: bundler
8
+ script:
9
+ - "bundle exec rake $TASK"
10
+ gemfile:
11
+ - Gemfile
12
+ - spec/rails/Gemfile
13
+ env:
14
+ - TASK=spec
15
+ - TASK=rails:spec
16
+ - TASK=bench TIME=10
17
+ matrix:
18
+ allow_failures:
19
+ - env: TASK=bench TIME=10
20
+ exclude:
21
+ - env: TASK=spec
22
+ gemfile: spec/rails/Gemfile
23
+ - env: TASK=rails:spec
24
+ gemfile: Gemfile
25
+ - env: TASK=bench TIME=10
26
+ gemfile: spec/rails/Gemfile
27
+ - rvm: 2.1
28
+ env: TASK=rails:spec
29
+ - rvm: 2.1
30
+ env: TASK=bench TIME=10
31
+ - rvm: 2.0.0
32
+ env: TASK=rails:spec
33
+ - rvm: 2.0.0
34
+ env: TASK=bench TIME=10
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hamlit.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2015 Takashi Kokubun
2
+ Copyright (c) 2006-2009 Hampton Catlin and Natalie Weizenbaum
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Hamlit [![Build Status](https://travis-ci.org/k0kubun/hamlit.svg?branch=master)](https://travis-ci.org/k0kubun/hamlit)
2
+
3
+ Hamlit is a high performance [haml](https://github.com/haml/haml) implementation.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'hamlit'
11
+ ```
12
+
13
+ or just replace `gem "haml"` with `gem "hamlit"`.
14
+
15
+ ## Features
16
+ ### Fast rendering
17
+
18
+ Hamlit's rendering is **8.47x times faster** than original haml.
19
+
20
+ ```
21
+ hamlit: 133922.9 i/s
22
+ erubis: 123464.1 i/s - 1.08x slower
23
+ slim: 110404.3 i/s - 1.21x slower
24
+ faml: 92009.3 i/s - 1.46x slower
25
+ haml: 15810.4 i/s - 8.47x slower
26
+ ```
27
+
28
+ [This benchmark](https://github.com/k0kubun/hamlit/blob/74ede1101f228828e343ceb1af481c45eaf0a1dd/benchmarks/benchmark.rb)
29
+ is the same as [slim-template/slim](https://github.com/slim-template/slim)'s one for fairness.
30
+ ([The result on travis CI](https://travis-ci.org/k0kubun/hamlit/jobs/56403724))
31
+
32
+ ### Better parser
33
+
34
+ Haml's attribute parser is not so good. For example, raises syntax error for `%a{ b: '}' }`.
35
+ Hamlit's attribute parser is implemented with Ripper, which is an official lexer for Ruby,
36
+ so it can able to parse such an attribute.
37
+
38
+ ### Passing haml-spec
39
+
40
+ [haml/haml-spec](https://github.com/haml/haml-spec) is a basic suite of tests for Haml interpreters.
41
+ For all test cases in haml-spec, Hamlit behaves the same as Haml (ugly mode only, which is used on production).
42
+
43
+ ## License
44
+
45
+ MIT License
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ desc 'Run benchmarks'
4
+ task :bench do
5
+ exit system('bundle exec ruby benchmarks/benchmark.rb')
6
+ end
7
+
8
+ desc 'Run RSpec code examples'
9
+ task :spec do
10
+ exit system('bundle exec rspec --pattern spec/hamlit/**{,/\*/\*\*\}/\*_spec.rb')
11
+ end
12
+
13
+ namespace :spec do
14
+ namespace :update do
15
+ desc 'Generate converted ugly haml-spec'
16
+ task :ugly do
17
+ system('cd spec && rake ugly')
18
+ end
19
+
20
+ desc 'Generate converted pretty haml-spec'
21
+ task :pretty do
22
+ system('cd spec && rake pretty')
23
+ end
24
+ end
25
+ end
26
+
27
+ namespace :rails do
28
+ desc 'Run Rails specs'
29
+ task :spec do
30
+ exit system('cd spec/rails && rake spec')
31
+ end
32
+ end
33
+
34
+ task default: [:spec, 'rails:spec']
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
4
+
5
+ require_relative './context'
6
+ require 'benchmark/ips'
7
+
8
+ require 'erb'
9
+ require 'erubis'
10
+ require 'faml'
11
+ require 'haml'
12
+ require 'slim'
13
+ require 'tenjin'
14
+ require 'tilt'
15
+ require 'hamlit'
16
+
17
+ class Benchmarks
18
+ def initialize(time)
19
+ @time = time
20
+ @benches = []
21
+ @versions = {}
22
+
23
+ @erb_code = File.read(File.dirname(__FILE__) + '/view.erb')
24
+ @haml_code = File.read(File.dirname(__FILE__) + '/view.haml')
25
+ @slim_code = File.read(File.dirname(__FILE__) + '/view.slim')
26
+ @rbhtml_path = File.dirname(__FILE__) + '/view.rbhtml'
27
+
28
+ init_compiled_benches
29
+ end
30
+
31
+ def init_compiled_benches
32
+ erb = ERB.new(@erb_code)
33
+ erubis = Erubis::Eruby.new(@erb_code)
34
+ fast_erubis = Erubis::FastEruby.new(@erb_code)
35
+ haml_ugly = Haml::Engine.new(@haml_code, format: :html5, ugly: true)
36
+ tenjin = Tenjin::Engine.new.get_template(@rbhtml_path)
37
+
38
+ context = Context.new
39
+
40
+ haml_ugly.def_method(context, :run_haml_ugly)
41
+ context.instance_eval %{
42
+ def run_erb; #{erb.src}; end
43
+ def run_erubis; #{erubis.src}; end
44
+ def run_temple_erb; #{Temple::ERB::Engine.new.call @erb_code}; end
45
+ def run_fast_erubis; #{fast_erubis.src}; end
46
+ def run_slim_ugly; #{Slim::Engine.new.call @slim_code}; end
47
+ def run_faml; #{Faml::Engine.new.call @haml_code}; end
48
+ def run_tenjin; _buf = ''; #{tenjin.script}; end
49
+ def run_hamlit; #{Hamlit::Engine.new.call @haml_code}; end
50
+ }
51
+
52
+ bench('hamlit', Hamlit::VERSION) { context.run_hamlit }
53
+ bench('erubis', Erubis::VERSION) { context.run_erubis }
54
+ bench('slim', Slim::VERSION) { context.run_slim_ugly }
55
+ bench('faml', Faml::VERSION) { context.run_faml }
56
+ bench('haml', Haml::VERSION) { context.run_haml_ugly }
57
+
58
+ if ENV['ALL']
59
+ erb_version = ERB.version.match(/\[([^ ]+)/)[1]
60
+ bench('tenjin', Tenjin::RELEASE) { context.run_tenjin }
61
+ bench('fast erubis', Erubis::VERSION) { context.run_fast_erubis }
62
+ bench('temple erb', Temple::VERSION) { context.run_temple_erb }
63
+ bench('erb', erb_version) { context.run_erb }
64
+ end
65
+ end
66
+
67
+ def run
68
+ show_versions
69
+ result = Benchmark.ips do |x|
70
+ x.config(time: @time, warmup: 2)
71
+ @benches.each do |name, block|
72
+ x.report(name, &block)
73
+ end
74
+ x.compare!
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def bench(name, version, &block)
81
+ @benches.push([name, block])
82
+ @versions[name] = version
83
+ end
84
+
85
+ def show_versions
86
+ puts 'Versions ' + '-' * 40
87
+ @versions.each do |name, version|
88
+ printf "%20s %10s\n", name, "v#{version}"
89
+ end
90
+ end
91
+ end
92
+
93
+ time = (ENV['TIME'] || 5).to_i
94
+ Benchmarks.new(time).run
@@ -0,0 +1,13 @@
1
+ class Context
2
+ def header
3
+ 'Colors'
4
+ end
5
+
6
+ def item
7
+ [
8
+ { name: 'red', current: true, url: '#red' },
9
+ { name: 'green', current: false, url: '#green' },
10
+ { name: 'blue', current: false, url: '#blue' },
11
+ ]
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE HTML>
2
+
3
+ <html>
4
+ <head>
5
+ <title>Simple Benchmark</title>
6
+ </head>
7
+ <body>
8
+ <h1><%= header %></h1>
9
+ <% unless item.empty? %>
10
+ <ul>
11
+ <% for i in item %>
12
+ <% if i[:current] %>
13
+ <li><strong><%= i[:name] %></strong></li>
14
+ <% else %>
15
+ <li><a href="<%= i[:url] %>"><%= i[:name] %></a></li>
16
+ <% end %>
17
+ <% end %>
18
+ </ul>
19
+ <% else %>
20
+ <p>The list is empty.</p>
21
+ <% end %>
22
+ </body>
23
+ </html>
@@ -0,0 +1,18 @@
1
+ !!! html
2
+
3
+ %html
4
+ %head
5
+ %title Simple Benchmark
6
+ %body
7
+ %h1= header
8
+ - unless item.empty?
9
+ %ul
10
+ - for i in item
11
+ - if i[:current]
12
+ %li
13
+ %strong= i[:name]
14
+ - else
15
+ %li
16
+ %a{:href => i[:url]}= i[:name]
17
+ - else
18
+ %p The list is empty.
@@ -0,0 +1,23 @@
1
+ <!DOCTYPE HTML>
2
+
3
+ <html>
4
+ <head>
5
+ <title>Simple Benchmark</title>
6
+ </head>
7
+ <body>
8
+ <h1>#{ header }</h1>
9
+ <?rb unless item.empty? ?>
10
+ <ul>
11
+ <?rb for i in item ?>
12
+ <?rb if i[:current] ?>
13
+ <li><strong>#{ i[:name] }</strong></li>
14
+ <?rb else ?>
15
+ <li><a href="#{ i[:url] }">#{ i[:name] }</a></li>
16
+ <?rb end ?>
17
+ <?rb end ?>
18
+ </ul>
19
+ <?rb else ?>
20
+ <p>The list is empty.</p>
21
+ <?rb end ?>
22
+ </body>
23
+ </html>
@@ -0,0 +1,17 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title Simple Benchmark
5
+ body
6
+ h1 == header
7
+ - unless item.empty?
8
+ ul
9
+ - for i in item
10
+ - if i[:current]
11
+ li
12
+ strong == i[:name]
13
+ - else
14
+ li
15
+ a href==i[:url] == i[:name]
16
+ - else
17
+ p The list is empty.
data/bin/hamlit ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../lib', __FILE__)
4
+ require 'hamlit/cli'
5
+
6
+ Hamlit::CLI.start(ARGV)
data/hamlit.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hamlit/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hamlit"
8
+ spec.version = Hamlit::VERSION
9
+ spec.authors = ["Takashi Kokubun"]
10
+ spec.email = ["takashikkbn@gmail.com"]
11
+ spec.summary = %q{Yet another haml implementation}
12
+ spec.description = %q{Yet another haml implementation}
13
+ spec.homepage = "https://github.com/k0kubun/hamlit"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "temple"
22
+ spec.add_dependency "thor"
23
+ spec.add_dependency "tilt"
24
+ spec.add_development_dependency "benchmark-ips"
25
+ spec.add_development_dependency "bundler"
26
+ spec.add_development_dependency "coffee-script"
27
+ spec.add_development_dependency "erubis"
28
+ spec.add_development_dependency "faml"
29
+ spec.add_development_dependency "haml"
30
+ spec.add_development_dependency "less"
31
+ spec.add_development_dependency "pry"
32
+ spec.add_development_dependency "rake"
33
+ spec.add_development_dependency "redcarpet"
34
+ spec.add_development_dependency "rspec", ">= 3"
35
+ spec.add_development_dependency "sass"
36
+ spec.add_development_dependency "slim"
37
+ spec.add_development_dependency "tenjin"
38
+ spec.add_development_dependency "therubyracer"
39
+ spec.add_development_dependency "unindent"
40
+ end
@@ -0,0 +1,31 @@
1
+ require 'hamlit/concerns/attribute_builder'
2
+ require 'temple/utils'
3
+
4
+ # Hamlit::Attribute is a module to compile old-style attributes which
5
+ # can be compiled only on runtime. If you write old-style attributes
6
+ # which is not valid as Ruby hash, the attributes are compiled on runtime.
7
+ #
8
+ # Note that you should avoid writing such a template for performance.
9
+ module Hamlit
10
+ class Attribute
11
+ include Concerns::AttributeBuilder
12
+
13
+ def self.build(quote, attributes)
14
+ builder = self.new(quote)
15
+ builder.build(attributes)
16
+ end
17
+
18
+ def initialize(quote)
19
+ @quote = quote
20
+ end
21
+
22
+ def build(attributes)
23
+ result = ''
24
+ flatten_attributes(attributes).each do |key, value|
25
+ escaped = Temple::Utils.escape_html(value)
26
+ result += " #{key}=#{@quote}#{escaped}#{@quote}"
27
+ end
28
+ result
29
+ end
30
+ end
31
+ end
data/lib/hamlit/cli.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'hamlit'
2
+ require 'thor'
3
+
4
+ module Hamlit
5
+ class CLI < Thor
6
+ IGNORED_COMPILERS = ['HTML'].freeze
7
+
8
+ desc 'render HAML', 'Render haml template'
9
+ option :ugly, type: :boolean, aliases: ['-u']
10
+ def render(file)
11
+ code = generate_code(file)
12
+ puts eval(code)
13
+ end
14
+
15
+ desc 'compile HAML', 'Show generated rendering code'
16
+ option :ugly, type: :boolean, aliases: ['-u']
17
+ def compile(file)
18
+ code = generate_code(file)
19
+ puts code
20
+ end
21
+
22
+ desc 'temple HAML', 'Show a compile result of hamlit AST'
23
+ option :ugly, type: :boolean, aliases: ['-u']
24
+ def temple(file)
25
+ pp generate_temple_ast(file)
26
+ end
27
+
28
+ desc 'parse HAML', 'Show parse result'
29
+ def parse(file)
30
+ pp generate_hamlit_ast(file)
31
+ end
32
+
33
+ private
34
+
35
+ # Flexible default_task, compatible with haml's CLI
36
+ def method_missing(*args)
37
+ return super(*args) if args.length > 1
38
+
39
+ render(args.first.to_s)
40
+ end
41
+
42
+ def generate_code(file)
43
+ template = File.read(file)
44
+ Hamlit::Engine.new(options).call(template)
45
+ end
46
+
47
+ def generate_temple_ast(file)
48
+ chain = Hamlit::Engine.chain.map(&:first).map(&:to_s)
49
+ compilers = chain.select do |compiler|
50
+ compiler =~ /\AHamlit::/ && !ignored_compilers.include?(compiler)
51
+ end
52
+
53
+ template = File.read(file)
54
+ compilers.inject(template) do |exp, compiler|
55
+ Module.const_get(compiler).new(options).call(exp)
56
+ end
57
+ end
58
+
59
+ def generate_hamlit_ast(file)
60
+ template = File.read(file)
61
+ Hamlit::Parser.new.call(template)
62
+ end
63
+
64
+ # Enable colored pretty printing only for development environment.
65
+ # I don't think it is a good idea to add pry as runtime dependency
66
+ # just for debug color printing.
67
+ def pp(arg)
68
+ begin
69
+ require 'pry'
70
+ Pry::ColorPrinter.pp(arg)
71
+ rescue LoadError
72
+ require 'pp'
73
+ super(arg)
74
+ end
75
+ end
76
+
77
+ def ignored_compilers
78
+ IGNORED_COMPILERS.map { |name| "Hamlit::#{name}" }
79
+ end
80
+
81
+ def options
82
+ symbolize_keys(super)
83
+ end
84
+
85
+ def symbolize_keys(hash)
86
+ {}.tap { |h| hash.each { |k, v| h[k.to_sym] = v } }
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,24 @@
1
+ require 'hamlit/compilers/attributes'
2
+ require 'hamlit/compilers/comment'
3
+ require 'hamlit/compilers/doctype'
4
+ require 'hamlit/compilers/dynamic'
5
+ require 'hamlit/compilers/filter'
6
+ require 'hamlit/compilers/preserve'
7
+ require 'hamlit/compilers/script'
8
+ require 'hamlit/compilers/strip'
9
+ require 'hamlit/compilers/text'
10
+ require 'temple/html/filter'
11
+
12
+ module Hamlit
13
+ class Compiler < Temple::HTML::Filter
14
+ include Compilers::Attributes
15
+ include Compilers::Comment
16
+ include Compilers::Doctype
17
+ include Compilers::Dynamic
18
+ include Compilers::Filter
19
+ include Compilers::Preserve
20
+ include Compilers::Script
21
+ include Compilers::Strip
22
+ include Compilers::Text
23
+ end
24
+ end
@@ -0,0 +1,78 @@
1
+ require 'hamlit/compilers/new_attribute'
2
+ require 'hamlit/compilers/old_attribute'
3
+ require 'hamlit/concerns/included'
4
+
5
+ module Hamlit
6
+ module Compilers
7
+ module Attributes
8
+ extend Concerns::Included
9
+ include Compilers::NewAttribute
10
+ include Compilers::OldAttribute
11
+
12
+ included do
13
+ define_options :format, :attr_quote
14
+ end
15
+
16
+ def on_haml_attrs(*attrs)
17
+ attrs = compile_attributes(attrs)
18
+ attrs = join_ids(attrs)
19
+ attrs = combine_classes(attrs)
20
+ attrs = pull_class_first(attrs)
21
+ [:html, :attrs, *attrs]
22
+ end
23
+
24
+ private
25
+
26
+ def compile_attributes(exps)
27
+ attrs = []
28
+ exps.each do |exp|
29
+ case exp
30
+ when /\A\(.+\)\Z/
31
+ attrs += compile_new_attribute(exp)
32
+ when /\A{.+}\Z/
33
+ attrs += compile_old_attribute(exp)
34
+ else
35
+ attrs << compile(exp)
36
+ end
37
+ end
38
+ attrs
39
+ end
40
+
41
+ def pull_class_first(attrs)
42
+ class_attrs = filter_attrs(attrs, 'class')
43
+ combine_classes(class_attrs) + (attrs - class_attrs)
44
+ end
45
+
46
+ def combine_classes(attrs)
47
+ class_attrs = filter_attrs(attrs, 'class')
48
+ return attrs if class_attrs.length <= 1
49
+
50
+ values = class_attrs.map(&:last).sort_by(&:last)
51
+ [[:html, :attr, 'class', [:multi, *insert_static(values, ' ')]]] + (attrs - class_attrs)
52
+ end
53
+
54
+ def join_ids(attrs)
55
+ id_attrs = filter_attrs(attrs, 'id')
56
+ return attrs if id_attrs.length <= 1
57
+
58
+ values = attrs.map(&:last)
59
+ [[:html, :attr, 'id', [:multi, *insert_static(values, '_')]]] + (attrs - id_attrs)
60
+ end
61
+
62
+ def filter_attrs(attrs, target)
63
+ class_attrs = attrs.select do |html, attr, name, content|
64
+ name == target
65
+ end
66
+ end
67
+
68
+ def insert_static(array, str)
69
+ result = []
70
+ array.each_with_index do |value, index|
71
+ result << [:static, str] if index > 0
72
+ result << value
73
+ end
74
+ result
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,13 @@
1
+ module Hamlit
2
+ module Compilers
3
+ module Comment
4
+ def on_haml_comment(condition, exps)
5
+ content = [:multi]
6
+ content << [:static, "#{condition}>\n"]
7
+ content += exps.map { |exp| compile(exp) }
8
+ content << [:static, "<![endif]"]
9
+ [:html, :comment, content]
10
+ end
11
+ end
12
+ end
13
+ end