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.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.travis.yml +34 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +23 -0
- data/README.md +45 -0
- data/Rakefile +34 -0
- data/benchmarks/benchmark.rb +94 -0
- data/benchmarks/context.rb +13 -0
- data/benchmarks/view.erb +23 -0
- data/benchmarks/view.haml +18 -0
- data/benchmarks/view.rbhtml +23 -0
- data/benchmarks/view.slim +17 -0
- data/bin/hamlit +6 -0
- data/hamlit.gemspec +40 -0
- data/lib/hamlit/attribute.rb +31 -0
- data/lib/hamlit/cli.rb +89 -0
- data/lib/hamlit/compiler.rb +24 -0
- data/lib/hamlit/compilers/attributes.rb +78 -0
- data/lib/hamlit/compilers/comment.rb +13 -0
- data/lib/hamlit/compilers/doctype.rb +39 -0
- data/lib/hamlit/compilers/dynamic.rb +9 -0
- data/lib/hamlit/compilers/filter.rb +53 -0
- data/lib/hamlit/compilers/new_attribute.rb +107 -0
- data/lib/hamlit/compilers/old_attribute.rb +147 -0
- data/lib/hamlit/compilers/preserve.rb +10 -0
- data/lib/hamlit/compilers/script.rb +31 -0
- data/lib/hamlit/compilers/strip.rb +30 -0
- data/lib/hamlit/compilers/text.rb +15 -0
- data/lib/hamlit/concerns/attribute_builder.rb +21 -0
- data/lib/hamlit/concerns/balanceable.rb +59 -0
- data/lib/hamlit/concerns/deprecation.rb +20 -0
- data/lib/hamlit/concerns/error.rb +27 -0
- data/lib/hamlit/concerns/escapable.rb +17 -0
- data/lib/hamlit/concerns/included.rb +28 -0
- data/lib/hamlit/concerns/indentable.rb +53 -0
- data/lib/hamlit/concerns/line_reader.rb +60 -0
- data/lib/hamlit/concerns/registerable.rb +24 -0
- data/lib/hamlit/concerns/ripperable.rb +20 -0
- data/lib/hamlit/concerns/string_interpolation.rb +48 -0
- data/lib/hamlit/engine.rb +42 -0
- data/lib/hamlit/filters/base.rb +44 -0
- data/lib/hamlit/filters/coffee.rb +12 -0
- data/lib/hamlit/filters/css.rb +34 -0
- data/lib/hamlit/filters/erb.rb +11 -0
- data/lib/hamlit/filters/escaped.rb +19 -0
- data/lib/hamlit/filters/javascript.rb +34 -0
- data/lib/hamlit/filters/less.rb +12 -0
- data/lib/hamlit/filters/markdown.rb +11 -0
- data/lib/hamlit/filters/plain.rb +21 -0
- data/lib/hamlit/filters/preserve.rb +11 -0
- data/lib/hamlit/filters/ruby.rb +11 -0
- data/lib/hamlit/filters/sass.rb +12 -0
- data/lib/hamlit/filters/scss.rb +12 -0
- data/lib/hamlit/filters/tilt.rb +41 -0
- data/lib/hamlit/helpers.rb +38 -0
- data/lib/hamlit/html/pretty.rb +49 -0
- data/lib/hamlit/html/ugly.rb +10 -0
- data/lib/hamlit/parser.rb +123 -0
- data/lib/hamlit/parsers/attribute.rb +52 -0
- data/lib/hamlit/parsers/comment.rb +27 -0
- data/lib/hamlit/parsers/doctype.rb +18 -0
- data/lib/hamlit/parsers/filter.rb +18 -0
- data/lib/hamlit/parsers/multiline.rb +54 -0
- data/lib/hamlit/parsers/script.rb +93 -0
- data/lib/hamlit/parsers/tag.rb +71 -0
- data/lib/hamlit/parsers/text.rb +11 -0
- data/lib/hamlit/parsers/whitespace.rb +38 -0
- data/lib/hamlit/railtie.rb +21 -0
- data/lib/hamlit/template.rb +9 -0
- data/lib/hamlit/version.rb +3 -0
- data/lib/hamlit.rb +8 -0
- data/spec/Rakefile +79 -0
- data/spec/hamlit/compilers/script_spec.rb +46 -0
- data/spec/hamlit/engine/comment_spec.rb +29 -0
- data/spec/hamlit/engine/doctype_spec.rb +19 -0
- data/spec/hamlit/engine/error_spec.rb +47 -0
- data/spec/hamlit/engine/multiline_spec.rb +44 -0
- data/spec/hamlit/engine/new_attribute_spec.rb +19 -0
- data/spec/hamlit/engine/old_attributes_spec.rb +85 -0
- data/spec/hamlit/engine/preservation_spec.rb +11 -0
- data/spec/hamlit/engine/script_spec.rb +87 -0
- data/spec/hamlit/engine/silent_script_spec.rb +135 -0
- data/spec/hamlit/engine/tag_spec.rb +210 -0
- data/spec/hamlit/engine/text_spec.rb +29 -0
- data/spec/hamlit/engine_spec.rb +20 -0
- data/spec/hamlit/filters/coffee_spec.rb +41 -0
- data/spec/hamlit/filters/css_spec.rb +33 -0
- data/spec/hamlit/filters/erb_spec.rb +16 -0
- data/spec/hamlit/filters/javascript_spec.rb +82 -0
- data/spec/hamlit/filters/less_spec.rb +22 -0
- data/spec/hamlit/filters/markdown_spec.rb +28 -0
- data/spec/hamlit/filters/ruby_spec.rb +24 -0
- data/spec/hamlit/filters/sass_spec.rb +37 -0
- data/spec/hamlit/filters/scss_spec.rb +21 -0
- data/spec/hamlit/ugly_spec.rb +912 -0
- data/spec/rails/.gitignore +17 -0
- data/spec/rails/.rspec +2 -0
- data/spec/rails/Gemfile +19 -0
- data/spec/rails/Gemfile.lock +177 -0
- data/spec/rails/README.rdoc +28 -0
- data/spec/rails/Rakefile +6 -0
- data/spec/rails/app/assets/images/.keep +0 -0
- data/spec/rails/app/assets/javascripts/application.js +15 -0
- data/spec/rails/app/assets/stylesheets/application.css +15 -0
- data/spec/rails/app/controllers/application_controller.rb +8 -0
- data/spec/rails/app/controllers/concerns/.keep +0 -0
- data/spec/rails/app/controllers/users_controller.rb +20 -0
- data/spec/rails/app/helpers/application_helper.rb +2 -0
- data/spec/rails/app/mailers/.keep +0 -0
- data/spec/rails/app/models/.keep +0 -0
- data/spec/rails/app/models/concerns/.keep +0 -0
- data/spec/rails/app/views/application/index.html.haml +15 -0
- data/spec/rails/app/views/layouts/application.html.haml +12 -0
- data/spec/rails/app/views/users/capture.html.haml +5 -0
- data/spec/rails/app/views/users/capture_haml.html.haml +5 -0
- data/spec/rails/app/views/users/form.html.haml +2 -0
- data/spec/rails/app/views/users/helpers.html.haml +1 -0
- data/spec/rails/app/views/users/index.html.haml +9 -0
- data/spec/rails/app/views/users/safe_buffer.html.haml +4 -0
- data/spec/rails/bin/bundle +3 -0
- data/spec/rails/bin/rails +8 -0
- data/spec/rails/bin/rake +8 -0
- data/spec/rails/bin/setup +29 -0
- data/spec/rails/bin/spring +15 -0
- data/spec/rails/config/application.rb +34 -0
- data/spec/rails/config/boot.rb +3 -0
- data/spec/rails/config/database.yml +25 -0
- data/spec/rails/config/environment.rb +5 -0
- data/spec/rails/config/environments/development.rb +41 -0
- data/spec/rails/config/environments/production.rb +79 -0
- data/spec/rails/config/environments/test.rb +42 -0
- data/spec/rails/config/initializers/assets.rb +11 -0
- data/spec/rails/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails/config/initializers/cookies_serializer.rb +3 -0
- data/spec/rails/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/rails/config/initializers/inflections.rb +16 -0
- data/spec/rails/config/initializers/mime_types.rb +4 -0
- data/spec/rails/config/initializers/session_store.rb +3 -0
- data/spec/rails/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails/config/locales/en.yml +23 -0
- data/spec/rails/config/routes.rb +13 -0
- data/spec/rails/config/secrets.yml +22 -0
- data/spec/rails/config.ru +4 -0
- data/spec/rails/db/schema.rb +16 -0
- data/spec/rails/db/seeds.rb +7 -0
- data/spec/rails/lib/assets/.keep +0 -0
- data/spec/rails/lib/tasks/.keep +0 -0
- data/spec/rails/log/.keep +0 -0
- data/spec/rails/public/404.html +67 -0
- data/spec/rails/public/422.html +67 -0
- data/spec/rails/public/500.html +66 -0
- data/spec/rails/public/favicon.ico +0 -0
- data/spec/rails/public/robots.txt +5 -0
- data/spec/rails/spec/hamlit_spec.rb +87 -0
- data/spec/rails/spec/rails_helper.rb +56 -0
- data/spec/rails/spec/spec_helper.rb +91 -0
- data/spec/rails/vendor/assets/javascripts/.keep +0 -0
- data/spec/rails/vendor/assets/stylesheets/.keep +0 -0
- data/spec/spec_helper.rb +48 -0
- metadata +560 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Hamlit
|
|
2
|
+
module Concerns
|
|
3
|
+
module LineReader
|
|
4
|
+
def reset_lines(lines)
|
|
5
|
+
@lines = lines
|
|
6
|
+
@current_lineno = -1
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def current_line
|
|
10
|
+
@lines[@current_lineno]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Return nearest line ignoring empty lines.
|
|
14
|
+
def next_line
|
|
15
|
+
lineno = @current_lineno + 1
|
|
16
|
+
while @lines[lineno] && empty_line?(@lines[lineno])
|
|
17
|
+
lineno += 1
|
|
18
|
+
end
|
|
19
|
+
@lines[lineno]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def empty_line?(line)
|
|
23
|
+
line =~ /\A *\Z/
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def skip_lines
|
|
27
|
+
while next_indent >= @current_indent
|
|
28
|
+
@current_lineno += 1
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def read_lines
|
|
33
|
+
lines = []
|
|
34
|
+
while read_line?
|
|
35
|
+
lines << @lines[@current_lineno + 1]
|
|
36
|
+
@current_lineno += 1
|
|
37
|
+
end
|
|
38
|
+
trim_lines(lines)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def trim_lines(lines)
|
|
44
|
+
size = (lines.first || '').index(/[^\s]/) || 0
|
|
45
|
+
lines.map { |line| line.gsub(/\A {#{size}}/, '') }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def read_line?
|
|
49
|
+
return true if count_indent(next_line, strict: false) >= @current_indent
|
|
50
|
+
|
|
51
|
+
line = @lines[@current_lineno + 1]
|
|
52
|
+
return false unless line
|
|
53
|
+
|
|
54
|
+
# NOTE: preserve filter also requires an empty line
|
|
55
|
+
line.gsub(/ /, '').length == 0
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Hamlit
|
|
2
|
+
class NotFound < StandardError
|
|
3
|
+
def initialize(name)
|
|
4
|
+
super(%Q{Filter "#{name}" is not defined.})
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Concerns
|
|
9
|
+
module Registerable
|
|
10
|
+
def registered
|
|
11
|
+
@registered ||= {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def register(name, compiler)
|
|
15
|
+
registered[name.to_sym] = compiler
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def find(name)
|
|
19
|
+
raise NotFound.new(name) unless registered[name.to_sym]
|
|
20
|
+
registered[name.to_sym]
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'ripper'
|
|
2
|
+
|
|
3
|
+
module Hamlit
|
|
4
|
+
module Concerns
|
|
5
|
+
module Ripperable
|
|
6
|
+
TYPE_POSITION = 1
|
|
7
|
+
|
|
8
|
+
def skip_tokens!(tokens, *types)
|
|
9
|
+
while types.include?(type_of(tokens.first))
|
|
10
|
+
tokens.shift
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def type_of(token)
|
|
15
|
+
return nil unless token
|
|
16
|
+
token[TYPE_POSITION]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Hamlit
|
|
2
|
+
module Concerns
|
|
3
|
+
module StringInterpolation
|
|
4
|
+
def string_literal(str)
|
|
5
|
+
unescape_interpolation(str)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def contains_interpolation?(str)
|
|
9
|
+
/#[\{$@]/ === str
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def unescape_interpolation(str)
|
|
15
|
+
res = ''
|
|
16
|
+
rest = handle_interpolation(str.inspect) do |scan|
|
|
17
|
+
escapes = (scan[2].size - 1) / 2
|
|
18
|
+
res << scan.matched[0...-3 - escapes]
|
|
19
|
+
if escapes % 2 == 1
|
|
20
|
+
res << '#{'
|
|
21
|
+
else
|
|
22
|
+
content = eval('"' + balance(scan, ?{, ?}, 1)[0][0...-1] + '"')
|
|
23
|
+
res << '#{' + content + '}'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
res + rest
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def handle_interpolation(str)
|
|
30
|
+
scan = StringScanner.new(str)
|
|
31
|
+
yield scan while scan.scan(/(.*?)(\\*)\#\{/)
|
|
32
|
+
scan.rest
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def balance(scanner, start, finish, count = 0)
|
|
36
|
+
str = ''
|
|
37
|
+
scanner = StringScanner.new(scanner) unless scanner.is_a? StringScanner
|
|
38
|
+
regexp = Regexp.new("(.*?)[\\#{start.chr}\\#{finish.chr}]", Regexp::MULTILINE)
|
|
39
|
+
while scanner.scan(regexp)
|
|
40
|
+
str << scanner.matched
|
|
41
|
+
count += 1 if scanner.matched[-1] == start
|
|
42
|
+
count -= 1 if scanner.matched[-1] == finish
|
|
43
|
+
return [str.strip, scanner.rest] if count == 0
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'temple'
|
|
2
|
+
require 'hamlit/compiler'
|
|
3
|
+
require 'hamlit/html/pretty'
|
|
4
|
+
require 'hamlit/html/ugly'
|
|
5
|
+
require 'hamlit/parser'
|
|
6
|
+
|
|
7
|
+
module Hamlit
|
|
8
|
+
class Engine < Temple::Engine
|
|
9
|
+
define_options(
|
|
10
|
+
generator: Temple::Generators::ArrayBuffer,
|
|
11
|
+
format: :html,
|
|
12
|
+
attr_quote: "'",
|
|
13
|
+
ugly: true,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
use Parser
|
|
17
|
+
use Compiler
|
|
18
|
+
use :Html, -> { create(html_compiler) }
|
|
19
|
+
filter :Escapable
|
|
20
|
+
filter :ControlFlow
|
|
21
|
+
filter :MultiFlattener
|
|
22
|
+
filter :StaticMerger
|
|
23
|
+
use :Generator, -> { create(options[:generator]) }
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def create(klass)
|
|
28
|
+
valid_options = options.to_hash.select do |key, value|
|
|
29
|
+
klass.options.valid_key?(key)
|
|
30
|
+
end
|
|
31
|
+
klass.new(valid_options)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def html_compiler
|
|
35
|
+
if options[:ugly]
|
|
36
|
+
HTML::Ugly
|
|
37
|
+
else
|
|
38
|
+
HTML::Pretty
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Hamlit
|
|
2
|
+
module Filters
|
|
3
|
+
class Base
|
|
4
|
+
attr_reader :options
|
|
5
|
+
|
|
6
|
+
def self.indent_source(source, indent_width: 0)
|
|
7
|
+
lines = source.split("\n")
|
|
8
|
+
self.new.compile_lines(lines, indent_width: indent_width)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize(options = {})
|
|
12
|
+
@options = options
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def compile(lines)
|
|
16
|
+
raise NotImplementedError
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def compile_lines(lines, indent_width: 0)
|
|
20
|
+
base = (lines.first || '').index(/[^\s]/) || 0
|
|
21
|
+
width = indent_width - base
|
|
22
|
+
width = 0 if width < 0
|
|
23
|
+
|
|
24
|
+
lines = strip_last(lines).map do |line|
|
|
25
|
+
' ' * width + line
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
text = lines.join("\n") + "\n"
|
|
29
|
+
text
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# NOTE: empty line is reserved for preserve filter.
|
|
35
|
+
def strip_last(lines)
|
|
36
|
+
lines = lines.dup
|
|
37
|
+
while lines.last && lines.last.length == 0
|
|
38
|
+
lines.delete_at(-1)
|
|
39
|
+
end
|
|
40
|
+
lines
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'hamlit/filters/base'
|
|
2
|
+
|
|
3
|
+
module Hamlit
|
|
4
|
+
module Filters
|
|
5
|
+
class Css < Base
|
|
6
|
+
def compile(lines)
|
|
7
|
+
return compile_xhtml(lines) if options[:format] == :xhtml
|
|
8
|
+
|
|
9
|
+
compile_html(lines)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def compile_html(lines)
|
|
15
|
+
ast = [:haml, :text, compile_lines(lines, indent_width: 2)]
|
|
16
|
+
ast = [:multi, [:static, "\n"], ast]
|
|
17
|
+
ast = [:html, :tag, 'style', [:html, :attrs], ast]
|
|
18
|
+
ast
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def compile_xhtml(lines)
|
|
22
|
+
attr = [:html, :attr, 'type', [:static, 'text/css']]
|
|
23
|
+
attrs = [:html, :attrs, attr]
|
|
24
|
+
|
|
25
|
+
multi = [:multi, [:static, "\n"]]
|
|
26
|
+
multi << [:static, " /*<![CDATA[*/\n"]
|
|
27
|
+
multi << [:haml, :text, compile_lines(lines, indent_width: 4)]
|
|
28
|
+
multi << [:static, " /*]]>*/\n"]
|
|
29
|
+
|
|
30
|
+
[:html, :tag, 'style', attrs, multi]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'hamlit/filters/base'
|
|
2
|
+
|
|
3
|
+
module Hamlit
|
|
4
|
+
module Filters
|
|
5
|
+
class Escaped < Base
|
|
6
|
+
def compile(lines)
|
|
7
|
+
ast = [:haml, :text, lines.join("\n")]
|
|
8
|
+
ast = [:multi, escape_html(ast)]
|
|
9
|
+
ast
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def escape_html(ast)
|
|
15
|
+
[:escape, true, ast]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'hamlit/filters/base'
|
|
2
|
+
|
|
3
|
+
module Hamlit
|
|
4
|
+
module Filters
|
|
5
|
+
class Javascript < Base
|
|
6
|
+
def compile(lines)
|
|
7
|
+
return compile_xhtml(lines) if options[:format] == :xhtml
|
|
8
|
+
|
|
9
|
+
compile_html(lines)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def compile_html(lines)
|
|
15
|
+
ast = [:haml, :text, compile_lines(lines, indent_width: 2)]
|
|
16
|
+
ast = [:multi, [:static, "\n"], ast]
|
|
17
|
+
ast = [:html, :tag, 'script', [:html, :attrs], ast]
|
|
18
|
+
ast
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def compile_xhtml(lines)
|
|
22
|
+
attr = [:html, :attr, 'type', [:static, 'text/javascript']]
|
|
23
|
+
attrs = [:html, :attrs, attr]
|
|
24
|
+
|
|
25
|
+
multi = [:multi, [:static, "\n"]]
|
|
26
|
+
multi << [:static, " //<![CDATA[\n"]
|
|
27
|
+
multi << [:haml, :text, compile_lines(lines, indent_width: 4)]
|
|
28
|
+
multi << [:static, " //]]>\n"]
|
|
29
|
+
|
|
30
|
+
[:html, :tag, 'script', attrs, multi]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require 'hamlit/filters/base'
|
|
2
|
+
|
|
3
|
+
module Hamlit
|
|
4
|
+
module Filters
|
|
5
|
+
class Plain < Base
|
|
6
|
+
def compile(lines)
|
|
7
|
+
ast = [:multi]
|
|
8
|
+
text = compile_lines(lines)
|
|
9
|
+
text.gsub!(/\n\Z/, '') unless string_interpolated?(text)
|
|
10
|
+
ast << [:haml, :text, text]
|
|
11
|
+
ast
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def string_interpolated?(text)
|
|
17
|
+
text =~ /\#{[^\#{}]*}/
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require 'tilt'
|
|
2
|
+
require 'hamlit/concerns/string_interpolation'
|
|
3
|
+
require 'hamlit/filters/base'
|
|
4
|
+
|
|
5
|
+
module Hamlit
|
|
6
|
+
module Filters
|
|
7
|
+
class Tilt < Filters::Base
|
|
8
|
+
include Concerns::StringInterpolation
|
|
9
|
+
|
|
10
|
+
def self.render(name, source, indent_width: 2)
|
|
11
|
+
result = ::Tilt["t.#{name}"].new { source }.render
|
|
12
|
+
indent_source(result, indent_width: indent_width)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
def compile_with_tilt(name, source, ast, indent_width: 2)
|
|
18
|
+
if contains_interpolation?(source)
|
|
19
|
+
return runtime_compile(name, source, ast, indent_width: indent_width)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
content = [:static, Filters::Tilt.render(name, source, indent_width: indent_width)]
|
|
23
|
+
build_ast(ast, content)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def runtime_compile(name, source, ast, indent_width: 2)
|
|
27
|
+
literal = string_literal(source)
|
|
28
|
+
code = "::Hamlit::Filters::Tilt.render(#{name.inspect}, #{literal}, indent_width: #{indent_width})"
|
|
29
|
+
content = [:dynamic, code]
|
|
30
|
+
build_ast(ast, content)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def build_ast(ast, content)
|
|
34
|
+
return content if ast.empty?
|
|
35
|
+
|
|
36
|
+
content = [:multi, [:static, "\n"], content]
|
|
37
|
+
ast << content
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# This is a module compatible with Haml::Helpers.
|
|
2
|
+
# It is included by ActionView in initializer.
|
|
3
|
+
module Hamlit
|
|
4
|
+
module Helpers
|
|
5
|
+
extend self
|
|
6
|
+
|
|
7
|
+
DEFAULT_PRESERVE_TAGS = %w[textarea pre code].freeze
|
|
8
|
+
|
|
9
|
+
def find_and_preserve(input = nil, tags = DEFAULT_PRESERVE_TAGS, &block)
|
|
10
|
+
return find_and_preserve(capture_haml(&block), input || tags) if block
|
|
11
|
+
|
|
12
|
+
tags = tags.each_with_object('') do |t, s|
|
|
13
|
+
s << '|' unless s.empty?
|
|
14
|
+
s << Regexp.escape(t)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
re = /<(#{tags})([^>]*)>(.*?)(<\/\1>)/im
|
|
18
|
+
input.to_s.gsub(re) do |s|
|
|
19
|
+
s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible
|
|
20
|
+
"<#{$1}#{$2}>#{preserve($3)}</#{$1}>"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def preserve(input = nil, &block)
|
|
25
|
+
return preserve(capture_haml(&block)) if block
|
|
26
|
+
s = input.to_s.chomp("\n")
|
|
27
|
+
s.gsub!(/\n/, '
')
|
|
28
|
+
s.delete!("\r")
|
|
29
|
+
s
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# NOTE: currently Hamlit::Helpers is enabled by default on only
|
|
33
|
+
# Rails environment. Thus you can use capture.
|
|
34
|
+
def capture_haml(*args, &block)
|
|
35
|
+
capture(*args, &block)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'hamlit/concerns/deprecation'
|
|
2
|
+
require 'temple/html/pretty'
|
|
3
|
+
|
|
4
|
+
# NOTE: This does not work and disabled by default.
|
|
5
|
+
# Actually on_static is just a workaround. This should be totally rewritten.
|
|
6
|
+
# Because pretty mode is not used on production and not so important,
|
|
7
|
+
# it is not done for now.
|
|
8
|
+
module Hamlit
|
|
9
|
+
module HTML
|
|
10
|
+
class Pretty < Temple::HTML::Pretty
|
|
11
|
+
include Concerns::Deprecation
|
|
12
|
+
|
|
13
|
+
def call(exp)
|
|
14
|
+
result = super(exp)
|
|
15
|
+
result << [:static, "\n"] if @added_newline
|
|
16
|
+
result
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def on_static(exp)
|
|
20
|
+
if exp == "\n"
|
|
21
|
+
@added_newline = true
|
|
22
|
+
[:static, '']
|
|
23
|
+
else
|
|
24
|
+
[:static, exp]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def on_html_tag(name, attrs, content = nil)
|
|
29
|
+
if content.is_a?(Array) && content.first != :multi
|
|
30
|
+
return parse_oneline_tag(name, attrs, content)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
super
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def parse_oneline_tag(name, attrs, content)
|
|
39
|
+
name = name.to_s
|
|
40
|
+
closed = !content || (empty_exp?(content) && (@format == :xml || options[:autoclose].include?(name)))
|
|
41
|
+
result = [:multi, [:static, "<#{name}"], compile(attrs)]
|
|
42
|
+
result << [:static, (closed && @format != :html ? ' /' : '') + '>']
|
|
43
|
+
result << compile(content) if content
|
|
44
|
+
result << [:static, "</#{name}>"] if !closed
|
|
45
|
+
result
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|