slimi 0.5.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +42 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +35 -1
- data/README.md +25 -3
- data/exe/slimi +7 -0
- data/lib/slimi/cli.rb +37 -0
- data/lib/slimi/engine.rb +5 -3
- data/lib/slimi/erb_converter.rb +9 -0
- data/lib/slimi/filters/amble.rb +23 -0
- data/lib/slimi/filters/attribute.rb +3 -3
- data/lib/slimi/filters/base.rb +49 -0
- data/lib/slimi/filters/control.rb +3 -3
- data/lib/slimi/filters/do_inserter.rb +5 -5
- data/lib/slimi/filters/embedded.rb +17 -15
- data/lib/slimi/filters/end_inserter.rb +2 -2
- data/lib/slimi/filters/interpolation.rb +2 -24
- data/lib/slimi/filters/output.rb +3 -3
- data/lib/slimi/filters/text.rb +3 -3
- data/lib/slimi/filters/unposition.rb +7 -23
- data/lib/slimi/filters.rb +2 -0
- data/lib/slimi/parser.rb +13 -13
- data/lib/slimi/rails_template_handler.rb +68 -5
- data/lib/slimi/railtie.rb +1 -0
- data/lib/slimi/version.rb +1 -1
- data/lib/slimi.rb +2 -0
- data/slimi.gemspec +2 -3
- metadata +26 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c151d108a263b740aa9cf7f7ac6dba84741a722b1fdffcb1b6078c63a55a911
|
4
|
+
data.tar.gz: fe127168b410730d5303deff0d50b43d42d805b9fcb16bce17c09fb00549c149
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbffeb9d9bd5dd13b085503bc439a85b4832ae44bd8839d07fd879faf5e158b7f5b41f72f051e3963a73086e302a5f9f3cc2541c6a404b7acbed66dd225824d3
|
7
|
+
data.tar.gz: 945f20409900cdd7fb7cff7a2517aae58a334d9528b6092d1a212b4715bc2dbf713650a25201b2bf8ba28f3f181d4e5cc635b1c759f9b0420e3c9dc6b4742ec2
|
data/.rubocop.yml
CHANGED
@@ -24,8 +24,14 @@ RSpec/ImplicitSubject:
|
|
24
24
|
RSpec/MultipleExpectations:
|
25
25
|
Enabled: false
|
26
26
|
|
27
|
+
RSpec/MultipleMemoizedHelpers:
|
28
|
+
Enabled: false
|
29
|
+
|
27
30
|
RSpec/NamedSubject:
|
28
31
|
Enabled: false
|
29
32
|
|
33
|
+
Security/Eval:
|
34
|
+
Enabled: false
|
35
|
+
|
30
36
|
Style/Documentation:
|
31
37
|
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,48 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 0.7.2 - 2022-01-24
|
6
|
+
|
7
|
+
### Fixed
|
8
|
+
|
9
|
+
- Fix parser bug at CR+LF empty line.
|
10
|
+
- Fix typo at internal const name.
|
11
|
+
|
12
|
+
## 0.7.1 - 2022-01-18
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
- Fix error handling on unexpected line ending.
|
17
|
+
- Fix missing some metadata in gemspec.
|
18
|
+
|
19
|
+
## 0.7.0 - 2022-01-04
|
20
|
+
|
21
|
+
### Added
|
22
|
+
|
23
|
+
- Add `slimi` executable.
|
24
|
+
|
25
|
+
### Fixed
|
26
|
+
|
27
|
+
- Remove preceding white spaces from HTML comment.
|
28
|
+
- Fix bug that :generator option was not working.
|
29
|
+
- Fix bug that Ruby code in nested line can be problem on compilation.
|
30
|
+
|
31
|
+
## 0.6.0 - 2022-01-03
|
32
|
+
|
33
|
+
### Added
|
34
|
+
|
35
|
+
- Support annotate_rendered_view_with_filenames.
|
36
|
+
|
37
|
+
### Changed
|
38
|
+
|
39
|
+
- Rename expression name from slim to slimi.
|
40
|
+
|
41
|
+
### Fixed
|
42
|
+
|
43
|
+
- Fix bug at registering handler to ActionView.
|
44
|
+
- Fix Engine options at RailsTemplateHandler.
|
45
|
+
- Define missing :generator option at Engine.
|
46
|
+
|
5
47
|
## 0.5.1 - 2022-01-02
|
6
48
|
|
7
49
|
### Changed
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,18 +1,48 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
slimi (0.
|
4
|
+
slimi (0.7.2)
|
5
5
|
temple
|
6
|
+
thor
|
6
7
|
tilt
|
7
8
|
|
8
9
|
GEM
|
9
10
|
remote: https://rubygems.org/
|
10
11
|
specs:
|
12
|
+
actionview (7.0.0)
|
13
|
+
activesupport (= 7.0.0)
|
14
|
+
builder (~> 3.1)
|
15
|
+
erubi (~> 1.4)
|
16
|
+
rails-dom-testing (~> 2.0)
|
17
|
+
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
18
|
+
activesupport (7.0.0)
|
19
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
20
|
+
i18n (>= 1.6, < 2)
|
21
|
+
minitest (>= 5.1)
|
22
|
+
tzinfo (~> 2.0)
|
11
23
|
ast (2.4.2)
|
24
|
+
builder (3.2.4)
|
25
|
+
concurrent-ruby (1.1.9)
|
26
|
+
crass (1.0.6)
|
12
27
|
diff-lcs (1.4.4)
|
28
|
+
erubi (1.10.0)
|
29
|
+
i18n (1.8.11)
|
30
|
+
concurrent-ruby (~> 1.0)
|
31
|
+
loofah (2.13.0)
|
32
|
+
crass (~> 1.0.2)
|
33
|
+
nokogiri (>= 1.5.9)
|
34
|
+
minitest (5.15.0)
|
35
|
+
nokogiri (1.12.5-x86_64-linux)
|
36
|
+
racc (~> 1.4)
|
13
37
|
parallel (1.21.0)
|
14
38
|
parser (3.0.3.2)
|
15
39
|
ast (~> 2.4.1)
|
40
|
+
racc (1.6.0)
|
41
|
+
rails-dom-testing (2.0.3)
|
42
|
+
activesupport (>= 4.2.0)
|
43
|
+
nokogiri (>= 1.6)
|
44
|
+
rails-html-sanitizer (1.4.2)
|
45
|
+
loofah (~> 2.3)
|
16
46
|
rainbow (3.0.0)
|
17
47
|
rake (13.0.6)
|
18
48
|
regexp_parser (2.2.0)
|
@@ -45,13 +75,17 @@ GEM
|
|
45
75
|
rubocop (~> 1.19)
|
46
76
|
ruby-progressbar (1.11.0)
|
47
77
|
temple (0.8.2)
|
78
|
+
thor (1.2.1)
|
48
79
|
tilt (2.0.10)
|
80
|
+
tzinfo (2.0.4)
|
81
|
+
concurrent-ruby (~> 1.0)
|
49
82
|
unicode-display_width (2.1.0)
|
50
83
|
|
51
84
|
PLATFORMS
|
52
85
|
x86_64-linux
|
53
86
|
|
54
87
|
DEPENDENCIES
|
88
|
+
actionview
|
55
89
|
rake (~> 13.0)
|
56
90
|
rspec
|
57
91
|
rubocop
|
data/README.md
CHANGED
@@ -15,12 +15,30 @@ It uses Slimi to apply `rubocop --auto-correct` to embedded Ruby codes in Slim t
|
|
15
15
|
|
16
16
|
## Usage
|
17
17
|
|
18
|
-
|
18
|
+
### Rails
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile.
|
19
21
|
|
20
22
|
```ruby
|
21
23
|
gem 'slimi'
|
22
24
|
```
|
23
25
|
|
26
|
+
This will cause `app/views/**/*.slim` files to be rendered by Slimi.
|
27
|
+
|
28
|
+
### CLI
|
29
|
+
|
30
|
+
Slimi can be tested from command line by `slimi` executable. This takes Slim code from STDIN and converts it into another form.
|
31
|
+
|
32
|
+
```console
|
33
|
+
$ slimi --help
|
34
|
+
Commands:
|
35
|
+
slimi compile # Convert Slim into Ruby
|
36
|
+
slimi erb # Convert Slim into ERB
|
37
|
+
slimi help [COMMAND] # Describe available commands or one specific command
|
38
|
+
slimi parse # Convert Slim into Temple expression
|
39
|
+
slimi render # Convert Slim into HTML
|
40
|
+
```
|
41
|
+
|
24
42
|
## Compatibility
|
25
43
|
|
26
44
|
- Line indicators
|
@@ -53,7 +71,11 @@ gem 'slimi'
|
|
53
71
|
- [ ] Translator/I18n
|
54
72
|
- [ ] Logic-less mode
|
55
73
|
- [ ] Smart text mode
|
56
|
-
-
|
57
|
-
- [
|
74
|
+
- CLI
|
75
|
+
- [x] Convert Slim to Ruby
|
76
|
+
- [x] Convert Slim to HTML
|
77
|
+
- [x] Convert Slim to ERB
|
58
78
|
- Slimi-only features
|
59
79
|
- [x] Embedded Ruby code location
|
80
|
+
- [x] Support for annotate_rendered_view_with_filenames
|
81
|
+
- [x] Convert Slim to Temple expression by CLI
|
data/exe/slimi
ADDED
data/lib/slimi/cli.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Slimi
|
6
|
+
# Provide CLI features.
|
7
|
+
class Cli < ::Thor
|
8
|
+
desc 'compile', 'Convert Slim into Ruby'
|
9
|
+
def compile
|
10
|
+
slim = $stdin.read
|
11
|
+
ruby = Engine.new.call(slim)
|
12
|
+
puts ruby
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'erb', 'Convert Slim into ERB'
|
16
|
+
def erb
|
17
|
+
slim = $stdin.read
|
18
|
+
expression = ErbConverter.new.call(slim)
|
19
|
+
puts expression
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'parse', 'Convert Slim into Temple expression'
|
23
|
+
def parse
|
24
|
+
slim = $stdin.read
|
25
|
+
expression = Parser.new.call(slim)
|
26
|
+
pp expression
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'render', 'Convert Slim into HTML'
|
30
|
+
def render
|
31
|
+
slim = $stdin.read
|
32
|
+
ruby = Engine.new.call(slim)
|
33
|
+
result = eval(ruby)
|
34
|
+
puts result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/slimi/engine.rb
CHANGED
@@ -3,21 +3,22 @@
|
|
3
3
|
require 'temple'
|
4
4
|
|
5
5
|
module Slimi
|
6
|
-
# Convert Slim
|
6
|
+
# Convert Slim into Ruby.
|
7
7
|
class Engine < ::Temple::Engine
|
8
8
|
define_options(
|
9
9
|
attr_quote: '"',
|
10
10
|
default_tag: 'div',
|
11
11
|
format: :xhtml,
|
12
|
+
generator: ::Temple::Generators::StringBuffer,
|
12
13
|
merge_attrs: { 'class' => ' ' },
|
13
14
|
pretty: false,
|
14
15
|
sort_attrs: true
|
15
16
|
)
|
16
17
|
|
17
18
|
use Parser
|
18
|
-
use Filters::Unposition
|
19
19
|
use Filters::Embedded
|
20
20
|
use Filters::Interpolation
|
21
|
+
use Filters::Unposition
|
21
22
|
use Filters::DoInserter
|
22
23
|
use Filters::EndInserter
|
23
24
|
use Filters::Control
|
@@ -28,10 +29,11 @@ module Slimi
|
|
28
29
|
use Filters::Attribute
|
29
30
|
use(:AttributeRemover) { ::Temple::HTML::AttributeRemover.new(remove_empty_attrs: options[:merge_attrs].keys) }
|
30
31
|
html :Pretty
|
32
|
+
use Filters::Amble
|
31
33
|
filter :Escapable
|
32
34
|
filter :ControlFlow
|
33
35
|
filter :MultiFlattener
|
34
36
|
filter :StaticMerger
|
35
|
-
generator
|
37
|
+
use(:Generator) { options[:generator] }
|
36
38
|
end
|
37
39
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
module Filters
|
5
|
+
# Support Rails annotate_rendered_view_with_filenames feature.
|
6
|
+
class Amble < Base
|
7
|
+
define_options(
|
8
|
+
:postamble,
|
9
|
+
:preamble
|
10
|
+
)
|
11
|
+
|
12
|
+
# @param [Array] expression
|
13
|
+
# @return [Array]
|
14
|
+
def call(expression)
|
15
|
+
result = %i[multi]
|
16
|
+
result << [:static, options[:preamble]] if options[:preamble]
|
17
|
+
result << expression
|
18
|
+
result << [:static, options[:postamble]] if options[:postamble]
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
5
|
# Handle `[:slimi, :attributes, ...]`.
|
6
|
-
class Attribute <
|
6
|
+
class Attribute < Base
|
7
7
|
define_options :merge_attrs
|
8
8
|
|
9
9
|
# @param [Array<Array>] expressions
|
@@ -16,7 +16,7 @@ module Slimi
|
|
16
16
|
# @param [Array] value
|
17
17
|
# @return [Array]
|
18
18
|
def on_html_attr(name, value)
|
19
|
-
if value[0] == :
|
19
|
+
if value[0] == :slimi && value[1] == :attrvalue && !options[:merge_attrs][name]
|
20
20
|
escape = value[2]
|
21
21
|
code = value[3]
|
22
22
|
case code
|
@@ -42,7 +42,7 @@ module Slimi
|
|
42
42
|
# @param [Boolean] escape
|
43
43
|
# @param [String] code\
|
44
44
|
# @return [Array]\
|
45
|
-
def
|
45
|
+
def on_slimi_attrvalue(escape, code)
|
46
46
|
if (delimiter = options[:merge_attrs][@attr])
|
47
47
|
tmp = unique_name
|
48
48
|
[:multi,
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temple'
|
4
|
+
|
5
|
+
module Slimi
|
6
|
+
module Filters
|
7
|
+
# Pass-through some expressions which are unknown for Temple.
|
8
|
+
class Base < ::Temple::HTML::Filter
|
9
|
+
# @param [String] code
|
10
|
+
# @param [Array] expression
|
11
|
+
# @return [Array]
|
12
|
+
def on_slimi_control(code, expression)
|
13
|
+
[:slimi, :control, code, compile(expression)]
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [String] type
|
17
|
+
# @param [String] code
|
18
|
+
# @param [Array] expression
|
19
|
+
# @param [Array] attributes
|
20
|
+
# @return [Array]
|
21
|
+
def on_slimi_embedded(type, expression, attributes)
|
22
|
+
[:slimi, :embedded, type, compile(expression), attributes]
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [Boolean] escape
|
26
|
+
# @param [String] code
|
27
|
+
# @param [Array] expression
|
28
|
+
# @return [Array]
|
29
|
+
def on_slimi_output(escape, code, expression)
|
30
|
+
[:slimi, :output, escape, code, compile(expression)]
|
31
|
+
end
|
32
|
+
|
33
|
+
# @param [Integer] begin_
|
34
|
+
# @param [Integer] end_
|
35
|
+
# @param [Array] expression
|
36
|
+
# @return [Array]
|
37
|
+
def on_slimi_position(begin_, end_, expression)
|
38
|
+
[:slimi, :position, begin_, end_, compile(expression)]
|
39
|
+
end
|
40
|
+
|
41
|
+
# @param [String] type
|
42
|
+
# @param [Array] expression
|
43
|
+
# @return [Array]
|
44
|
+
def on_slimi_text(type, expression)
|
45
|
+
[:slimi, :text, type, compile(expression)]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
|
-
# Handle `[:
|
6
|
-
class Control <
|
5
|
+
# Handle `[:slimi, :control, code, multi]`.
|
6
|
+
class Control < Base
|
7
7
|
# @param [String] code
|
8
8
|
# @param [Array] multi
|
9
9
|
# @return [Array]
|
10
|
-
def
|
10
|
+
def on_slimi_control(code, multi)
|
11
11
|
[
|
12
12
|
:multi,
|
13
13
|
[:code, code],
|
@@ -3,24 +3,24 @@
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
5
|
# Append missing `do` to embedded Ruby code.
|
6
|
-
class DoInserter <
|
6
|
+
class DoInserter < Base
|
7
7
|
VALID_RUBY_LINE_REGEXP = /(\A(if|unless|else|elsif|when|begin|rescue|ensure|case)\b)|\bdo\s*(\|[^|]*\|\s*)?\Z/.freeze
|
8
8
|
|
9
9
|
# @param [String] code
|
10
10
|
# @param [Array] expressio
|
11
11
|
# @return [Array]
|
12
|
-
def
|
12
|
+
def on_slimi_control(code, expression)
|
13
13
|
code += ' do' unless code.match?(VALID_RUBY_LINE_REGEXP) || empty_exp?(expression)
|
14
|
-
[:
|
14
|
+
[:slimi, :control, code, compile(expression)]
|
15
15
|
end
|
16
16
|
|
17
17
|
# @param [Boolean] escape
|
18
18
|
# @param [String] code
|
19
19
|
# @param [Array] expression
|
20
20
|
# @return [Array]
|
21
|
-
def
|
21
|
+
def on_slimi_output(escape, code, expression)
|
22
22
|
code += ' do' unless code.match?(VALID_RUBY_LINE_REGEXP) || empty_exp?(expression)
|
23
|
-
[:
|
23
|
+
[:slimi, :output, escape, code, compile(expression)]
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -1,23 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'tilt'
|
4
|
+
|
3
5
|
module Slimi
|
4
6
|
module Filters
|
5
7
|
# @api private
|
6
|
-
class TextCollector <
|
8
|
+
class TextCollector < Base
|
7
9
|
def call(exp)
|
8
10
|
@collected = ''
|
9
11
|
super(exp)
|
10
12
|
@collected
|
11
13
|
end
|
12
14
|
|
13
|
-
def
|
15
|
+
def on_slimi_interpolate(text)
|
14
16
|
@collected << text
|
15
17
|
nil
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
21
|
# @api private
|
20
|
-
class NewlineCollector <
|
22
|
+
class NewlineCollector < Base
|
21
23
|
def call(exp)
|
22
24
|
@collected = [:multi]
|
23
25
|
super(exp)
|
@@ -31,7 +33,7 @@ module Slimi
|
|
31
33
|
end
|
32
34
|
|
33
35
|
# @api private
|
34
|
-
class OutputProtector <
|
36
|
+
class OutputProtector < Base
|
35
37
|
def call(exp)
|
36
38
|
@protect = []
|
37
39
|
@collected = ''
|
@@ -45,9 +47,9 @@ module Slimi
|
|
45
47
|
nil
|
46
48
|
end
|
47
49
|
|
48
|
-
def
|
50
|
+
def on_slimi_output(escape, text, content)
|
49
51
|
@collected << @tag
|
50
|
-
@protect << [:
|
52
|
+
@protect << [:slimi, :output, escape, text, content]
|
51
53
|
nil
|
52
54
|
end
|
53
55
|
|
@@ -64,7 +66,7 @@ module Slimi
|
|
64
66
|
|
65
67
|
# Temple filter which processes embedded engines
|
66
68
|
# @api private
|
67
|
-
class Embedded <
|
69
|
+
class Embedded < Base
|
68
70
|
@engines = {}
|
69
71
|
|
70
72
|
class << self
|
@@ -101,12 +103,12 @@ module Slimi
|
|
101
103
|
@disabled = normalize_engine_list(options[:disable_engines])
|
102
104
|
end
|
103
105
|
|
104
|
-
def
|
106
|
+
def on_slimi_embedded(name, body, attrs)
|
105
107
|
name = name.to_sym
|
106
108
|
raise(Temple::FilterError, "Embedded engine #{name} is disabled") unless enabled?(name)
|
107
109
|
|
108
110
|
@engines[name] ||= self.class.create(name, options)
|
109
|
-
@engines[name].
|
111
|
+
@engines[name].on_slimi_embedded(name, body, attrs)
|
110
112
|
end
|
111
113
|
|
112
114
|
def enabled?(name)
|
@@ -122,7 +124,7 @@ module Slimi
|
|
122
124
|
list&.map(&:to_sym)
|
123
125
|
end
|
124
126
|
|
125
|
-
class Engine <
|
127
|
+
class Engine < Base
|
126
128
|
protected
|
127
129
|
|
128
130
|
def collect_text(body)
|
@@ -138,7 +140,7 @@ module Slimi
|
|
138
140
|
|
139
141
|
# Basic tilt engine
|
140
142
|
class TiltEngine < Engine
|
141
|
-
def
|
143
|
+
def on_slimi_embedded(engine, body, _attrs)
|
142
144
|
tilt_engine = Tilt[engine] || raise(Temple::FilterError, "Tilt engine #{engine} is not available.")
|
143
145
|
tilt_options = options[engine.to_sym] || {}
|
144
146
|
tilt_options[:default_encoding] ||= 'utf-8'
|
@@ -194,7 +196,7 @@ module Slimi
|
|
194
196
|
class TagEngine < Engine
|
195
197
|
disable_option_validator!
|
196
198
|
|
197
|
-
def
|
199
|
+
def on_slimi_embedded(engine, body, attrs)
|
198
200
|
unless options[:attributes].empty?
|
199
201
|
options[:attributes].map do |k, v|
|
200
202
|
attrs << [:html, :attr, k, [:static, v]]
|
@@ -207,7 +209,7 @@ module Slimi
|
|
207
209
|
opts.delete(:tag)
|
208
210
|
opts.delete(:attributes)
|
209
211
|
@engine ||= options[:engine].new(opts)
|
210
|
-
body = @engine.
|
212
|
+
body = @engine.on_slimi_embedded(engine, body, attrs)
|
211
213
|
end
|
212
214
|
|
213
215
|
[:html, :tag, options[:tag], attrs, body]
|
@@ -221,14 +223,14 @@ module Slimi
|
|
221
223
|
|
222
224
|
set_options tag: :script, attributes: {}
|
223
225
|
|
224
|
-
def
|
226
|
+
def on_slimi_embedded(engine, body, attrs)
|
225
227
|
super(engine, [:html, :js, body], attrs)
|
226
228
|
end
|
227
229
|
end
|
228
230
|
|
229
231
|
# Embeds ruby code
|
230
232
|
class RubyEngine < Engine
|
231
|
-
def
|
233
|
+
def on_slimi_embedded(_engine, body, _attrs)
|
232
234
|
[:multi, [:newline], [:code, "#{collect_text(body)}\n"]]
|
233
235
|
end
|
234
236
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
5
|
# Append missing `end` line to embedded Ruby code in control block.
|
6
|
-
class EndInserter <
|
6
|
+
class EndInserter < Base
|
7
7
|
# @param [Array<Array>] expressions
|
8
8
|
def on_multi(*expressions)
|
9
9
|
result = [:multi]
|
@@ -49,7 +49,7 @@ module Slimi
|
|
49
49
|
|
50
50
|
# @return [Boolean]
|
51
51
|
def control?
|
52
|
-
@expression[0] == :
|
52
|
+
@expression[0] == :slimi && @expression[1] == :control
|
53
53
|
end
|
54
54
|
|
55
55
|
# @return [Boolean]
|
@@ -4,29 +4,7 @@ require 'strscan'
|
|
4
4
|
|
5
5
|
module Slimi
|
6
6
|
module Filters
|
7
|
-
class Interpolation
|
8
|
-
def initialize(*); end
|
9
|
-
|
10
|
-
def call(node)
|
11
|
-
convert(node)
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def convert(value)
|
17
|
-
if value.instance_of?(::Array)
|
18
|
-
if value[0] == :slimi && value[1] == :interpolate
|
19
|
-
on_slimi_interpolate(value[2], value[3], value[4])
|
20
|
-
else
|
21
|
-
value.map do |element|
|
22
|
-
call(element)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
else
|
26
|
-
value
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
7
|
+
class Interpolation < Base
|
30
8
|
# @param [Integer] begin_
|
31
9
|
# @param [Integer] end_
|
32
10
|
# @return [Array] S-expression.
|
@@ -47,7 +25,7 @@ module Slimi
|
|
47
25
|
else
|
48
26
|
escape = false
|
49
27
|
end
|
50
|
-
block << [:slimi, :position, begin2, begin2 + code.length, [:
|
28
|
+
block << [:slimi, :position, begin2, begin2 + code.length, [:slimi, :output, escape, code, [:multi]]]
|
51
29
|
elsif (value = scanner.scan(/([#\\]?[^#\\]*([#\\][^\\\#{][^#\\]*)*)/)) # rubocop:disable Lint/DuplicateBranch
|
52
30
|
block << [:static, value]
|
53
31
|
end
|
data/lib/slimi/filters/output.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
|
-
# Handle `[:
|
6
|
-
class Output <
|
5
|
+
# Handle `[:slimi, :output, escape, code, multi]`.
|
6
|
+
class Output < Base
|
7
7
|
define_options :disable_capture
|
8
8
|
|
9
9
|
IF_REGEXP = /\A(if|unless)\b|\bdo\s*(\|[^|]*\|)?\s*$/.freeze
|
@@ -12,7 +12,7 @@ module Slimi
|
|
12
12
|
# @param [String] code
|
13
13
|
# @param [Array] multi
|
14
14
|
# @return [Array]
|
15
|
-
def
|
15
|
+
def on_slimi_output(escape, code, multi)
|
16
16
|
if code.match?(IF_REGEXP)
|
17
17
|
tmp = unique_name
|
18
18
|
[
|
data/lib/slimi/filters/text.rb
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
|
-
# Handle `[:
|
6
|
-
class Text <
|
5
|
+
# Handle `[:slimi, :text, multi]`.
|
6
|
+
class Text < Base
|
7
7
|
# @param [Symbol] _type
|
8
8
|
# @param [Array] multi
|
9
9
|
# @return [Array]
|
10
|
-
def
|
10
|
+
def on_slimi_text(_type, multi)
|
11
11
|
compile(multi)
|
12
12
|
end
|
13
13
|
end
|
@@ -2,29 +2,13 @@
|
|
2
2
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
|
-
class Unposition
|
6
|
-
|
7
|
-
|
8
|
-
# @param [Array]
|
9
|
-
# @return [Array]
|
10
|
-
def
|
11
|
-
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def convert(value)
|
17
|
-
if value.instance_of?(::Array)
|
18
|
-
if value[0] == :slimi && value[1] == :position
|
19
|
-
call(value[4])
|
20
|
-
else
|
21
|
-
value.map do |element|
|
22
|
-
call(element)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
else
|
26
|
-
value
|
27
|
-
end
|
5
|
+
class Unposition < Base
|
6
|
+
# @param [Integer] _begin
|
7
|
+
# @param [Integer] _end
|
8
|
+
# @param [Array] expression
|
9
|
+
# @return [Array]
|
10
|
+
def on_slimi_position(_begin, _end, expression)
|
11
|
+
compile(expression)
|
28
12
|
end
|
29
13
|
end
|
30
14
|
end
|
data/lib/slimi/filters.rb
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
|
+
autoload :Amble, 'slimi/filters/amble'
|
5
6
|
autoload :Attribute, 'slimi/filters/attribute'
|
7
|
+
autoload :Base, 'slimi/filters/base'
|
6
8
|
autoload :Control, 'slimi/filters/control'
|
7
9
|
autoload :DoInserter, 'slimi/filters/do_inserter'
|
8
10
|
autoload :Embedded, 'slimi/filters/embedded'
|
data/lib/slimi/parser.rb
CHANGED
@@ -77,7 +77,7 @@ module Slimi
|
|
77
77
|
# Parse blank line.
|
78
78
|
# @return [Boolean] True if it could parse a blank line.
|
79
79
|
def parse_blank_line
|
80
|
-
if @scanner.skip(/[ \t]
|
80
|
+
if @scanner.skip(/[ \t]*(?=\R|$)/)
|
81
81
|
parse_line_ending
|
82
82
|
true
|
83
83
|
else
|
@@ -115,7 +115,7 @@ module Slimi
|
|
115
115
|
|
116
116
|
embedded_template_engine_name = @scanner[1]
|
117
117
|
attributes = parse_attributes
|
118
|
-
@stacks.last << [:
|
118
|
+
@stacks.last << [:slimi, :embedded, embedded_template_engine_name, parse_text_block, attributes]
|
119
119
|
end
|
120
120
|
|
121
121
|
# @return [Boolean]
|
@@ -150,14 +150,14 @@ module Slimi
|
|
150
150
|
block = [:multi]
|
151
151
|
@stacks.last.insert(-2, [:static, ' ']) if with_leading_white_space2
|
152
152
|
@scanner.skip(/[ \t]+/)
|
153
|
-
tag << with_position { [:
|
153
|
+
tag << with_position { [:slimi, :output, escape, parse_broken_lines, block] }
|
154
154
|
@stacks.last << [:static, ' '] if with_trailing_white_space2
|
155
155
|
@stacks << block
|
156
156
|
elsif @scanner.skip(%r{[ \t]*/[ \t]*})
|
157
157
|
syntax_error!(Errors::UnexpectedTextAfterClosedTagError) unless @scanner.match?(/\r?\n/)
|
158
158
|
else
|
159
159
|
@scanner.skip(/[ \t]+/)
|
160
|
-
tag << [:
|
160
|
+
tag << [:slimi, :text, :inline, parse_text_block]
|
161
161
|
end
|
162
162
|
true
|
163
163
|
else
|
@@ -272,7 +272,7 @@ module Slimi
|
|
272
272
|
charpos = @scanner.charpos
|
273
273
|
attribute_value = parse_ruby_attribute_value(attribute_delimiter_closing)
|
274
274
|
syntax_error!(Errors::InvalidEmptyAttributeError) if attribute_value.empty?
|
275
|
-
attributes << [:html, :attr, attribute_name, [:slimi, :position, charpos, charpos + attribute_value.length, [:
|
275
|
+
attributes << [:html, :attr, attribute_name, [:slimi, :position, charpos, charpos + attribute_value.length, [:slimi, :attrvalue, escape, attribute_value]]]
|
276
276
|
elsif !attribute_delimiter_closing_part_regexp
|
277
277
|
break
|
278
278
|
elsif @scanner.skip(boolean_attribute_regexp)
|
@@ -332,9 +332,9 @@ module Slimi
|
|
332
332
|
|
333
333
|
# @return [Boolean]
|
334
334
|
def parse_html_comment
|
335
|
-
if @scanner.skip(%r{/!})
|
335
|
+
if @scanner.skip(%r{/![ \t]*})
|
336
336
|
text_block = parse_text_block
|
337
|
-
text = [:
|
337
|
+
text = [:slimi, :text, :verbatim, text_block]
|
338
338
|
@stacks.last << [:html, :comment, text]
|
339
339
|
true
|
340
340
|
else
|
@@ -381,7 +381,7 @@ module Slimi
|
|
381
381
|
def parse_verbatim_text_block_inner
|
382
382
|
if @scanner.skip(/([|']) ?/)
|
383
383
|
with_trailing_white_space = @scanner[1] == "'"
|
384
|
-
@stacks.last << [:
|
384
|
+
@stacks.last << [:slimi, :text, :verbatim, parse_text_block]
|
385
385
|
@stacks.last << [:static, ' '] if with_trailing_white_space
|
386
386
|
true
|
387
387
|
else
|
@@ -420,7 +420,7 @@ module Slimi
|
|
420
420
|
if @scanner.skip(/-/)
|
421
421
|
block = [:multi]
|
422
422
|
@scanner.skip(/[ \t]+/)
|
423
|
-
@stacks.last << with_position { [:
|
423
|
+
@stacks.last << with_position { [:slimi, :control, parse_broken_lines, block] }
|
424
424
|
@stacks << block
|
425
425
|
true
|
426
426
|
else
|
@@ -443,7 +443,7 @@ module Slimi
|
|
443
443
|
block = [:multi]
|
444
444
|
@stacks.last << [:static, ' '] if with_trailing_white_space
|
445
445
|
@scanner.skip(/[ \t]+/)
|
446
|
-
@stacks.last << with_position { [:
|
446
|
+
@stacks.last << with_position { [:slimi, :output, escape, parse_broken_lines, block] }
|
447
447
|
@stacks.last << [:static, ' '] if with_leading_white_space
|
448
448
|
@stacks << block
|
449
449
|
else
|
@@ -473,7 +473,7 @@ module Slimi
|
|
473
473
|
|
474
474
|
# @raise
|
475
475
|
def expect_line_ending
|
476
|
-
parse_line_ending || @scanner.eos? ||
|
476
|
+
parse_line_ending || @scanner.eos? || syntax_error!(Errors::LineEndingNotFoundError)
|
477
477
|
end
|
478
478
|
|
479
479
|
# @return [Integer] Indent level.
|
@@ -578,7 +578,7 @@ module Slimi
|
|
578
578
|
|
579
579
|
# Convert human-friendly options into machine-friendly objects.
|
580
580
|
class Factory
|
581
|
-
|
581
|
+
EMBEDDED_TEMPLATE_ENGINE_NAMES = %w[
|
582
582
|
coffee
|
583
583
|
css
|
584
584
|
javascript
|
@@ -667,7 +667,7 @@ module Slimi
|
|
667
667
|
|
668
668
|
# @return [Regexp]
|
669
669
|
def embedded_template_regexp
|
670
|
-
/(#{::Regexp.union(
|
670
|
+
/(#{::Regexp.union(EMBEDDED_TEMPLATE_ENGINE_NAMES)})(?:[ \t]*(?:(.*)))?:([ \t]*)/
|
671
671
|
end
|
672
672
|
|
673
673
|
# @return [Regexp]
|
@@ -1,14 +1,77 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Slimi
|
4
|
+
# Render Slim template in response to requests from Rails.
|
4
5
|
class RailsTemplateHandler
|
5
|
-
|
6
|
-
|
6
|
+
# @param [ActionView::Template] template
|
7
|
+
# @param [String, nil] source
|
8
|
+
# @return [String]
|
9
|
+
def call(template, source = nil)
|
10
|
+
Renderer.new(
|
11
|
+
source: source,
|
12
|
+
template: template
|
13
|
+
).call
|
7
14
|
end
|
8
15
|
|
9
|
-
|
10
|
-
|
11
|
-
@
|
16
|
+
# Render HTML from given source and options.
|
17
|
+
class Renderer
|
18
|
+
# @param [String] source
|
19
|
+
# @param [ActionView::Template] template
|
20
|
+
def initialize(
|
21
|
+
source:,
|
22
|
+
template:
|
23
|
+
)
|
24
|
+
@source = source
|
25
|
+
@template = template
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [String]
|
29
|
+
def call
|
30
|
+
engine.call(source)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# @return [Slimi::Engine]
|
36
|
+
def engine
|
37
|
+
Engine.new(engine_options)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [Hash{Symbol => Object}]
|
41
|
+
def engine_options
|
42
|
+
engine_default_options.merge(engine_amble_options)
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Hash{Symbol => Object}]
|
46
|
+
def engine_default_options
|
47
|
+
{
|
48
|
+
generator: ::Temple::Generators::RailsOutputBuffer,
|
49
|
+
streaming: true,
|
50
|
+
use_html_safe: true
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [Hash{Symbol => Object}]
|
55
|
+
def engine_amble_options
|
56
|
+
if with_annotate_rendered_view_with_filenames?
|
57
|
+
{
|
58
|
+
postamble: "<!-- END #{@template.short_identifier} -->\n",
|
59
|
+
preamble: "<!-- BEGIN #{@template.short_identifier} -->\n"
|
60
|
+
}
|
61
|
+
else
|
62
|
+
{}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [String]
|
67
|
+
def source
|
68
|
+
@source || @template.source
|
69
|
+
end
|
70
|
+
|
71
|
+
# @return [Boolean]
|
72
|
+
def with_annotate_rendered_view_with_filenames?
|
73
|
+
::ActionView::Base.try(:annotate_rendered_view_with_filenames) && @template.format == :html
|
74
|
+
end
|
12
75
|
end
|
13
76
|
end
|
14
77
|
end
|
data/lib/slimi/railtie.rb
CHANGED
data/lib/slimi/version.rb
CHANGED
data/lib/slimi.rb
CHANGED
@@ -3,7 +3,9 @@
|
|
3
3
|
require_relative 'slimi/version'
|
4
4
|
|
5
5
|
module Slimi
|
6
|
+
autoload :Cli, 'slimi/cli'
|
6
7
|
autoload :Engine, 'slimi/engine'
|
8
|
+
autoload :ErbConverter, 'slimi/erb_converter'
|
7
9
|
autoload :Errors, 'slimi/errors'
|
8
10
|
autoload :Filters, 'slimi/filters'
|
9
11
|
autoload :Parser, 'slimi/parser'
|
data/slimi.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.metadata['homepage_uri'] = spec.homepage
|
17
17
|
spec.metadata['source_code_uri'] = spec.homepage
|
18
18
|
spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
19
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
19
20
|
|
20
21
|
# Specify which files should be added to the gem when it is released.
|
21
22
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -27,10 +28,8 @@ Gem::Specification.new do |spec|
|
|
27
28
|
spec.bindir = 'exe'
|
28
29
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
30
|
spec.require_paths = ['lib']
|
30
|
-
spec.metadata = {
|
31
|
-
'rubygems_mfa_required' => 'true'
|
32
|
-
}
|
33
31
|
|
34
32
|
spec.add_dependency 'temple'
|
33
|
+
spec.add_dependency 'thor'
|
35
34
|
spec.add_dependency 'tilt'
|
36
35
|
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.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-01-
|
11
|
+
date: 2022-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: temple
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: tilt
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -41,7 +55,8 @@ dependencies:
|
|
41
55
|
description:
|
42
56
|
email:
|
43
57
|
- r7kamura@gmail.com
|
44
|
-
executables:
|
58
|
+
executables:
|
59
|
+
- slimi
|
45
60
|
extensions: []
|
46
61
|
extra_rdoc_files: []
|
47
62
|
files:
|
@@ -56,11 +71,16 @@ files:
|
|
56
71
|
- Rakefile
|
57
72
|
- bin/console
|
58
73
|
- bin/setup
|
74
|
+
- exe/slimi
|
59
75
|
- lib/slimi.rb
|
76
|
+
- lib/slimi/cli.rb
|
60
77
|
- lib/slimi/engine.rb
|
78
|
+
- lib/slimi/erb_converter.rb
|
61
79
|
- lib/slimi/errors.rb
|
62
80
|
- lib/slimi/filters.rb
|
81
|
+
- lib/slimi/filters/amble.rb
|
63
82
|
- lib/slimi/filters/attribute.rb
|
83
|
+
- lib/slimi/filters/base.rb
|
64
84
|
- lib/slimi/filters/control.rb
|
65
85
|
- lib/slimi/filters/do_inserter.rb
|
66
86
|
- lib/slimi/filters/embedded.rb
|
@@ -79,6 +99,9 @@ homepage: https://github.com/r7kamura/slimi
|
|
79
99
|
licenses:
|
80
100
|
- MIT
|
81
101
|
metadata:
|
102
|
+
homepage_uri: https://github.com/r7kamura/slimi
|
103
|
+
source_code_uri: https://github.com/r7kamura/slimi
|
104
|
+
changelog_uri: https://github.com/r7kamura/slimi/blob/main/CHANGELOG.md
|
82
105
|
rubygems_mfa_required: 'true'
|
83
106
|
post_install_message:
|
84
107
|
rdoc_options: []
|