hamlit 1.7.2 → 2.0.1

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 (283) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -3
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +25 -37
  5. data/CHANGELOG.md +18 -0
  6. data/Gemfile +16 -0
  7. data/LICENSE.txt +23 -2
  8. data/README.md +106 -48
  9. data/REFERENCE.md +222 -0
  10. data/Rakefile +77 -19
  11. data/benchmark/boolean_attribute.haml +6 -0
  12. data/benchmark/class_attribute.haml +5 -0
  13. data/benchmark/common_attribute.haml +3 -0
  14. data/benchmark/data_attribute.haml +4 -0
  15. data/benchmark/dynamic_attributes/boolean_attribute.haml +4 -0
  16. data/benchmark/dynamic_attributes/class_attribute.haml +4 -0
  17. data/benchmark/dynamic_attributes/common_attribute.haml +2 -0
  18. data/benchmark/dynamic_attributes/data_attribute.haml +2 -0
  19. data/benchmark/dynamic_attributes/id_attribute.haml +2 -0
  20. data/benchmark/etc/attribute_builder.haml +5 -0
  21. data/benchmark/etc/real_sample.haml +888 -0
  22. data/benchmark/etc/real_sample.rb +11 -0
  23. data/benchmark/etc/static_analyzer.haml +1 -0
  24. data/benchmark/etc/tags.haml +3 -0
  25. data/benchmark/ext/build_data.rb +15 -0
  26. data/benchmark/ext/build_id.rb +13 -0
  27. data/benchmark/id_attribute.haml +3 -0
  28. data/benchmark/plain.haml +4 -0
  29. data/benchmark/script.haml +4 -0
  30. data/benchmark/slim/LICENSE +21 -0
  31. data/{benchmarks → benchmark/slim}/context.rb +2 -4
  32. data/benchmark/slim/run-benchmarks.rb +94 -0
  33. data/{benchmarks → benchmark/slim}/view.erb +3 -3
  34. data/{benchmarks → benchmark/slim}/view.haml +0 -0
  35. data/{benchmarks/view.escaped.slim → benchmark/slim/view.slim} +1 -1
  36. data/benchmark/string_interpolation.haml +2 -0
  37. data/benchmark/utils/benchmark_ips_extension.rb +43 -0
  38. data/bin/bench +85 -0
  39. data/bin/clone +14 -0
  40. data/bin/console +11 -0
  41. data/bin/lineprof +48 -0
  42. data/bin/ruby +3 -0
  43. data/bin/setup +7 -0
  44. data/bin/stackprof +27 -0
  45. data/{test → bin/test} +6 -10
  46. data/{bin → exe}/hamlit +0 -0
  47. data/ext/hamlit/extconf.rb +14 -0
  48. data/ext/hamlit/hamlit.c +512 -0
  49. data/ext/hamlit/houdini/.gitignore +3 -0
  50. data/ext/hamlit/houdini/COPYING +7 -0
  51. data/ext/hamlit/houdini/Makefile +79 -0
  52. data/ext/hamlit/houdini/README.md +59 -0
  53. data/ext/hamlit/houdini/buffer.c +249 -0
  54. data/ext/hamlit/houdini/buffer.h +113 -0
  55. data/ext/hamlit/houdini/houdini.h +46 -0
  56. data/ext/hamlit/houdini/houdini_href_e.c +115 -0
  57. data/ext/hamlit/houdini/houdini_html_e.c +90 -0
  58. data/ext/hamlit/houdini/houdini_html_u.c +122 -0
  59. data/ext/hamlit/houdini/houdini_js_e.c +90 -0
  60. data/ext/hamlit/houdini/houdini_js_u.c +60 -0
  61. data/ext/hamlit/houdini/houdini_uri_e.c +107 -0
  62. data/ext/hamlit/houdini/houdini_uri_u.c +68 -0
  63. data/ext/hamlit/houdini/houdini_xml_e.c +136 -0
  64. data/ext/hamlit/houdini/html_unescape.gperf +258 -0
  65. data/ext/hamlit/houdini/html_unescape.h +754 -0
  66. data/ext/hamlit/houdini/tools/build_table.py +13 -0
  67. data/ext/hamlit/houdini/tools/build_tables.c +51 -0
  68. data/ext/hamlit/houdini/tools/wikipedia_table.txt +2025 -0
  69. data/hamlit.gemspec +30 -31
  70. data/lib/hamlit.rb +3 -1
  71. data/lib/hamlit/attribute_builder.rb +12 -0
  72. data/lib/hamlit/cli.rb +44 -43
  73. data/lib/hamlit/compiler.rb +92 -16
  74. data/lib/hamlit/compiler/attribute_compiler.rb +148 -0
  75. data/lib/hamlit/compiler/children_compiler.rb +111 -0
  76. data/lib/hamlit/compiler/comment_compiler.rb +36 -0
  77. data/lib/hamlit/compiler/doctype_compiler.rb +45 -0
  78. data/lib/hamlit/compiler/script_compiler.rb +97 -0
  79. data/lib/hamlit/compiler/silent_script_compiler.rb +24 -0
  80. data/lib/hamlit/compiler/tag_compiler.rb +69 -0
  81. data/lib/hamlit/engine.rb +12 -7
  82. data/lib/hamlit/error.rb +14 -0
  83. data/lib/hamlit/escapable.rb +12 -0
  84. data/lib/hamlit/filters.rb +65 -0
  85. data/lib/hamlit/filters/base.rb +4 -62
  86. data/lib/hamlit/filters/coffee.rb +9 -7
  87. data/lib/hamlit/filters/css.rb +25 -8
  88. data/lib/hamlit/filters/erb.rb +4 -6
  89. data/lib/hamlit/filters/escaped.rb +11 -9
  90. data/lib/hamlit/filters/javascript.rb +25 -8
  91. data/lib/hamlit/filters/less.rb +9 -7
  92. data/lib/hamlit/filters/markdown.rb +5 -6
  93. data/lib/hamlit/filters/plain.rb +11 -15
  94. data/lib/hamlit/filters/preserve.rb +15 -5
  95. data/lib/hamlit/filters/ruby.rb +3 -5
  96. data/lib/hamlit/filters/sass.rb +9 -7
  97. data/lib/hamlit/filters/scss.rb +9 -7
  98. data/lib/hamlit/filters/text_base.rb +24 -0
  99. data/lib/hamlit/filters/tilt_base.rb +47 -0
  100. data/lib/hamlit/hash_parser.rb +107 -0
  101. data/lib/hamlit/html.rb +9 -6
  102. data/lib/hamlit/identity.rb +12 -0
  103. data/lib/hamlit/object_ref.rb +29 -0
  104. data/lib/hamlit/parser.rb +25 -142
  105. data/lib/hamlit/parser/MIT-LICENSE +20 -0
  106. data/lib/hamlit/parser/README.md +28 -0
  107. data/lib/hamlit/parser/haml_buffer.rb +348 -0
  108. data/lib/hamlit/parser/haml_compiler.rb +553 -0
  109. data/lib/hamlit/parser/haml_error.rb +61 -0
  110. data/lib/hamlit/parser/haml_helpers.rb +727 -0
  111. data/lib/hamlit/parser/haml_options.rb +286 -0
  112. data/lib/hamlit/parser/haml_parser.rb +801 -0
  113. data/lib/hamlit/parser/haml_util.rb +283 -0
  114. data/lib/hamlit/parser/haml_xss_mods.rb +109 -0
  115. data/lib/hamlit/{helpers.rb → rails_helpers.rb} +2 -7
  116. data/lib/hamlit/rails_template.rb +30 -0
  117. data/lib/hamlit/railtie.rb +1 -12
  118. data/lib/hamlit/ruby_expression.rb +31 -0
  119. data/lib/hamlit/static_analyzer.rb +49 -0
  120. data/lib/hamlit/string_interpolation.rb +69 -0
  121. data/lib/hamlit/template.rb +8 -0
  122. data/lib/hamlit/utils.rb +9 -0
  123. data/lib/hamlit/version.rb +1 -1
  124. metadata +116 -324
  125. data/.rspec +0 -2
  126. data/benchmarks/benchmark.rb +0 -110
  127. data/benchmarks/view.slim +0 -17
  128. data/doc/README.md +0 -19
  129. data/doc/engine/indent.md +0 -48
  130. data/doc/engine/new_attribute.md +0 -77
  131. data/doc/engine/old_attributes.md +0 -198
  132. data/doc/engine/silent_script.md +0 -97
  133. data/doc/engine/tag.md +0 -48
  134. data/doc/engine/text.md +0 -64
  135. data/doc/faml/README.md +0 -16
  136. data/doc/faml/engine/indent.md +0 -48
  137. data/doc/faml/engine/old_attributes.md +0 -111
  138. data/doc/faml/engine/silent_script.md +0 -97
  139. data/doc/faml/engine/text.md +0 -59
  140. data/doc/faml/filters/erb.md +0 -24
  141. data/doc/faml/filters/javascript.md +0 -27
  142. data/doc/faml/filters/less.md +0 -57
  143. data/doc/faml/filters/plain.md +0 -25
  144. data/doc/filters/erb.md +0 -31
  145. data/doc/filters/javascript.md +0 -83
  146. data/doc/filters/less.md +0 -57
  147. data/doc/filters/markdown.md +0 -31
  148. data/doc/filters/plain.md +0 -25
  149. data/doc/haml/README.md +0 -15
  150. data/doc/haml/engine/new_attribute.md +0 -77
  151. data/doc/haml/engine/old_attributes.md +0 -142
  152. data/doc/haml/engine/tag.md +0 -48
  153. data/doc/haml/engine/text.md +0 -29
  154. data/doc/haml/filters/erb.md +0 -26
  155. data/doc/haml/filters/javascript.md +0 -76
  156. data/doc/haml/filters/markdown.md +0 -31
  157. data/lib/hamlit/attribute.rb +0 -78
  158. data/lib/hamlit/compilers/attributes.rb +0 -108
  159. data/lib/hamlit/compilers/comment.rb +0 -13
  160. data/lib/hamlit/compilers/doctype.rb +0 -39
  161. data/lib/hamlit/compilers/filter.rb +0 -53
  162. data/lib/hamlit/compilers/new_attribute.rb +0 -115
  163. data/lib/hamlit/compilers/old_attribute.rb +0 -241
  164. data/lib/hamlit/compilers/runtime_attribute.rb +0 -58
  165. data/lib/hamlit/compilers/script.rb +0 -31
  166. data/lib/hamlit/compilers/strip.rb +0 -19
  167. data/lib/hamlit/compilers/text.rb +0 -111
  168. data/lib/hamlit/concerns/attribute_builder.rb +0 -22
  169. data/lib/hamlit/concerns/balanceable.rb +0 -68
  170. data/lib/hamlit/concerns/deprecation.rb +0 -20
  171. data/lib/hamlit/concerns/error.rb +0 -31
  172. data/lib/hamlit/concerns/escapable.rb +0 -17
  173. data/lib/hamlit/concerns/included.rb +0 -28
  174. data/lib/hamlit/concerns/indentable.rb +0 -117
  175. data/lib/hamlit/concerns/lexable.rb +0 -32
  176. data/lib/hamlit/concerns/line_reader.rb +0 -62
  177. data/lib/hamlit/concerns/registerable.rb +0 -24
  178. data/lib/hamlit/concerns/string_interpolation.rb +0 -48
  179. data/lib/hamlit/concerns/whitespace.rb +0 -91
  180. data/lib/hamlit/filters/tilt.rb +0 -41
  181. data/lib/hamlit/parsers/attribute.rb +0 -71
  182. data/lib/hamlit/parsers/comment.rb +0 -30
  183. data/lib/hamlit/parsers/doctype.rb +0 -18
  184. data/lib/hamlit/parsers/filter.rb +0 -18
  185. data/lib/hamlit/parsers/multiline.rb +0 -58
  186. data/lib/hamlit/parsers/script.rb +0 -126
  187. data/lib/hamlit/parsers/tag.rb +0 -83
  188. data/lib/hamlit/parsers/text.rb +0 -28
  189. data/lib/hamlit/temple.rb +0 -9
  190. data/release +0 -6
  191. data/spec/Rakefile +0 -72
  192. data/spec/hamlit/engine/comment_spec.rb +0 -56
  193. data/spec/hamlit/engine/doctype_spec.rb +0 -19
  194. data/spec/hamlit/engine/error_spec.rb +0 -135
  195. data/spec/hamlit/engine/indent_spec.rb +0 -42
  196. data/spec/hamlit/engine/multiline_spec.rb +0 -44
  197. data/spec/hamlit/engine/new_attribute_spec.rb +0 -110
  198. data/spec/hamlit/engine/old_attributes_spec.rb +0 -404
  199. data/spec/hamlit/engine/script_spec.rb +0 -116
  200. data/spec/hamlit/engine/silent_script_spec.rb +0 -213
  201. data/spec/hamlit/engine/tag_spec.rb +0 -295
  202. data/spec/hamlit/engine/text_spec.rb +0 -239
  203. data/spec/hamlit/engine_spec.rb +0 -58
  204. data/spec/hamlit/filters/coffee_spec.rb +0 -60
  205. data/spec/hamlit/filters/css_spec.rb +0 -33
  206. data/spec/hamlit/filters/erb_spec.rb +0 -16
  207. data/spec/hamlit/filters/javascript_spec.rb +0 -82
  208. data/spec/hamlit/filters/less_spec.rb +0 -37
  209. data/spec/hamlit/filters/markdown_spec.rb +0 -30
  210. data/spec/hamlit/filters/plain_spec.rb +0 -15
  211. data/spec/hamlit/filters/ruby_spec.rb +0 -24
  212. data/spec/hamlit/filters/sass_spec.rb +0 -33
  213. data/spec/hamlit/filters/scss_spec.rb +0 -37
  214. data/spec/hamlit/haml_spec.rb +0 -910
  215. data/spec/rails/.gitignore +0 -18
  216. data/spec/rails/.rspec +0 -2
  217. data/spec/rails/Gemfile +0 -19
  218. data/spec/rails/README.rdoc +0 -28
  219. data/spec/rails/Rakefile +0 -6
  220. data/spec/rails/app/assets/images/.keep +0 -0
  221. data/spec/rails/app/assets/javascripts/application.js +0 -15
  222. data/spec/rails/app/assets/stylesheets/application.css +0 -15
  223. data/spec/rails/app/controllers/application_controller.rb +0 -8
  224. data/spec/rails/app/controllers/concerns/.keep +0 -0
  225. data/spec/rails/app/controllers/users_controller.rb +0 -23
  226. data/spec/rails/app/helpers/application_helper.rb +0 -2
  227. data/spec/rails/app/mailers/.keep +0 -0
  228. data/spec/rails/app/models/.keep +0 -0
  229. data/spec/rails/app/models/concerns/.keep +0 -0
  230. data/spec/rails/app/views/application/index.html.haml +0 -18
  231. data/spec/rails/app/views/layouts/application.html.haml +0 -12
  232. data/spec/rails/app/views/users/capture.html.haml +0 -5
  233. data/spec/rails/app/views/users/capture_haml.html.haml +0 -5
  234. data/spec/rails/app/views/users/form.html.haml +0 -2
  235. data/spec/rails/app/views/users/helpers.html.haml +0 -10
  236. data/spec/rails/app/views/users/index.html.haml +0 -9
  237. data/spec/rails/app/views/users/inline.html.haml +0 -6
  238. data/spec/rails/app/views/users/old_attributes.html.haml +0 -5
  239. data/spec/rails/app/views/users/safe_buffer.html.haml +0 -4
  240. data/spec/rails/app/views/users/whitespace.html.haml +0 -4
  241. data/spec/rails/bin/bundle +0 -3
  242. data/spec/rails/bin/rails +0 -8
  243. data/spec/rails/bin/rake +0 -8
  244. data/spec/rails/bin/setup +0 -29
  245. data/spec/rails/bin/spring +0 -15
  246. data/spec/rails/config.ru +0 -4
  247. data/spec/rails/config/application.rb +0 -34
  248. data/spec/rails/config/boot.rb +0 -3
  249. data/spec/rails/config/database.yml +0 -25
  250. data/spec/rails/config/environment.rb +0 -5
  251. data/spec/rails/config/environments/development.rb +0 -41
  252. data/spec/rails/config/environments/production.rb +0 -79
  253. data/spec/rails/config/environments/test.rb +0 -42
  254. data/spec/rails/config/initializers/assets.rb +0 -11
  255. data/spec/rails/config/initializers/backtrace_silencers.rb +0 -7
  256. data/spec/rails/config/initializers/cookies_serializer.rb +0 -3
  257. data/spec/rails/config/initializers/filter_parameter_logging.rb +0 -4
  258. data/spec/rails/config/initializers/inflections.rb +0 -16
  259. data/spec/rails/config/initializers/mime_types.rb +0 -4
  260. data/spec/rails/config/initializers/session_store.rb +0 -3
  261. data/spec/rails/config/initializers/wrap_parameters.rb +0 -14
  262. data/spec/rails/config/locales/en.yml +0 -24
  263. data/spec/rails/config/routes.rb +0 -16
  264. data/spec/rails/config/secrets.yml +0 -22
  265. data/spec/rails/db/schema.rb +0 -16
  266. data/spec/rails/db/seeds.rb +0 -7
  267. data/spec/rails/lib/assets/.keep +0 -0
  268. data/spec/rails/lib/tasks/.keep +0 -0
  269. data/spec/rails/log/.keep +0 -0
  270. data/spec/rails/public/404.html +0 -67
  271. data/spec/rails/public/422.html +0 -67
  272. data/spec/rails/public/500.html +0 -66
  273. data/spec/rails/public/favicon.ico +0 -0
  274. data/spec/rails/public/robots.txt +0 -5
  275. data/spec/rails/spec/hamlit_spec.rb +0 -123
  276. data/spec/rails/spec/rails_helper.rb +0 -56
  277. data/spec/rails/spec/spec_helper.rb +0 -91
  278. data/spec/rails/vendor/assets/javascripts/.keep +0 -0
  279. data/spec/rails/vendor/assets/stylesheets/.keep +0 -0
  280. data/spec/spec_helper.rb +0 -36
  281. data/spec/spec_helper/document_generator.rb +0 -93
  282. data/spec/spec_helper/render_helper.rb +0 -120
  283. data/spec/spec_helper/test_case.rb +0 -55
@@ -0,0 +1,111 @@
1
+ module Hamlit
2
+ class Compiler
3
+ class ChildrenCompiler
4
+ def initialize
5
+ @lineno = 1
6
+ end
7
+
8
+ def compile(node, &block)
9
+ temple = [:multi]
10
+ return temple if node.children.empty?
11
+
12
+ temple << :whitespace if prepend_whitespace?(node)
13
+ node.children.each do |n|
14
+ rstrip_whitespace!(temple) if nuke_prev_whitespace?(n)
15
+ insert_newlines!(temple, n)
16
+ temple << yield(n)
17
+ temple << :whitespace if insert_whitespace?(n)
18
+ end
19
+ rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
20
+ confirm_whitespace(temple)
21
+ end
22
+
23
+ private
24
+
25
+ def insert_newlines!(temple, node)
26
+ (node.line - @lineno).times do
27
+ temple << [:newline]
28
+ end
29
+ @lineno = node.line
30
+
31
+ case node.type
32
+ when :script, :silent_script
33
+ @lineno += 1
34
+ when :filter
35
+ @lineno += (node.value[:text] || '').split("\n").size
36
+ when :tag
37
+ node.value[:attributes_hashes].each do |attribute_hash|
38
+ @lineno += attribute_hash.count("\n")
39
+ end
40
+ @lineno += 1 if node.children.empty? && node.value[:parse]
41
+ end
42
+ end
43
+
44
+ def confirm_whitespace(temple)
45
+ temple.map do |exp|
46
+ case exp
47
+ when :whitespace
48
+ [:static, "\n"]
49
+ else
50
+ exp
51
+ end
52
+ end
53
+ end
54
+
55
+ def prepend_whitespace?(node)
56
+ return false unless %i[comment tag].include?(node.type)
57
+ !nuke_inner_whitespace?(node)
58
+ end
59
+
60
+ def nuke_inner_whitespace?(node)
61
+ case
62
+ when node.type == :tag
63
+ node.value[:nuke_inner_whitespace]
64
+ when node.parent.nil?
65
+ false
66
+ else
67
+ nuke_inner_whitespace?(node.parent)
68
+ end
69
+ end
70
+
71
+ def nuke_prev_whitespace?(node)
72
+ case node.type
73
+ when :tag
74
+ node.value[:nuke_outer_whitespace]
75
+ when :silent_script
76
+ !node.children.empty? && nuke_prev_whitespace?(node.children.first)
77
+ else
78
+ false
79
+ end
80
+ end
81
+
82
+ def nuke_outer_whitespace?(node)
83
+ return false if node.type != :tag
84
+ node.value[:nuke_outer_whitespace]
85
+ end
86
+
87
+ def rstrip_whitespace!(temple)
88
+ if temple[-1] == :whitespace
89
+ temple.delete_at(-1)
90
+ end
91
+ end
92
+
93
+ def insert_whitespace?(node)
94
+ return false if nuke_outer_whitespace?(node)
95
+
96
+ case node.type
97
+ when :doctype
98
+ node.value[:type] != 'xml'
99
+ when :comment, :plain, :tag
100
+ true
101
+ when :script
102
+ node.children.empty? && !nuke_inner_whitespace?(node)
103
+ when :filter
104
+ !%w[ruby].freeze.include?(node.value[:name])
105
+ else
106
+ false
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,36 @@
1
+ module Hamlit
2
+ class Compiler
3
+ class CommentCompiler
4
+ def compile(node, &block)
5
+ if node.value[:conditional]
6
+ compile_conditional_comment(node, &block)
7
+ else
8
+ compile_html_comment(node, &block)
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def compile_html_comment(node, &block)
15
+ if node.children.empty?
16
+ [:html, :comment, [:static, " #{node.value[:text]} "]]
17
+ else
18
+ [:html, :comment, yield(node)]
19
+ end
20
+ end
21
+
22
+ def compile_conditional_comment(node, &block)
23
+ condition = node.value[:conditional]
24
+ if node.value[:conditional] =~ /\A\[(\[*[^\[\]]+\]*)\]/
25
+ condition = $1
26
+ end
27
+
28
+ if node.children.empty?
29
+ [:html, :condcomment, condition, [:static, " #{node.value[:text]} "]]
30
+ else
31
+ [:html, :condcomment, condition, yield(node)]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,45 @@
1
+ module Hamlit
2
+ class Compiler
3
+ class DoctypeCompiler
4
+ def initialize(options = {})
5
+ @format = options[:format]
6
+ end
7
+
8
+ def compile(node)
9
+ case node.value[:type]
10
+ when 'xml'
11
+ xml_doctype
12
+ when ''
13
+ html_doctype(node)
14
+ else
15
+ [:html, :doctype, node.value[:type]]
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def html_doctype(node)
22
+ version = node.value[:version] || :transitional
23
+ case @format
24
+ when :xhtml
25
+ [:html, :doctype, version]
26
+ when :html4
27
+ [:html, :doctype, :transitional]
28
+ when :html5
29
+ [:html, :doctype, :html]
30
+ else
31
+ [:html, :doctype, @format]
32
+ end
33
+ end
34
+
35
+ def xml_doctype
36
+ case @format
37
+ when :xhtml
38
+ [:static, "<?xml version='1.0' encoding='utf-8' ?>\n"]
39
+ else
40
+ [:multi]
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,97 @@
1
+ require 'hamlit/ruby_expression'
2
+ require 'hamlit/static_analyzer'
3
+ require 'hamlit/string_interpolation'
4
+
5
+ module Hamlit
6
+ class Compiler
7
+ class ScriptCompiler
8
+ def initialize(identity)
9
+ @identity = identity
10
+ end
11
+
12
+ def compile(node, &block)
13
+ case
14
+ when node.children.empty? && RubyExpression.string_literal?(node.value[:text])
15
+ string_compile(node)
16
+ when node.children.empty? && StaticAnalyzer.static?(node.value[:text])
17
+ static_compile(node)
18
+ else
19
+ dynamic_compile(node, &block)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ # String-interpolated plain text must be compiled with this method
26
+ def string_compile(node)
27
+ temple = [:multi]
28
+ StringInterpolation.compile(node.value[:text]).each do |type, value|
29
+ case type
30
+ when :static
31
+ value = Temple::Utils.escape_html(value) if node.value[:escape_html]
32
+ temple << [:static, value]
33
+ when :dynamic
34
+ if Hamlit::StaticAnalyzer.static?(value)
35
+ value = eval(value).to_s
36
+ value = Temple::Utils.escape_html(value) if node.value[:escape_html] || node.value[:escape_interpolation]
37
+ temple << [:static, value]
38
+ else
39
+ temple << [:escape, node.value[:escape_html] || node.value[:escape_interpolation], [:dynamic, value]]
40
+ end
41
+ end
42
+ end
43
+ temple << [:newline]
44
+ end
45
+
46
+ def static_compile(node)
47
+ str = eval("(#{node.value[:text]}).to_s")
48
+ if node.value[:escape_html]
49
+ str = Temple::Utils.escape_html(str)
50
+ elsif node.value[:preserve]
51
+ str = ::Hamlit::HamlHelpers.find_and_preserve(str, %w(textarea pre code))
52
+ end
53
+ [:multi, [:static, str], [:newline]]
54
+ end
55
+
56
+ def dynamic_compile(node, &block)
57
+ var = @identity.generate
58
+ temple = compile_script_assign(var, node, &block)
59
+ temple << compile_script_result(var, node)
60
+ end
61
+
62
+ def compile_script_assign(var, node, &block)
63
+ if node.children.empty?
64
+ [:multi,
65
+ [:code, "#{var} = (#{node.value[:text]}"],
66
+ [:newline],
67
+ [:code, ')'.freeze],
68
+ ]
69
+ else
70
+ [:multi,
71
+ [:code, "#{var} = #{node.value[:text]}"],
72
+ [:newline],
73
+ yield(node),
74
+ [:code, 'end'.freeze],
75
+ ]
76
+ end
77
+ end
78
+
79
+ def compile_script_result(result, node)
80
+ if !node.value[:escape_html] && node.value[:preserve]
81
+ result = find_and_preserve(result)
82
+ else
83
+ result = '(' << result << ').to_s'.freeze
84
+ end
85
+ [:escape, node.value[:escape_html], [:dynamic, result]]
86
+ end
87
+
88
+ def find_and_preserve(code)
89
+ %Q[::Hamlit::HamlHelpers.find_and_preserve(#{code}, %w(textarea pre code))]
90
+ end
91
+
92
+ def escape_html(temple)
93
+ [:escape, true, temple]
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,24 @@
1
+ module Hamlit
2
+ class Compiler
3
+ class SilentScriptCompiler
4
+ def compile(node, &block)
5
+ if node.children.empty?
6
+ [:multi, [:code, node.value[:text]], [:newline]]
7
+ else
8
+ compile_with_children(node, &block)
9
+ end
10
+ end
11
+
12
+ private
13
+
14
+ def compile_with_children(node, &block)
15
+ temple = [:multi]
16
+ temple << [:code, node.value[:text]]
17
+ temple << [:newline]
18
+ temple << yield(node)
19
+ temple << [:code, 'end']
20
+ temple
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,69 @@
1
+ require 'hamlit/parser/haml_util'
2
+ require 'hamlit/compiler/attribute_compiler'
3
+ require 'hamlit/string_interpolation'
4
+
5
+ module Hamlit
6
+ class Compiler
7
+ class TagCompiler
8
+ def initialize(identity, options)
9
+ @autoclose = options[:autoclose]
10
+ @identity = identity
11
+ @attribute_compiler = AttributeCompiler.new(identity, options)
12
+ end
13
+
14
+ def compile(node, &block)
15
+ attrs = @attribute_compiler.compile(node)
16
+ contents = compile_contents(node, &block)
17
+ [:html, :tag, node.value[:name], attrs, contents]
18
+ end
19
+
20
+ private
21
+
22
+ def compile_contents(node, &block)
23
+ case
24
+ when !node.children.empty?
25
+ yield(node)
26
+ when node.value[:value].nil? && self_closing?(node)
27
+ nil
28
+ when node.value[:parse]
29
+ return compile_string(node) if RubyExpression.string_literal?(node.value[:value])
30
+
31
+ var = @identity.generate
32
+ [:multi,
33
+ [:code, "#{var} = (#{node.value[:value]}"],
34
+ [:newline],
35
+ [:code, ')'.freeze],
36
+ [:escape, node.value[:escape_html], [:dynamic, var]]
37
+ ]
38
+ else
39
+ [:static, node.value[:value]]
40
+ end
41
+ end
42
+
43
+ def compile_string(node)
44
+ temple = [:multi]
45
+ StringInterpolation.compile(node.value[:value]).each do |type, value|
46
+ case type
47
+ when :static
48
+ value = Temple::Utils.escape_html(value) if node.value[:escape_html]
49
+ temple << [:static, value]
50
+ when :dynamic
51
+ if Hamlit::StaticAnalyzer.static?(value)
52
+ value = eval(value).to_s
53
+ value = Temple::Utils.escape_html(value) if node.value[:escape_html] || node.value[:escape_interpolation]
54
+ temple << [:static, value]
55
+ else
56
+ temple << [:escape, node.value[:escape_html] || node.value[:escape_interpolation], [:dynamic, value]]
57
+ end
58
+ end
59
+ end
60
+ temple << [:newline]
61
+ end
62
+
63
+ def self_closing?(node)
64
+ return true if @autoclose.include?(node.value[:name])
65
+ node.value[:self_closing]
66
+ end
67
+ end
68
+ end
69
+ end
data/lib/hamlit/engine.rb CHANGED
@@ -1,22 +1,27 @@
1
1
  require 'temple'
2
+ require 'hamlit/parser'
2
3
  require 'hamlit/compiler'
4
+ require 'hamlit/escapable'
3
5
  require 'hamlit/html'
4
- require 'hamlit/parser'
5
- require 'hamlit/temple'
6
6
 
7
7
  module Hamlit
8
8
  class Engine < Temple::Engine
9
9
  define_options(
10
- generator: Temple::Generators::ArrayBuffer,
11
- format: :html,
12
- attr_quote: "'",
13
- escape_html: true,
10
+ generator: Temple::Generators::ArrayBuffer,
11
+ format: :html,
12
+ attr_quote: "'",
13
+ escape_html: true,
14
+ escape_attrs: true,
15
+ autoclose: %w(area base basefont br col command embed frame
16
+ hr img input isindex keygen link menuitem meta
17
+ param source track wbr),
18
+ filename: "",
14
19
  )
15
20
 
16
21
  use Parser
17
22
  use Compiler
18
23
  use HTML
19
- filter :Escapable
24
+ use Escapable
20
25
  filter :ControlFlow
21
26
  filter :MultiFlattener
22
27
  filter :StaticMerger
@@ -0,0 +1,14 @@
1
+ module Hamlit
2
+ class Error < StandardError
3
+ attr_reader :line
4
+
5
+ def initialize(message = nil, line = nil)
6
+ super(message)
7
+ @line = line
8
+ end
9
+ end
10
+
11
+ class SyntaxError < Error; end
12
+ class InternalError < Error; end
13
+ class FilterNotFound < Error; end
14
+ end
@@ -0,0 +1,12 @@
1
+ require 'hamlit/utils'
2
+
3
+ module Hamlit
4
+ class Escapable < Temple::Filters::Escapable
5
+ def initialize(opts = {})
6
+ super
7
+ @escape_code = options[:escape_code] ||
8
+ "::Hamlit::Utils.escape_html#{options[:use_html_safe] ? '_safe' : ''}((%s))"
9
+ @escaper = eval("proc {|v| #{@escape_code % 'v'} }")
10
+ end
11
+ end
12
+ end