slimi 0.4.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|