slimi 0.4.2 → 0.7.0
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 +40 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +36 -5
- data/README.md +51 -16
- data/exe/slimi +7 -0
- data/lib/slimi/cli.rb +37 -0
- data/lib/slimi/engine.rb +39 -0
- data/lib/slimi/erb_converter.rb +9 -0
- data/lib/slimi/filters/amble.rb +23 -0
- data/lib/slimi/filters/attribute.rb +63 -0
- data/lib/slimi/filters/base.rb +49 -0
- data/lib/slimi/filters/control.rb +19 -0
- data/lib/slimi/filters/do_inserter.rb +27 -0
- data/lib/slimi/filters/embedded.rb +257 -0
- data/lib/slimi/filters/end_inserter.rb +77 -0
- data/lib/slimi/filters/interpolation.rb +2 -24
- data/lib/slimi/filters/output.rb +33 -0
- data/lib/slimi/filters/text.rb +15 -0
- data/lib/slimi/filters/unposition.rb +7 -23
- data/lib/slimi/filters.rb +9 -0
- data/lib/slimi/parser.rb +10 -9
- data/lib/slimi/rails_template_handler.rb +77 -0
- data/lib/slimi/railtie.rb +14 -0
- data/lib/slimi/version.rb +1 -1
- data/lib/slimi.rb +6 -0
- data/slimi.gemspec +2 -0
- metadata +47 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '09a450cbc4d4a536b55bee031d9b76345aee45e82d112563d83cdadc1476a82c'
|
4
|
+
data.tar.gz: 781931ba445275b0bc24157df457dde36e49f74b7c48afedcbfa8cb279c6a401
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3810040838f6d5eaf636326eaa4021edd62a810d508b41efe7f27a29702c444a783cd2f0bfbd9dedc535d52738bc2446c55df08e6a6e0acee3cb3743ae7798f8
|
7
|
+
data.tar.gz: 625e3d9bd3be61d376364388f6ef86f555fe9065a73d802e907fcb1a6238d4707d42a5d4597acc05794d6e46d4623ebb01007836b2b8bb5ae2884158e3d16ad1
|
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,46 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## 0.7.0 - 2022-01-04
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- Add `slimi` executable.
|
10
|
+
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
- Remove preceding white spaces from HTML comment.
|
14
|
+
- Fix bug that :generator option was not working.
|
15
|
+
- Fix bug that Ruby code in nested line can be problem on compilation.
|
16
|
+
|
17
|
+
## 0.6.0 - 2022-01-03
|
18
|
+
|
19
|
+
### Added
|
20
|
+
|
21
|
+
- Support annotate_rendered_view_with_filenames.
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
|
25
|
+
- Rename expression name from slim to slimi.
|
26
|
+
|
27
|
+
### Fixed
|
28
|
+
|
29
|
+
- Fix bug at registering handler to ActionView.
|
30
|
+
- Fix Engine options at RailsTemplateHandler.
|
31
|
+
- Define missing :generator option at Engine.
|
32
|
+
|
33
|
+
## 0.5.1 - 2022-01-02
|
34
|
+
|
35
|
+
### Changed
|
36
|
+
|
37
|
+
- Wrap slim attrvalue by slimi position expression.
|
38
|
+
|
39
|
+
## 0.5.0 - 2022-01-02
|
40
|
+
|
41
|
+
### Added
|
42
|
+
|
43
|
+
- Add Slimi::Engine.
|
44
|
+
|
5
45
|
## 0.4.2 - 2021-12-27
|
6
46
|
|
7
47
|
### Fixed
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,17 +1,48 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
slimi (0.
|
4
|
+
slimi (0.7.0)
|
5
5
|
temple
|
6
|
+
thor
|
7
|
+
tilt
|
6
8
|
|
7
9
|
GEM
|
8
10
|
remote: https://rubygems.org/
|
9
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)
|
10
23
|
ast (2.4.2)
|
24
|
+
builder (3.2.4)
|
25
|
+
concurrent-ruby (1.1.9)
|
26
|
+
crass (1.0.6)
|
11
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)
|
12
37
|
parallel (1.21.0)
|
13
38
|
parser (3.0.3.2)
|
14
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)
|
15
46
|
rainbow (3.0.0)
|
16
47
|
rake (13.0.6)
|
17
48
|
regexp_parser (2.2.0)
|
@@ -43,22 +74,22 @@ GEM
|
|
43
74
|
rubocop-rspec (2.6.0)
|
44
75
|
rubocop (~> 1.19)
|
45
76
|
ruby-progressbar (1.11.0)
|
46
|
-
slim (4.1.0)
|
47
|
-
temple (>= 0.7.6, < 0.9)
|
48
|
-
tilt (>= 2.0.6, < 2.1)
|
49
77
|
temple (0.8.2)
|
78
|
+
thor (1.1.0)
|
50
79
|
tilt (2.0.10)
|
80
|
+
tzinfo (2.0.4)
|
81
|
+
concurrent-ruby (~> 1.0)
|
51
82
|
unicode-display_width (2.1.0)
|
52
83
|
|
53
84
|
PLATFORMS
|
54
85
|
x86_64-linux
|
55
86
|
|
56
87
|
DEPENDENCIES
|
88
|
+
actionview
|
57
89
|
rake (~> 13.0)
|
58
90
|
rspec
|
59
91
|
rubocop
|
60
92
|
rubocop-rspec
|
61
|
-
slim
|
62
93
|
slimi!
|
63
94
|
|
64
95
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -5,28 +5,63 @@
|
|
5
5
|
|
6
6
|
Yet another implementation for [Slim](https://github.com/slim-template/slim) template language.
|
7
7
|
|
8
|
-
|
8
|
+
## Introduction
|
9
9
|
|
10
|
-
|
10
|
+
Slimi provides almost the same functionality as Slim, with a few additional useful features,
|
11
|
+
such as generating AST with detailed location information about embedded Ruby codes.
|
11
12
|
|
12
|
-
|
13
|
+
Originally, Slimi was developed for [Slimcop](https://github.com/r7kamura/slimcop), a RuboCop runner for Slim template.
|
14
|
+
It uses Slimi to apply `rubocop --auto-correct` to embedded Ruby codes in Slim template.
|
13
15
|
|
14
|
-
|
15
|
-
gem 'slimi'
|
16
|
-
```
|
17
|
-
|
18
|
-
And then execute:
|
16
|
+
## Usage
|
19
17
|
|
20
|
-
|
21
|
-
bundle install
|
22
|
-
```
|
18
|
+
### Rails
|
23
19
|
|
24
|
-
|
20
|
+
Add this line to your application's Gemfile.
|
25
21
|
|
26
|
-
```
|
27
|
-
gem
|
22
|
+
```ruby
|
23
|
+
gem 'slimi'
|
28
24
|
```
|
29
25
|
|
30
|
-
|
26
|
+
This will cause `app/views/**/*.slim` files to be rendered by Slimi.
|
27
|
+
|
28
|
+
## Compatibility
|
31
29
|
|
32
|
-
|
30
|
+
- Line indicators
|
31
|
+
- [x] Vebatim text
|
32
|
+
- [x] Inline HTML
|
33
|
+
- [x] Control
|
34
|
+
- [x] Output
|
35
|
+
- [x] HTML comment
|
36
|
+
- [x] Code comment
|
37
|
+
- [x] IE conditional comment
|
38
|
+
- Tags
|
39
|
+
- [x] Doctype declaration
|
40
|
+
- [x] Closed tags
|
41
|
+
- [x] Trailing and leading white space
|
42
|
+
- [x] Inline tags
|
43
|
+
- [x] Text content
|
44
|
+
- [x] Dynamic content
|
45
|
+
- [x] Tag shortcuts
|
46
|
+
- [ ] Dynamic tags
|
47
|
+
- Attributes
|
48
|
+
- [x] Attributes wrapper
|
49
|
+
- [x] Quoted attributes
|
50
|
+
- [x] Ruby attributes
|
51
|
+
- [x] Boolean attributes
|
52
|
+
- [x] Attribute merging
|
53
|
+
- [x] Attribute shortcuts
|
54
|
+
- [ ] Splat attributes
|
55
|
+
- Plugins
|
56
|
+
- [ ] Include partials
|
57
|
+
- [ ] Translator/I18n
|
58
|
+
- [ ] Logic-less mode
|
59
|
+
- [ ] Smart text mode
|
60
|
+
- CLI
|
61
|
+
- [x] Convert Slim to Ruby
|
62
|
+
- [x] Convert Slim to HTML
|
63
|
+
- [x] Convert Slim to ERB
|
64
|
+
- Slimi-only features
|
65
|
+
- [x] Embedded Ruby code location
|
66
|
+
- [x] Support for annotate_rendered_view_with_filenames
|
67
|
+
- [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
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'temple'
|
4
|
+
|
5
|
+
module Slimi
|
6
|
+
# Convert Slim into Ruby.
|
7
|
+
class Engine < ::Temple::Engine
|
8
|
+
define_options(
|
9
|
+
attr_quote: '"',
|
10
|
+
default_tag: 'div',
|
11
|
+
format: :xhtml,
|
12
|
+
generator: ::Temple::Generators::StringBuffer,
|
13
|
+
merge_attrs: { 'class' => ' ' },
|
14
|
+
pretty: false,
|
15
|
+
sort_attrs: true
|
16
|
+
)
|
17
|
+
|
18
|
+
use Parser
|
19
|
+
use Filters::Embedded
|
20
|
+
use Filters::Interpolation
|
21
|
+
use Filters::Unposition
|
22
|
+
use Filters::DoInserter
|
23
|
+
use Filters::EndInserter
|
24
|
+
use Filters::Control
|
25
|
+
use Filters::Output
|
26
|
+
use Filters::Text
|
27
|
+
html :AttributeSorter
|
28
|
+
html :AttributeMerger
|
29
|
+
use Filters::Attribute
|
30
|
+
use(:AttributeRemover) { ::Temple::HTML::AttributeRemover.new(remove_empty_attrs: options[:merge_attrs].keys) }
|
31
|
+
html :Pretty
|
32
|
+
use Filters::Amble
|
33
|
+
filter :Escapable
|
34
|
+
filter :ControlFlow
|
35
|
+
filter :MultiFlattener
|
36
|
+
filter :StaticMerger
|
37
|
+
use(:Generator) { options[:generator] }
|
38
|
+
end
|
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
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
module Filters
|
5
|
+
# Handle `[:slimi, :attributes, ...]`.
|
6
|
+
class Attribute < Base
|
7
|
+
define_options :merge_attrs
|
8
|
+
|
9
|
+
# @param [Array<Array>] expressions
|
10
|
+
# @return [Array]
|
11
|
+
def on_html_attrs(*expressions)
|
12
|
+
[:multi, *expressions.map { |expression| compile(expression) }]
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param [String] name
|
16
|
+
# @param [Array] value
|
17
|
+
# @return [Array]
|
18
|
+
def on_html_attr(name, value)
|
19
|
+
if value[0] == :slimi && value[1] == :attrvalue && !options[:merge_attrs][name]
|
20
|
+
escape = value[2]
|
21
|
+
code = value[3]
|
22
|
+
case code
|
23
|
+
when 'true'
|
24
|
+
[:html, :attr, name, [:multi]]
|
25
|
+
when 'false', 'nil'
|
26
|
+
[:multi]
|
27
|
+
else
|
28
|
+
tmp = unique_name
|
29
|
+
[:multi,
|
30
|
+
[:code, "#{tmp} = #{code}"],
|
31
|
+
[:if, tmp,
|
32
|
+
[:if, "#{tmp} == true",
|
33
|
+
[:html, :attr, name, [:multi]],
|
34
|
+
[:html, :attr, name, [:escape, escape, [:dynamic, tmp]]]]]]
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@attr = name
|
38
|
+
super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [Boolean] escape
|
43
|
+
# @param [String] code\
|
44
|
+
# @return [Array]\
|
45
|
+
def on_slimi_attrvalue(escape, code)
|
46
|
+
if (delimiter = options[:merge_attrs][@attr])
|
47
|
+
tmp = unique_name
|
48
|
+
[:multi,
|
49
|
+
[:code, "#{tmp} = #{code}"],
|
50
|
+
[:if, "Array === #{tmp}",
|
51
|
+
[:multi,
|
52
|
+
[:code, "#{tmp} = #{tmp}.flatten"],
|
53
|
+
[:code, "#{tmp}.map!(&:to_s)"],
|
54
|
+
[:code, "#{tmp}.reject!(&:empty?)"],
|
55
|
+
[:escape, escape, [:dynamic, "#{tmp}.join(#{delimiter.inspect})"]]],
|
56
|
+
[:escape, escape, [:dynamic, tmp]]]]
|
57
|
+
else
|
58
|
+
[:escape, escape, [:dynamic, code]]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -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
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
module Filters
|
5
|
+
# Handle `[:slimi, :control, code, multi]`.
|
6
|
+
class Control < Base
|
7
|
+
# @param [String] code
|
8
|
+
# @param [Array] multi
|
9
|
+
# @return [Array]
|
10
|
+
def on_slimi_control(code, multi)
|
11
|
+
[
|
12
|
+
:multi,
|
13
|
+
[:code, code],
|
14
|
+
compile(multi)
|
15
|
+
]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
module Filters
|
5
|
+
# Append missing `do` to embedded Ruby code.
|
6
|
+
class DoInserter < Base
|
7
|
+
VALID_RUBY_LINE_REGEXP = /(\A(if|unless|else|elsif|when|begin|rescue|ensure|case)\b)|\bdo\s*(\|[^|]*\|\s*)?\Z/.freeze
|
8
|
+
|
9
|
+
# @param [String] code
|
10
|
+
# @param [Array] expressio
|
11
|
+
# @return [Array]
|
12
|
+
def on_slimi_control(code, expression)
|
13
|
+
code += ' do' unless code.match?(VALID_RUBY_LINE_REGEXP) || empty_exp?(expression)
|
14
|
+
[:slimi, :control, code, compile(expression)]
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [Boolean] escape
|
18
|
+
# @param [String] code
|
19
|
+
# @param [Array] expression
|
20
|
+
# @return [Array]
|
21
|
+
def on_slimi_output(escape, code, expression)
|
22
|
+
code += ' do' unless code.match?(VALID_RUBY_LINE_REGEXP) || empty_exp?(expression)
|
23
|
+
[:slimi, :output, escape, code, compile(expression)]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tilt'
|
4
|
+
|
5
|
+
module Slimi
|
6
|
+
module Filters
|
7
|
+
# @api private
|
8
|
+
class TextCollector < Base
|
9
|
+
def call(exp)
|
10
|
+
@collected = ''
|
11
|
+
super(exp)
|
12
|
+
@collected
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_slimi_interpolate(text)
|
16
|
+
@collected << text
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
class NewlineCollector < Base
|
23
|
+
def call(exp)
|
24
|
+
@collected = [:multi]
|
25
|
+
super(exp)
|
26
|
+
@collected
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_newline
|
30
|
+
@collected << [:newline]
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# @api private
|
36
|
+
class OutputProtector < Base
|
37
|
+
def call(exp)
|
38
|
+
@protect = []
|
39
|
+
@collected = ''
|
40
|
+
@tag = "%#{object_id.abs.to_s(36)}%"
|
41
|
+
super(exp)
|
42
|
+
@collected
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_static(text)
|
46
|
+
@collected << text
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def on_slimi_output(escape, text, content)
|
51
|
+
@collected << @tag
|
52
|
+
@protect << [:slimi, :output, escape, text, content]
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def unprotect(text)
|
57
|
+
block = [:multi]
|
58
|
+
while text =~ /#{@tag}/
|
59
|
+
block << [:static, Regexp.last_match.pre_match]
|
60
|
+
block << @protect.shift
|
61
|
+
text = Regexp.last_match.post_match
|
62
|
+
end
|
63
|
+
block << [:static, text]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Temple filter which processes embedded engines
|
68
|
+
# @api private
|
69
|
+
class Embedded < Base
|
70
|
+
@engines = {}
|
71
|
+
|
72
|
+
class << self
|
73
|
+
attr_reader :engines
|
74
|
+
|
75
|
+
# Register embedded engine
|
76
|
+
#
|
77
|
+
# @param [String] name Name of the engine
|
78
|
+
# @param [Class] klass Engine class
|
79
|
+
# @param option_filter List of options to pass to engine.
|
80
|
+
# Last argument can be default option hash.
|
81
|
+
def register(name, klass, *option_filter)
|
82
|
+
name = name.to_sym
|
83
|
+
local_options = option_filter.last.respond_to?(:to_hash) ? option_filter.pop.to_hash : {}
|
84
|
+
define_options(name, *option_filter)
|
85
|
+
klass.define_options(name)
|
86
|
+
engines[name.to_sym] = proc do |options|
|
87
|
+
klass.new({}.update(options).delete_if { |k, _v| !option_filter.include?(k) && k != name }.update(local_options))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def create(name, options)
|
92
|
+
constructor = engines[name] || raise(Temple::FilterError, "Embedded engine #{name} not found")
|
93
|
+
constructor.call(options)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
define_options :enable_engines, :disable_engines
|
98
|
+
|
99
|
+
def initialize(opts = {})
|
100
|
+
super
|
101
|
+
@engines = {}
|
102
|
+
@enabled = normalize_engine_list(options[:enable_engines])
|
103
|
+
@disabled = normalize_engine_list(options[:disable_engines])
|
104
|
+
end
|
105
|
+
|
106
|
+
def on_slimi_embedded(name, body, attrs)
|
107
|
+
name = name.to_sym
|
108
|
+
raise(Temple::FilterError, "Embedded engine #{name} is disabled") unless enabled?(name)
|
109
|
+
|
110
|
+
@engines[name] ||= self.class.create(name, options)
|
111
|
+
@engines[name].on_slimi_embedded(name, body, attrs)
|
112
|
+
end
|
113
|
+
|
114
|
+
def enabled?(name)
|
115
|
+
(!@enabled || @enabled.include?(name)) &&
|
116
|
+
(!@disabled || !@disabled.include?(name))
|
117
|
+
end
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
121
|
+
def normalize_engine_list(list)
|
122
|
+
raise(ArgumentError, 'Option :enable_engines/:disable_engines must be String or Symbol list') unless !list || list.is_a?(Array)
|
123
|
+
|
124
|
+
list&.map(&:to_sym)
|
125
|
+
end
|
126
|
+
|
127
|
+
class Engine < Base
|
128
|
+
protected
|
129
|
+
|
130
|
+
def collect_text(body)
|
131
|
+
@text_collector ||= TextCollector.new
|
132
|
+
@text_collector.call(body)
|
133
|
+
end
|
134
|
+
|
135
|
+
def collect_newlines(body)
|
136
|
+
@newline_collector ||= NewlineCollector.new
|
137
|
+
@newline_collector.call(body)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Basic tilt engine
|
142
|
+
class TiltEngine < Engine
|
143
|
+
def on_slimi_embedded(engine, body, _attrs)
|
144
|
+
tilt_engine = Tilt[engine] || raise(Temple::FilterError, "Tilt engine #{engine} is not available.")
|
145
|
+
tilt_options = options[engine.to_sym] || {}
|
146
|
+
tilt_options[:default_encoding] ||= 'utf-8'
|
147
|
+
[:multi, tilt_render(tilt_engine, tilt_options, collect_text(body)), collect_newlines(body)]
|
148
|
+
end
|
149
|
+
|
150
|
+
protected
|
151
|
+
|
152
|
+
def tilt_render(tilt_engine, tilt_options, text)
|
153
|
+
[:static, tilt_engine.new(tilt_options) { text }.render]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Sass engine which supports :pretty option
|
158
|
+
class SassEngine < TiltEngine
|
159
|
+
define_options :pretty
|
160
|
+
|
161
|
+
protected
|
162
|
+
|
163
|
+
def tilt_render(tilt_engine, tilt_options, text)
|
164
|
+
text = tilt_engine.new(tilt_options.merge(
|
165
|
+
style: options[:pretty] ? :expanded : :compressed,
|
166
|
+
cache: false
|
167
|
+
)) { text }.render
|
168
|
+
text = text.chomp
|
169
|
+
[:static, text]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# Static template with interpolated ruby code
|
174
|
+
class InterpolateTiltEngine < TiltEngine
|
175
|
+
def collect_text(body)
|
176
|
+
output_protector.call(interpolation.call(body))
|
177
|
+
end
|
178
|
+
|
179
|
+
def tilt_render(tilt_engine, tilt_options, text)
|
180
|
+
output_protector.unprotect(tilt_engine.new(tilt_options) { text }.render)
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
def interpolation
|
186
|
+
@interpolation ||= Interpolation.new
|
187
|
+
end
|
188
|
+
|
189
|
+
def output_protector
|
190
|
+
@output_protector ||= OutputProtector.new
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Tag wrapper engine
|
195
|
+
# Generates a html tag and wraps another engine (specified via :engine option)
|
196
|
+
class TagEngine < Engine
|
197
|
+
disable_option_validator!
|
198
|
+
|
199
|
+
def on_slimi_embedded(engine, body, attrs)
|
200
|
+
unless options[:attributes].empty?
|
201
|
+
options[:attributes].map do |k, v|
|
202
|
+
attrs << [:html, :attr, k, [:static, v]]
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
if options[:engine]
|
207
|
+
opts = {}.update(options)
|
208
|
+
opts.delete(:engine)
|
209
|
+
opts.delete(:tag)
|
210
|
+
opts.delete(:attributes)
|
211
|
+
@engine ||= options[:engine].new(opts)
|
212
|
+
body = @engine.on_slimi_embedded(engine, body, attrs)
|
213
|
+
end
|
214
|
+
|
215
|
+
[:html, :tag, options[:tag], attrs, body]
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Javascript wrapper engine.
|
220
|
+
# Like TagEngine, but can wrap content in html comment or cdata.
|
221
|
+
class JavaScriptEngine < TagEngine
|
222
|
+
disable_option_validator!
|
223
|
+
|
224
|
+
set_options tag: :script, attributes: {}
|
225
|
+
|
226
|
+
def on_slimi_embedded(engine, body, attrs)
|
227
|
+
super(engine, [:html, :js, body], attrs)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Embeds ruby code
|
232
|
+
class RubyEngine < Engine
|
233
|
+
def on_slimi_embedded(_engine, body, _attrs)
|
234
|
+
[:multi, [:newline], [:code, "#{collect_text(body)}\n"]]
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# These engines are executed at compile time, embedded ruby is interpolated
|
239
|
+
register :markdown, InterpolateTiltEngine
|
240
|
+
register :textile, InterpolateTiltEngine
|
241
|
+
register :rdoc, InterpolateTiltEngine
|
242
|
+
|
243
|
+
# These engines are executed at compile time
|
244
|
+
register :coffee, JavaScriptEngine, engine: TiltEngine
|
245
|
+
register :less, TagEngine, tag: :style, attributes: { type: 'text/css' }, engine: TiltEngine
|
246
|
+
register :sass, TagEngine, :pretty, tag: :style, attributes: { type: 'text/css' }, engine: SassEngine
|
247
|
+
register :scss, TagEngine, :pretty, tag: :style, attributes: { type: 'text/css' }, engine: SassEngine
|
248
|
+
|
249
|
+
# Embedded javascript/css
|
250
|
+
register :javascript, JavaScriptEngine
|
251
|
+
register :css, TagEngine, tag: :style, attributes: { type: 'text/css' }
|
252
|
+
|
253
|
+
# Embedded ruby code
|
254
|
+
register :ruby, RubyEngine
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
module Filters
|
5
|
+
# Append missing `end` line to embedded Ruby code in control block.
|
6
|
+
class EndInserter < Base
|
7
|
+
# @param [Array<Array>] expressions
|
8
|
+
def on_multi(*expressions)
|
9
|
+
result = [:multi]
|
10
|
+
prev_indent = false
|
11
|
+
expressions.each do |source|
|
12
|
+
expression = Expression.new(source)
|
13
|
+
if expression.control?
|
14
|
+
raise ::Temple::FilterError, 'Explicit end statements are forbidden.' if expression.end?
|
15
|
+
|
16
|
+
result << code_end if prev_indent && !expression.else?
|
17
|
+
|
18
|
+
prev_indent = expression.if?
|
19
|
+
elsif !expression.newline? && prev_indent
|
20
|
+
result << code_end
|
21
|
+
prev_indent = false
|
22
|
+
end
|
23
|
+
|
24
|
+
result << compile(source)
|
25
|
+
end
|
26
|
+
|
27
|
+
result << code_end if prev_indent
|
28
|
+
result
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# @return [Array]
|
34
|
+
def code_end
|
35
|
+
[:code, 'end']
|
36
|
+
end
|
37
|
+
|
38
|
+
class Expression
|
39
|
+
IF_REGEXP = /\A(if|begin|unless|else|elsif|when|rescue|ensure)\b|\bdo\s*(\|[^|]*\|)?\s*$/.freeze
|
40
|
+
|
41
|
+
ELSE_REGEXP = /\A(else|elsif|when|rescue|ensure)\b/.freeze
|
42
|
+
|
43
|
+
END_REGEXP = /\Aend\b/.freeze
|
44
|
+
|
45
|
+
# @param [Array] expression
|
46
|
+
def initialize(expression)
|
47
|
+
@expression = expression
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Boolean]
|
51
|
+
def control?
|
52
|
+
@expression[0] == :slimi && @expression[1] == :control
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Boolean]
|
56
|
+
def if?
|
57
|
+
@expression[2].match?(IF_REGEXP)
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Boolean]
|
61
|
+
def else?
|
62
|
+
@expression[2].match?(ELSE_REGEXP)
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [Boolean]
|
66
|
+
def end?
|
67
|
+
@expression[2].match?(END_REGEXP)
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [Boolean]
|
71
|
+
def newline?
|
72
|
+
@expression[0] == :newline
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -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
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
module Filters
|
5
|
+
# Handle `[:slimi, :output, escape, code, multi]`.
|
6
|
+
class Output < Base
|
7
|
+
define_options :disable_capture
|
8
|
+
|
9
|
+
IF_REGEXP = /\A(if|unless)\b|\bdo\s*(\|[^|]*\|)?\s*$/.freeze
|
10
|
+
|
11
|
+
# @param [Boolean] escape
|
12
|
+
# @param [String] code
|
13
|
+
# @param [Array] multi
|
14
|
+
# @return [Array]
|
15
|
+
def on_slimi_output(escape, code, multi)
|
16
|
+
if code.match?(IF_REGEXP)
|
17
|
+
tmp = unique_name
|
18
|
+
[
|
19
|
+
:multi,
|
20
|
+
[:block, "#{tmp} = #{code}", options[:disable_capture] ? compile(multi) : [:capture, unique_name, compile(multi)]],
|
21
|
+
[:escape, escape, [:dynamic, tmp]]
|
22
|
+
]
|
23
|
+
else
|
24
|
+
[
|
25
|
+
:multi,
|
26
|
+
[:escape, escape, [:dynamic, code]],
|
27
|
+
multi
|
28
|
+
]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
module Filters
|
5
|
+
# Handle `[:slimi, :text, multi]`.
|
6
|
+
class Text < Base
|
7
|
+
# @param [Symbol] _type
|
8
|
+
# @param [Array] multi
|
9
|
+
# @return [Array]
|
10
|
+
def on_slimi_text(_type, multi)
|
11
|
+
compile(multi)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
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,16 @@
|
|
2
2
|
|
3
3
|
module Slimi
|
4
4
|
module Filters
|
5
|
+
autoload :Amble, 'slimi/filters/amble'
|
6
|
+
autoload :Attribute, 'slimi/filters/attribute'
|
7
|
+
autoload :Base, 'slimi/filters/base'
|
8
|
+
autoload :Control, 'slimi/filters/control'
|
9
|
+
autoload :DoInserter, 'slimi/filters/do_inserter'
|
10
|
+
autoload :Embedded, 'slimi/filters/embedded'
|
11
|
+
autoload :EndInserter, 'slimi/filters/end_inserter'
|
5
12
|
autoload :Interpolation, 'slimi/filters/interpolation'
|
13
|
+
autoload :Output, 'slimi/filters/output'
|
14
|
+
autoload :Text, 'slimi/filters/text'
|
6
15
|
autoload :Unposition, 'slimi/filters/unposition'
|
7
16
|
end
|
8
17
|
end
|
data/lib/slimi/parser.rb
CHANGED
@@ -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
|
@@ -269,9 +269,10 @@ module Slimi
|
|
269
269
|
elsif @scanner.skip(@ruby_attribute_regexp)
|
270
270
|
attribute_name = @scanner[1]
|
271
271
|
escape = @scanner[2].empty?
|
272
|
+
charpos = @scanner.charpos
|
272
273
|
attribute_value = parse_ruby_attribute_value(attribute_delimiter_closing)
|
273
274
|
syntax_error!(Errors::InvalidEmptyAttributeError) if attribute_value.empty?
|
274
|
-
attributes << [:html, :attr, attribute_name, [:
|
275
|
+
attributes << [:html, :attr, attribute_name, [:slimi, :position, charpos, charpos + attribute_value.length, [:slimi, :attrvalue, escape, attribute_value]]]
|
275
276
|
elsif !attribute_delimiter_closing_part_regexp
|
276
277
|
break
|
277
278
|
elsif @scanner.skip(boolean_attribute_regexp)
|
@@ -331,9 +332,9 @@ module Slimi
|
|
331
332
|
|
332
333
|
# @return [Boolean]
|
333
334
|
def parse_html_comment
|
334
|
-
if @scanner.skip(%r{/!})
|
335
|
+
if @scanner.skip(%r{/![ \t]*})
|
335
336
|
text_block = parse_text_block
|
336
|
-
text = [:
|
337
|
+
text = [:slimi, :text, :verbatim, text_block]
|
337
338
|
@stacks.last << [:html, :comment, text]
|
338
339
|
true
|
339
340
|
else
|
@@ -380,7 +381,7 @@ module Slimi
|
|
380
381
|
def parse_verbatim_text_block_inner
|
381
382
|
if @scanner.skip(/([|']) ?/)
|
382
383
|
with_trailing_white_space = @scanner[1] == "'"
|
383
|
-
@stacks.last << [:
|
384
|
+
@stacks.last << [:slimi, :text, :verbatim, parse_text_block]
|
384
385
|
@stacks.last << [:static, ' '] if with_trailing_white_space
|
385
386
|
true
|
386
387
|
else
|
@@ -419,7 +420,7 @@ module Slimi
|
|
419
420
|
if @scanner.skip(/-/)
|
420
421
|
block = [:multi]
|
421
422
|
@scanner.skip(/[ \t]+/)
|
422
|
-
@stacks.last << with_position { [:
|
423
|
+
@stacks.last << with_position { [:slimi, :control, parse_broken_lines, block] }
|
423
424
|
@stacks << block
|
424
425
|
true
|
425
426
|
else
|
@@ -442,7 +443,7 @@ module Slimi
|
|
442
443
|
block = [:multi]
|
443
444
|
@stacks.last << [:static, ' '] if with_trailing_white_space
|
444
445
|
@scanner.skip(/[ \t]+/)
|
445
|
-
@stacks.last << with_position { [:
|
446
|
+
@stacks.last << with_position { [:slimi, :output, escape, parse_broken_lines, block] }
|
446
447
|
@stacks.last << [:static, ' '] if with_leading_white_space
|
447
448
|
@stacks << block
|
448
449
|
else
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
# Render Slim template in response to requests from Rails.
|
5
|
+
class RailsTemplateHandler
|
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
|
14
|
+
end
|
15
|
+
|
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
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Slimi
|
4
|
+
class Railtie < ::Rails::Railtie
|
5
|
+
initializer 'Register Slimi template handler' do
|
6
|
+
::ActiveSupport.on_load(:action_view) do
|
7
|
+
::ActionView::Template.register_template_handler(
|
8
|
+
:slim,
|
9
|
+
RailsTemplateHandler.new
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/slimi/version.rb
CHANGED
data/lib/slimi.rb
CHANGED
@@ -3,8 +3,14 @@
|
|
3
3
|
require_relative 'slimi/version'
|
4
4
|
|
5
5
|
module Slimi
|
6
|
+
autoload :Cli, 'slimi/cli'
|
7
|
+
autoload :Engine, 'slimi/engine'
|
8
|
+
autoload :ErbConverter, 'slimi/erb_converter'
|
6
9
|
autoload :Errors, 'slimi/errors'
|
7
10
|
autoload :Filters, 'slimi/filters'
|
8
11
|
autoload :Parser, 'slimi/parser'
|
12
|
+
autoload :RailsTemplateHandler, 'slimi/rails_template_handler'
|
9
13
|
autoload :Range, 'slimi/range'
|
10
14
|
end
|
15
|
+
|
16
|
+
require_relative 'slimi/railtie' if defined?(Rails)
|
data/slimi.gemspec
CHANGED
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.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:
|
11
|
+
date: 2022-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: temple
|
@@ -24,10 +24,39 @@ 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'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tilt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
27
55
|
description:
|
28
56
|
email:
|
29
57
|
- r7kamura@gmail.com
|
30
|
-
executables:
|
58
|
+
executables:
|
59
|
+
- slimi
|
31
60
|
extensions: []
|
32
61
|
extra_rdoc_files: []
|
33
62
|
files:
|
@@ -42,12 +71,27 @@ files:
|
|
42
71
|
- Rakefile
|
43
72
|
- bin/console
|
44
73
|
- bin/setup
|
74
|
+
- exe/slimi
|
45
75
|
- lib/slimi.rb
|
76
|
+
- lib/slimi/cli.rb
|
77
|
+
- lib/slimi/engine.rb
|
78
|
+
- lib/slimi/erb_converter.rb
|
46
79
|
- lib/slimi/errors.rb
|
47
80
|
- lib/slimi/filters.rb
|
81
|
+
- lib/slimi/filters/amble.rb
|
82
|
+
- lib/slimi/filters/attribute.rb
|
83
|
+
- lib/slimi/filters/base.rb
|
84
|
+
- lib/slimi/filters/control.rb
|
85
|
+
- lib/slimi/filters/do_inserter.rb
|
86
|
+
- lib/slimi/filters/embedded.rb
|
87
|
+
- lib/slimi/filters/end_inserter.rb
|
48
88
|
- lib/slimi/filters/interpolation.rb
|
89
|
+
- lib/slimi/filters/output.rb
|
90
|
+
- lib/slimi/filters/text.rb
|
49
91
|
- lib/slimi/filters/unposition.rb
|
50
92
|
- lib/slimi/parser.rb
|
93
|
+
- lib/slimi/rails_template_handler.rb
|
94
|
+
- lib/slimi/railtie.rb
|
51
95
|
- lib/slimi/range.rb
|
52
96
|
- lib/slimi/version.rb
|
53
97
|
- slimi.gemspec
|