slimi 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7aed4b0083f7ec850df87f869b5687873dcf98fd6f80ab93854c101e0d03098
4
- data.tar.gz: bfa813fce529081b2eb876e00a9b722feecf914a5741c9ca341ec2aa8d1463ac
3
+ metadata.gz: ce4329befc9d19fb756c5609a28a3169c4f5a5aa2698771df14541b88b792da1
4
+ data.tar.gz: d99512e7191942f2fabb8667cb4de369dcad5d773c1e162cc039f2911b4b1dc9
5
5
  SHA512:
6
- metadata.gz: bcd9e3abde25cca87e45eb7244658ed6a99d56e458d2b0b3e1199252eb5621480fb7afc12f6246f3760e13a07a2efaabd80f45e5deb868212228cbf96b582a01
7
- data.tar.gz: 9fd6030053873163c81f12646461cb502a4d3632e9de4bd8ec77081546081e50fd7e088ad93f23b15666d54007ca1b298f44dd63eeb74b2f5778e716e5e3d6fc
6
+ metadata.gz: 6c1b46a4afdfc4ce2a8ce816898a17e6bd448e0e76a001efbebfe7fc498375a2c1c71aaa5f40cce11012f28e7e87f5c7eef06b70b6dbcd560a6343d5494ee71c
7
+ data.tar.gz: 7554a443efa9d30952d3446b92c494dd6ecf1caeb78d77aea347eef1ab862e64c35e93d4ef76c1423728734eb3b23913e75497c3358b0df2543229e05b177c07
data/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.0 - 2021-12-23
6
+
7
+ ### Added
8
+
9
+ - Support embedded template.
10
+ - Show useful message at syntax error.
11
+
5
12
  ## 0.1.1 - 2021-12-21
6
13
 
7
14
  ### Fixed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- slimi (0.1.0)
4
+ slimi (0.2.0)
5
5
  temple
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Yet another implementation for [Slim](https://github.com/slim-template/slim) template language.
7
7
 
8
- The current goal is to generate AST with detailed location information so that the embedded Ruby code in slim templates can be auto-corrected by Linter such as RuboCop.
8
+ Slimi is used by [Slimcop](https://github.com/r7kamura/slimcop).
9
9
 
10
10
  ## Installation
11
11
 
@@ -30,21 +30,3 @@ gem install slimi
30
30
  ## Usage
31
31
 
32
32
  TBD.
33
-
34
- ## Development
35
-
36
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
37
-
38
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
39
-
40
- ## Contributing
41
-
42
- Bug reports and pull requests are welcome on GitHub at https://github.com/r7kamura/slimi. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/r7kamura/slimi/blob/main/CODE_OF_CONDUCT.md).
43
-
44
- ## License
45
-
46
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
47
-
48
- ## Code of Conduct
49
-
50
- Everyone interacting in the Slimi project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/r7kamura/slimi/blob/main/CODE_OF_CONDUCT.md).
data/lib/slimi/errors.rb CHANGED
@@ -5,25 +5,53 @@ module Slimi
5
5
  class BaseError < StandardError
6
6
  end
7
7
 
8
- class ParserError < BaseError
8
+ class SlimSyntaxError < BaseError
9
+ # @param [Integer] column
10
+ # @param [String] file_path
11
+ # @param [String] line
12
+ # @param [Integer] line_number
13
+ def initialize(column:, file_path:, line:, line_number:)
14
+ super()
15
+ @column = column
16
+ @file_path = file_path
17
+ @line = line
18
+ @line_number = line_number
19
+ end
20
+
21
+ # @note Override.
22
+ # @return [String]
23
+ def to_s
24
+ <<~TEXT
25
+ #{error_type} at #{@file_path}:#{@line_number}:#{@column}
26
+ #{@line}
27
+ #{' ' * (@column - 1)}^
28
+ TEXT
29
+ end
30
+
31
+ private
32
+
33
+ # @return [String]
34
+ def error_type
35
+ self.class.to_s.split('::').last
36
+ end
9
37
  end
10
38
 
11
- class LineEndingNotFoundError < ParserError
39
+ class LineEndingNotFoundError < SlimSyntaxError
12
40
  end
13
41
 
14
- class MalformedIndentationError < ParserError
42
+ class MalformedIndentationError < SlimSyntaxError
15
43
  end
16
44
 
17
- class UnexpectedEosError < ParserError
45
+ class UnexpectedEosError < SlimSyntaxError
18
46
  end
19
47
 
20
- class UnexpectedIndentationError < ParserError
48
+ class UnexpectedIndentationError < SlimSyntaxError
21
49
  end
22
50
 
23
- class UnexpectedTextAfterClosedTagError < ParserError
51
+ class UnexpectedTextAfterClosedTagError < SlimSyntaxError
24
52
  end
25
53
 
26
- class UnknownLineIndicator < ParserError
54
+ class UnknownLineIndicator < SlimSyntaxError
27
55
  end
28
56
  end
29
57
  end
data/lib/slimi/parser.rb CHANGED
@@ -32,6 +32,7 @@ module Slimi
32
32
  @quoted_attribute_regexp = factory.quoted_attribute_regexp
33
33
  @tag_name_regexp = factory.tag_name_regexp
34
34
  @attribute_name_regexp = factory.attribute_name_regexp
35
+ @embedded_template_regexp = factory.embedded_template_regexp
35
36
  end
36
37
 
37
38
  def call(source)
@@ -55,6 +56,7 @@ module Slimi
55
56
  parse_inline_html ||
56
57
  parse_code_block ||
57
58
  parse_output_block ||
59
+ parse_embedded_template ||
58
60
  parse_doctype ||
59
61
  parse_tag ||
60
62
  raise(Errors::UnknownLineIndicatorError)
@@ -66,7 +68,7 @@ module Slimi
66
68
  @indents << indent if @indents.empty?
67
69
 
68
70
  if indent > @indents.last
69
- raise Errors::UnexpectedIndentationError unless expecting_indentation?
71
+ syntax_error!(Errors::UnexpectedIndentationError) unless expecting_indentation?
70
72
 
71
73
  @indents << indent
72
74
  else
@@ -77,10 +79,22 @@ module Slimi
77
79
  @stacks.pop
78
80
  end
79
81
 
80
- raise Errors::MalformedIndentationError if indent != @indents.last
82
+ syntax_error!(Errors::MalformedIndentationError) if indent != @indents.last
81
83
  end
82
84
  end
83
85
 
86
+ # Parse embedded template lines.
87
+ # e.g.
88
+ # ruby:
89
+ # a = b + c
90
+ def parse_embedded_template
91
+ return unless @scanner.skip(@embedded_template_regexp)
92
+
93
+ embedded_template_engine_name = @scanner[1]
94
+ attributes = parse_attributes
95
+ @stacks.last << [:slim, :embedded, embedded_template_engine_name, parse_text_block, attributes]
96
+ end
97
+
84
98
  # @return [Boolean]
85
99
  def parse_tag
86
100
  parse_tag_inner && expect_line_ending
@@ -117,7 +131,7 @@ module Slimi
117
131
  @stacks.last << [:static, ' '] if with_trailing_white_space2
118
132
  @stacks << block
119
133
  elsif @scanner.skip(%r{[ \t]*/[ \t]*})
120
- raise Errors::UnexpectedTextAfterClosedTagError unless @scanner.match?(/\r?\n/)
134
+ syntax_error!(Errors::UnexpectedTextAfterClosedTagError) unless @scanner.match?(/\r?\n/)
121
135
  else
122
136
  @scanner.skip(/[ \t]+/)
123
137
  tag << [:slim, :text, :inline, parse_text_block]
@@ -452,7 +466,7 @@ module Slimi
452
466
  result = +''
453
467
  result << @scanner.scan(/.*/)
454
468
  while result.end_with?(',') || result.end_with?('\\')
455
- raise Errors::UnexpectedEosError unless @scanner.scan(/\r?\n/)
469
+ syntax_error!(Errors::UnexpectedEosError) unless @scanner.scan(/\r?\n/)
456
470
 
457
471
  result << "\n"
458
472
  result << @scanner.scan(/.*/)
@@ -468,8 +482,33 @@ module Slimi
468
482
  [:slimi, :position, begin_, end_, inner]
469
483
  end
470
484
 
485
+ # @param [Class] syntax_error_class A child class of Slimi::Errors::SlimSyntaxError.
486
+ # @raise [Slimi::Errors::SlimSyntaxError]
487
+ def syntax_error!(syntax_error_class)
488
+ range = Range.new(index: @scanner.charpos, source: @scanner.string)
489
+ raise syntax_error_class.new(
490
+ column: range.column,
491
+ file_path: '(__TEMPLATE__)',
492
+ line: range.line,
493
+ line_number: range.line_number
494
+ )
495
+ end
496
+
471
497
  # Convert human-friendly options into machine-friendly objects.
472
498
  class Factory
499
+ EMBEDDED_TEMPLAE_ENGINE_NAMES = %w[
500
+ coffee
501
+ css
502
+ javascript
503
+ less
504
+ markdown
505
+ rdoc
506
+ ruby
507
+ sass
508
+ scss
509
+ textile
510
+ ].freeze
511
+
473
512
  # @return [Hash]
474
513
  attr_reader :attribute_delimiters
475
514
 
@@ -534,6 +573,11 @@ module Slimi
534
573
  %r{(#{markers_regexp}+)((?:\p{Word}|-|/\d+|:(\w|-)+)*)}
535
574
  end
536
575
 
576
+ # @return [Regexp]
577
+ def embedded_template_regexp
578
+ /(#{::Regexp.union(EMBEDDED_TEMPLAE_ENGINE_NAMES)})(?:[ \t]*(?:(.*)))?:([ \t]*)/
579
+ end
580
+
537
581
  # @return [Regexp]
538
582
  def quoted_attribute_regexp
539
583
  /#{attribute_name_regexp}[ \t]*=(=?)[ \t]*("|')/
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Slimi
4
+ # Get line-based information from source code and its index.
5
+ class Range
6
+ # @param [Integer] index 0-indexed per-character index.
7
+ # @param [String] source
8
+ def initialize(index:, source:)
9
+ @index = index
10
+ @source = source
11
+ end
12
+
13
+ # @return [Integer] 1-indexed column index.
14
+ def column
15
+ (@index - line_beginning_index) + 1
16
+ end
17
+
18
+ def line
19
+ @source[line_beginning_index...line_ending_index]
20
+ end
21
+
22
+ # @return [Integer] 1-indexed line index.
23
+ def line_number
24
+ @source[0..@index].scan(/^/).length
25
+ end
26
+
27
+ private
28
+
29
+ # @return [Integer]
30
+ def line_beginning_index
31
+ @source.rindex(/^/, @index) || 0
32
+ end
33
+
34
+ # @return [Integer]
35
+ def line_ending_index
36
+ @source.index(/$/, @index)
37
+ end
38
+ end
39
+ end
data/lib/slimi/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Slimi
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/slimi.rb CHANGED
@@ -6,4 +6,5 @@ module Slimi
6
6
  autoload :Errors, 'slimi/errors'
7
7
  autoload :Filters, 'slimi/filters'
8
8
  autoload :Parser, 'slimi/parser'
9
+ autoload :Range, 'slimi/range'
9
10
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slimi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryo Nakamura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-12-20 00:00:00.000000000 Z
11
+ date: 2021-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: temple
@@ -48,6 +48,7 @@ files:
48
48
  - lib/slimi/filters/interpolation.rb
49
49
  - lib/slimi/filters/unposition.rb
50
50
  - lib/slimi/parser.rb
51
+ - lib/slimi/range.rb
51
52
  - lib/slimi/version.rb
52
53
  - slimi.gemspec
53
54
  homepage: https://github.com/r7kamura/slimi