faml 0.2.13 → 0.2.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/README.md +2 -0
  4. data/faml.gemspec +2 -1
  5. data/incompatibilities/README.md +29 -0
  6. data/incompatibilities/spec/compiler_newline_spec.md +31 -0
  7. data/incompatibilities/spec/render/attribute_spec.md +587 -0
  8. data/incompatibilities/spec/render/comment_spec.md +42 -0
  9. data/incompatibilities/spec/render/doctype_spec.md +22 -0
  10. data/incompatibilities/spec/render/element_spec.md +95 -0
  11. data/incompatibilities/spec/render/filters/cdata_spec.md +25 -0
  12. data/incompatibilities/spec/render/filters/coffee_spec.md +88 -0
  13. data/incompatibilities/spec/render/filters/css_spec.md +38 -0
  14. data/incompatibilities/spec/render/filters/escaped_spec.md +33 -0
  15. data/incompatibilities/spec/render/filters/javascript_spec.md +38 -0
  16. data/incompatibilities/spec/render/filters/markdown_spec.md +24 -0
  17. data/incompatibilities/spec/render/filters/preserve_spec.md +29 -0
  18. data/incompatibilities/spec/render/filters/sass_spec.md +59 -0
  19. data/incompatibilities/spec/render/filters/scss_spec.md +65 -0
  20. data/incompatibilities/spec/render/helpers_spec.md +17 -0
  21. data/incompatibilities/spec/render/indent_spec.md +21 -0
  22. data/incompatibilities/spec/render/multiline_spec.md +55 -0
  23. data/incompatibilities/spec/render/newline_spec.md +91 -0
  24. data/incompatibilities/spec/render/plain_spec.md +19 -0
  25. data/incompatibilities/spec/render/sanitize_spec.md +36 -0
  26. data/incompatibilities/spec/render/silent_script_spec.md +31 -0
  27. data/incompatibilities/spec/render/unescape_spec.md +56 -0
  28. data/lib/faml/indent_tracker.rb +39 -3
  29. data/lib/faml/parser.rb +2 -0
  30. data/lib/faml/version.rb +1 -1
  31. data/spec/render/element_spec.rb +0 -9
  32. data/spec/render/indent_spec.rb +47 -0
  33. data/spec/spec_helper.rb +21 -2
  34. data/spec/support/incompatibilities_generator.rb +132 -0
  35. metadata +53 -3
@@ -3,6 +3,29 @@ require 'faml/error'
3
3
  module Faml
4
4
  class IndentTracker
5
5
  class IndentMismatch < Error
6
+ attr_reader :current_level, :indent_levels
7
+
8
+ def initialize(current_level, indent_levels, lineno)
9
+ super("Unexpected indent level: #{current_level}: indent_level=#{indent_levels}", lineno)
10
+ @current_level = current_level
11
+ @indent_levels = indent_levels
12
+ end
13
+ end
14
+
15
+ class InconsistentIndent < Error
16
+ attr_reader :previous_size, :current_size
17
+
18
+ def initialize(previous_size, current_size, lineno)
19
+ super("Inconsistent indentation: #{current_size} spaces used for indentation, but the rest of the document was indented using #{previous_size} spaces.", lineno)
20
+ @previous_size = previous_size
21
+ @current_size = current_size
22
+ end
23
+ end
24
+
25
+ class HardTabNotAllowed < Error
26
+ def initialize(lineno)
27
+ super('Indentation with hard tabs are not allowed :-p', lineno)
28
+ end
6
29
  end
7
30
 
8
31
  def initialize(on_enter: nil, on_leave: nil)
@@ -13,6 +36,9 @@ module Faml
13
36
  end
14
37
 
15
38
  def process(line, lineno)
39
+ if line =~ /\A\t/
40
+ raise HardTabNotAllowed.new(lineno)
41
+ end
16
42
  indent, text = split(line)
17
43
  indent_level = indent.size
18
44
 
@@ -39,17 +65,27 @@ module Faml
39
65
  @comment_level = @indent_levels[-2]
40
66
  end
41
67
 
68
+ def check_indent_level!(lineno)
69
+ if @indent_levels.size >= 3
70
+ previous_size = @indent_levels[-2] - @indent_levels[-3]
71
+ current_size = @indent_levels[-1] - @indent_levels[-2]
72
+ if previous_size != current_size
73
+ raise InconsistentIndent.new(previous_size, current_size, lineno)
74
+ end
75
+ end
76
+ end
77
+
42
78
  private
43
79
 
44
80
  def track(indent_level, text, lineno)
45
81
  if indent_level > @indent_levels.last
46
- indent_enter(indent_level, text)
82
+ indent_enter(indent_level, text, lineno)
47
83
  elsif indent_level < @indent_levels.last
48
84
  indent_leave(indent_level, text, lineno)
49
85
  end
50
86
  end
51
87
 
52
- def indent_enter(indent_level, text)
88
+ def indent_enter(indent_level, text, lineno)
53
89
  unless @comment_level
54
90
  @indent_levels.push(indent_level)
55
91
  @on_enter.call(indent_level, text)
@@ -73,7 +109,7 @@ module Faml
73
109
  end
74
110
 
75
111
  if indent_level != @indent_levels.last
76
- raise IndentMismatch.new("Unexpected indent level: #{indent_level}: indent_level=#{@indent_levels}", lineno)
112
+ raise IndentMismatch.new(indent_level, @indent_levels.dup, lineno)
77
113
  end
78
114
  end
79
115
  end
data/lib/faml/parser.rb CHANGED
@@ -186,6 +186,8 @@ module Faml
186
186
  end
187
187
  if @ast.is_a?(Ast::HamlComment)
188
188
  @indent_tracker.enter_comment!
189
+ else
190
+ @indent_tracker.check_indent_level!(@line_parser.lineno)
189
191
  end
190
192
  nil
191
193
  end
data/lib/faml/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Faml
2
- VERSION = "0.2.13"
2
+ VERSION = "0.2.14"
3
3
  end
@@ -42,15 +42,6 @@ HAML
42
42
  HAML
43
43
  end
44
44
 
45
- it 'raises error if indent is wrong' do
46
- expect { render_string(<<HAML) }.to raise_error(Faml::IndentTracker::IndentMismatch)
47
- %div
48
- %div
49
- %div
50
- %div
51
- HAML
52
- end
53
-
54
45
  it 'parses classes' do
55
46
  expect(render_string('%span.foo.bar hello')).to eq(%Q{<span class='foo bar'>hello</span>\n})
56
47
  end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Indent', type: :render do
4
+ it 'raises error if indent is wrong' do
5
+ expect { render_string(<<HAML) }.to raise_error(Faml::IndentTracker::IndentMismatch) { |e|
6
+ %div
7
+ %div
8
+ %div
9
+ %div
10
+ HAML
11
+ expect(e.current_level).to eq(2)
12
+ expect(e.indent_levels).to eq([0])
13
+ expect(e.lineno).to eq(4)
14
+ }
15
+ end
16
+
17
+ it 'raises error if the current indent is deeper than the previous one' do
18
+ expect { render_string(<<HAML) }.to raise_error(Faml::IndentTracker::InconsistentIndent) { |e|
19
+ %div
20
+ %div
21
+ %div
22
+ HAML
23
+ expect(e.previous_size).to eq(2)
24
+ expect(e.current_size).to eq(4)
25
+ expect(e.lineno).to eq(3)
26
+ }
27
+ end
28
+
29
+ it 'raises error if the current indent is shallower than the previous one' do
30
+ expect { render_string(<<HAML) }.to raise_error(Faml::IndentTracker::InconsistentIndent) { |e|
31
+ %div
32
+ %div
33
+ %div
34
+ HAML
35
+ expect(e.previous_size).to eq(4)
36
+ expect(e.current_size).to eq(2)
37
+ expect(e.lineno).to eq(3)
38
+ }
39
+ end
40
+
41
+ it 'raises error if indented with hard tabs' do
42
+ expect { render_string(<<HAML) }.to raise_error(Faml::IndentTracker::HardTabNotAllowed)
43
+ %p
44
+ %a
45
+ HAML
46
+ end
47
+ end
data/spec/spec_helper.rb CHANGED
@@ -12,8 +12,21 @@ end
12
12
  require 'faml'
13
13
 
14
14
  module RenderSpecHelper
15
- def render_string(str, options = {})
16
- eval(Faml::Engine.new(options).call(str))
15
+ if ENV['GENERATE_INCOMPATIBILITIES'] == '1'
16
+ require_relative 'support/incompatibilities_generator'
17
+
18
+ def render_string(str, options = {})
19
+ eval(Faml::Engine.new(options).call(str)).tap do |html|
20
+ IncompatibilitiesGenerator.instance.record(str, options, html, RSpec.current_example)
21
+ end
22
+ rescue => e
23
+ IncompatibilitiesGenerator.instance.record(str, options, e, RSpec.current_example)
24
+ raise e
25
+ end
26
+ else
27
+ def render_string(str, options = {})
28
+ eval(Faml::Engine.new(options).call(str))
29
+ end
17
30
  end
18
31
  end
19
32
 
@@ -44,4 +57,10 @@ RSpec.configure do |config|
44
57
  Kernel.srand config.seed
45
58
 
46
59
  config.include(RenderSpecHelper, type: :render)
60
+
61
+ if ENV['GENERATE_INCOMPATIBILITIES'] == '1'
62
+ config.after :suite do
63
+ IncompatibilitiesGenerator.instance.write_to('incompatibilities')
64
+ end
65
+ end
47
66
  end
@@ -0,0 +1,132 @@
1
+ require 'pathname'
2
+ require 'singleton'
3
+ require 'hamlit/engine'
4
+ require 'hamlit/version'
5
+
6
+ class IncompatibilitiesGenerator
7
+ include Singleton
8
+
9
+ class Record < Struct.new(:template, :options, :spec_path, :line_number, :faml_result, :haml_result, :hamlit_result)
10
+ end
11
+
12
+ def initialize
13
+ @records = []
14
+ end
15
+
16
+ def record(template, options, faml_result, example)
17
+ m = example.location.match(/\A(.+):(\d+)\z/)
18
+ @records.push(Record.new(template, options, m[1], m[2].to_i, faml_result, render_haml(template, options), render_hamlit(template, options)))
19
+ end
20
+
21
+ def write_to(markdown_root)
22
+ markdown_root = Pathname.new(markdown_root)
23
+
24
+ incompatibilities = Hash.new { |h, k| h[k] = [] }
25
+ @records.each do |record|
26
+ if record.faml_result.is_a?(Exception) && record.haml_result.is_a?(Exception) && record.hamlit_result.is_a?(Exception)
27
+ # All errored, not an incompatibility.
28
+ elsif record.faml_result != record.haml_result || record.faml_result != record.hamlit_result || record.haml_result != record.hamlit_result
29
+ incompatibilities[record.spec_path] << record
30
+ end
31
+ end
32
+
33
+ incompatibilities.keys.sort.each do |spec_path|
34
+ path = markdown_path(markdown_root, spec_path)
35
+ path.parent.mkpath
36
+ path.open('w') do |f|
37
+ incompatibilities[spec_path].sort_by(&:line_number).each do |record|
38
+ render_difference(f, path, record)
39
+ end
40
+ end
41
+ end
42
+ render_toc(markdown_root, incompatibilities.keys)
43
+ end
44
+
45
+ private
46
+
47
+ def render_haml(template, options)
48
+ obj = Object.new
49
+ Haml::Engine.new(template, {ugly: true, escape_html: true}.merge(options)).def_method(obj, :haml)
50
+ obj.haml
51
+ rescue Exception => e
52
+ e
53
+ end
54
+
55
+ def render_hamlit(template, options)
56
+ obj = Object.new
57
+ obj.instance_eval "def hamlit; #{Hamlit::Engine.new(options).call(template)}; end"
58
+ obj.hamlit
59
+ rescue Exception => e
60
+ e
61
+ end
62
+
63
+ def render_difference(file, path, record)
64
+ spec_path = Pathname.new(record.spec_path).relative_path_from(path.parent).to_s
65
+ file.write <<"EOS"
66
+ # [#{record.spec_path}:#{record.line_number}](#{spec_path}#L#{record.line_number})
67
+ ## #{render_input_title(record.options)}
68
+ ```haml
69
+ #{record.template}
70
+ ```
71
+
72
+ EOS
73
+ if record.faml_result != record.haml_result && record.faml_result != record.hamlit_result && record.haml_result != record.hamlit_result
74
+ render_grouped_difference(file, 'Faml' => record.faml_result, 'Haml' => record.haml_result, 'Hamlit' => record.hamlit_result)
75
+ elsif record.faml_result == record.haml_result
76
+ render_grouped_difference(file, 'Faml, Haml' => record.faml_result, 'Hamlit' => record.hamlit_result)
77
+ elsif record.faml_result == record.hamlit_result
78
+ render_grouped_difference(file, 'Faml, Hamlit' => record.faml_result, 'Haml' => record.haml_result)
79
+ else
80
+ render_grouped_difference(file, 'Faml' => record.faml_result, 'Haml, Hamlit' => record.haml_result)
81
+ end
82
+ end
83
+
84
+ def render_input_title(options)
85
+ title = 'Input'
86
+ if !options.empty?
87
+ title << " (with options=#{options.inspect})"
88
+ end
89
+ title
90
+ end
91
+
92
+ def render_grouped_difference(file, grouped_results)
93
+ grouped_results.each do |title, result|
94
+ file.write <<"EOS"
95
+ ## #{render_section(title, result)}
96
+ ```html
97
+ #{result}
98
+ ```
99
+
100
+ EOS
101
+ end
102
+ end
103
+
104
+ def render_section(title, result)
105
+ if result.is_a?(Exception)
106
+ "#{title} (Error)"
107
+ else
108
+ title
109
+ end
110
+ end
111
+
112
+ def markdown_path(markdown_root, spec_path)
113
+ markdown_root.join(spec_path).sub_ext('.md')
114
+ end
115
+
116
+ def render_toc(markdown_root, spec_paths)
117
+ toc_path = markdown_root.join('README.md')
118
+ toc_path.open('w') do |f|
119
+ f.puts '# Incompatibilities'
120
+ f.puts '## Versions'
121
+ f.puts "- Haml #{Haml::VERSION}"
122
+ f.puts "- Faml #{Faml::VERSION}"
123
+ f.puts "- Hamlit #{Hamlit::VERSION}"
124
+ f.puts
125
+ f.puts '## Table of contents'
126
+ spec_paths.sort.each do |spec_path|
127
+ path = markdown_path(markdown_root, spec_path).relative_path_from(markdown_root)
128
+ f.puts "- [#{path}](#{path})"
129
+ end
130
+ end
131
+ end
132
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: faml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.13
4
+ version: 0.2.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kohei Suzuki
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-13 00:00:00.000000000 Z
11
+ date: 2015-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: escape_utils
@@ -298,6 +298,29 @@ files:
298
298
  - gemfiles/rails_4.2.gemfile
299
299
  - gemfiles/rails_edge.gemfile
300
300
  - haml_spec_test.rb
301
+ - incompatibilities/README.md
302
+ - incompatibilities/spec/compiler_newline_spec.md
303
+ - incompatibilities/spec/render/attribute_spec.md
304
+ - incompatibilities/spec/render/comment_spec.md
305
+ - incompatibilities/spec/render/doctype_spec.md
306
+ - incompatibilities/spec/render/element_spec.md
307
+ - incompatibilities/spec/render/filters/cdata_spec.md
308
+ - incompatibilities/spec/render/filters/coffee_spec.md
309
+ - incompatibilities/spec/render/filters/css_spec.md
310
+ - incompatibilities/spec/render/filters/escaped_spec.md
311
+ - incompatibilities/spec/render/filters/javascript_spec.md
312
+ - incompatibilities/spec/render/filters/markdown_spec.md
313
+ - incompatibilities/spec/render/filters/preserve_spec.md
314
+ - incompatibilities/spec/render/filters/sass_spec.md
315
+ - incompatibilities/spec/render/filters/scss_spec.md
316
+ - incompatibilities/spec/render/helpers_spec.md
317
+ - incompatibilities/spec/render/indent_spec.md
318
+ - incompatibilities/spec/render/multiline_spec.md
319
+ - incompatibilities/spec/render/newline_spec.md
320
+ - incompatibilities/spec/render/plain_spec.md
321
+ - incompatibilities/spec/render/sanitize_spec.md
322
+ - incompatibilities/spec/render/silent_script_spec.md
323
+ - incompatibilities/spec/render/unescape_spec.md
301
324
  - lib/faml.rb
302
325
  - lib/faml/ast.rb
303
326
  - lib/faml/cli.rb
@@ -417,6 +440,7 @@ files:
417
440
  - spec/render/filters_spec.rb
418
441
  - spec/render/haml_comment_spec.rb
419
442
  - spec/render/helpers_spec.rb
443
+ - spec/render/indent_spec.rb
420
444
  - spec/render/multiline_spec.rb
421
445
  - spec/render/newline_spec.rb
422
446
  - spec/render/plain_spec.rb
@@ -426,6 +450,7 @@ files:
426
450
  - spec/render/silent_script_spec.rb
427
451
  - spec/render/unescape_spec.rb
428
452
  - spec/spec_helper.rb
453
+ - spec/support/incompatibilities_generator.rb
429
454
  - spec/tilt_spec.rb
430
455
  homepage: https://github.com/eagletmt/faml
431
456
  licenses:
@@ -439,7 +464,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
439
464
  requirements:
440
465
  - - ">="
441
466
  - !ruby/object:Gem::Version
442
- version: '0'
467
+ version: 2.0.0
443
468
  required_rubygems_version: !ruby/object:Gem::Requirement
444
469
  requirements:
445
470
  - - ">="
@@ -452,6 +477,29 @@ signing_key:
452
477
  specification_version: 4
453
478
  summary: Faster implementation of Haml template language.
454
479
  test_files:
480
+ - incompatibilities/README.md
481
+ - incompatibilities/spec/compiler_newline_spec.md
482
+ - incompatibilities/spec/render/attribute_spec.md
483
+ - incompatibilities/spec/render/comment_spec.md
484
+ - incompatibilities/spec/render/doctype_spec.md
485
+ - incompatibilities/spec/render/element_spec.md
486
+ - incompatibilities/spec/render/filters/cdata_spec.md
487
+ - incompatibilities/spec/render/filters/coffee_spec.md
488
+ - incompatibilities/spec/render/filters/css_spec.md
489
+ - incompatibilities/spec/render/filters/escaped_spec.md
490
+ - incompatibilities/spec/render/filters/javascript_spec.md
491
+ - incompatibilities/spec/render/filters/markdown_spec.md
492
+ - incompatibilities/spec/render/filters/preserve_spec.md
493
+ - incompatibilities/spec/render/filters/sass_spec.md
494
+ - incompatibilities/spec/render/filters/scss_spec.md
495
+ - incompatibilities/spec/render/helpers_spec.md
496
+ - incompatibilities/spec/render/indent_spec.md
497
+ - incompatibilities/spec/render/multiline_spec.md
498
+ - incompatibilities/spec/render/newline_spec.md
499
+ - incompatibilities/spec/render/plain_spec.md
500
+ - incompatibilities/spec/render/sanitize_spec.md
501
+ - incompatibilities/spec/render/silent_script_spec.md
502
+ - incompatibilities/spec/render/unescape_spec.md
455
503
  - spec/compiler_newline_spec.rb
456
504
  - spec/rails/Rakefile
457
505
  - spec/rails/app/assets/images/.keep
@@ -532,6 +580,7 @@ test_files:
532
580
  - spec/render/filters_spec.rb
533
581
  - spec/render/haml_comment_spec.rb
534
582
  - spec/render/helpers_spec.rb
583
+ - spec/render/indent_spec.rb
535
584
  - spec/render/multiline_spec.rb
536
585
  - spec/render/newline_spec.rb
537
586
  - spec/render/plain_spec.rb
@@ -541,4 +590,5 @@ test_files:
541
590
  - spec/render/silent_script_spec.rb
542
591
  - spec/render/unescape_spec.rb
543
592
  - spec/spec_helper.rb
593
+ - spec/support/incompatibilities_generator.rb
544
594
  - spec/tilt_spec.rb