erb-linter 0.0.1 → 0.2.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/.github/workflows/test.yml +26 -0
- data/.gitignore +1 -0
- data/README.md +8 -8
- data/bin/rake +29 -0
- data/lib/erb/linter.rb +1 -1
- data/lib/erb/linter/converter.rb +61 -22
- metadata +4 -3
- data/Gemfile.lock +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 44674209663a884ffa87821eea1396fdcfa779c67b7c1480c625b04111ffc645
|
4
|
+
data.tar.gz: f450b5dd3c9321c7f8854dcf68bb6dc38cf348b1cfab3c62b91fb73a6ebf5608
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a37692b76c98aa006fab462b58936a6b00cf4902a3badaf328406622267414abdd32a88c871bf742f10ce6a93793cf39b2239a9bfb55745a2c11a06edbcfc36
|
7
|
+
data.tar.gz: e14e4343a76cf0964e95ad73406a4e271be504ff1319096445778de58ddc2fa777e3638856650135ec6332f5b022d25382621f01d091009b6f7279fe4b0c0c4a
|
@@ -0,0 +1,26 @@
|
|
1
|
+
on:
|
2
|
+
- push
|
3
|
+
- pull_request
|
4
|
+
|
5
|
+
name: test
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
test:
|
9
|
+
name: "ruby ${{ matrix.ruby }}"
|
10
|
+
|
11
|
+
strategy:
|
12
|
+
matrix:
|
13
|
+
os: [ 'ubuntu-latest' ]
|
14
|
+
ruby: [ "3.0", "2.7", "2.6", "2.5" ]
|
15
|
+
|
16
|
+
runs-on: ${{ matrix.os }}
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- uses: actions/checkout@v2
|
20
|
+
- uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby }}
|
23
|
+
- name: Setup project
|
24
|
+
run: bin/setup
|
25
|
+
- name: Run test
|
26
|
+
run: bin/rake
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
<a href="https://nebulab.it?utm_source=github&utm_medium=badge"><img src="https://img.shields.io/static/v1?label=Nebulab&message=Open+Source&color=%235dbefd&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMQSURBVHgBrZZNTxNRFIbfczsgIMQiLBCRFDaGhUr9A9iiIa5EEneIwE/AlRsNv8KlIKwFl35RTUBX8rFBdiVKAgqmXSCY0M71nJl+zJTOdKh9k6Yzc8/cZ86555x7CQE0mji5hSyGlQoNaOgIPwrnhtIArWszu4EQFudjdR8rzUV+gw8/ZMZB9IwvIwimJJGafhmjWZwFOJ7QkYzWCwTdj+qUDJGKz8Rou3RAlT4YS+hHWW2u/QdM1MNzrI6+zwyXDrg8FANStIDaSXOIJ5whLgAljOIZiglRK6U4vDfz4S2ElGGJWsEaQkCTUbhtNbV+lb+xgFY2Bs9ET0h/GzBxlfAkqnCUKY5xKfVLbsi1/R126lcF6WgCYp2ES42EBp6tvQFY+alLTUlrUxizJEVNWiVwBkVagGg7oe+CDclLYOfrgMdfTBz8PfWa1lkzbsDEsH/5FyF9YUK0zQ1xwpoZtsm9pwxMRLyA9wyi0A2Jcjl1NNqeeEFEimxYPkmWd014ikIDnDTeBb53DOweaRxnvWGyhnmYfPZWGt487sNi6lsK67/lZ1oZGOtUaD3nhtU7etXXfe0VzrzCBgLKCR68rNDX6oaJlvd0xXnklbSfgSTL/QghXF8EP980cVKyVL/Ys9UDVFJa8Tdt+1lYmcmJM3Vd4UEvWeslRf32h9ubrVRl77gBrCto85OfUU+LXTMGx+JuN2Hoin3/Zkfjj6ObBAknV+KG4jpc9BqXMEpiCMz6Z9ZQ12kvJZxb6co4Zr1W83esY8F2OYsIe+eEyfTiVXczCl7uM2wliHfMEJaRc3Wa++mLUotrF4EW7h6f94Dvh6aVFM60Fy8Xkya+BfBOjh5yUWhqY0vmKi9q1GnVxZ7sHKIWSs7FQ71yUagkRTTCfymnVY1gsgHHC5z8hbUjaz0Fr8ZanXhX0pPOw5SrV8wNGjNscMrTKpXKaj05f9twVYHnMZGPHEuwTwEBNi+3NGiNt6GRcsfEIAfhp2cAV3cQLtXoOz7q8+ZJRLx3kmxn4dy7aas1SrfiBpKraV/9A+PSJLDAXLUvAAAAAElFTkSuQmCC"></a>
|
4
4
|
|
5
|
-
|
5
|
+
[](https://github.com/nebulab/erb-linter/actions/workflows/test.yml)
|
6
|
+
|
7
|
+
It's all too easy to introduce errors inside ERB files, unclosed tags, wrong attribute names, bad indentation.
|
6
8
|
|
7
9
|
ERB::Linter can check for those errors by turning your ERB tags into HTML-ish tags and run a proper HTML linter on the result:
|
8
10
|
|
@@ -45,13 +47,9 @@ Add this line to your application's Gemfile:
|
|
45
47
|
gem 'erb-linter'
|
46
48
|
```
|
47
49
|
|
48
|
-
And
|
49
|
-
|
50
|
-
$ bundle install
|
50
|
+
And add `linthtml` to yarn:
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
$ gem install erb-linter
|
52
|
+
$ yarn add --dev @linthtml/linthtml
|
55
53
|
|
56
54
|
## Usage
|
57
55
|
|
@@ -81,7 +79,9 @@ ERB::Linter::Task.new do |task|
|
|
81
79
|
end
|
82
80
|
```
|
83
81
|
|
84
|
-
|
82
|
+
### Example linthtml configuration
|
83
|
+
|
84
|
+
And then add a `linthtml` configuration like this:
|
85
85
|
|
86
86
|
`.linthtmlrc.js`
|
87
87
|
|
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/lib/erb/linter.rb
CHANGED
data/lib/erb/linter/converter.rb
CHANGED
@@ -2,43 +2,82 @@
|
|
2
2
|
|
3
3
|
require "cgi"
|
4
4
|
require "ripper"
|
5
|
+
require 'securerandom'
|
6
|
+
require 'strscan'
|
5
7
|
|
6
8
|
module ERB::Linter::Converter
|
7
9
|
extend self
|
8
10
|
|
9
|
-
#
|
11
|
+
# https://stackoverflow.com/a/317081
|
12
|
+
ATTR_NAME = %r{[^\r\n\t\f\v= '"<>]*[^\r\n\t\f\v= '"<>/]} # not ending with a slash
|
13
|
+
UNQUOTED_VALUE = ATTR_NAME
|
14
|
+
UNQUOTED_ATTR = %r{#{ATTR_NAME}=#{UNQUOTED_VALUE}}
|
15
|
+
SINGLE_QUOTE_ATTR = %r{(?:#{ATTR_NAME}='[^']*')}
|
16
|
+
DOUBLE_QUOTE_ATTR = %r{(?:#{ATTR_NAME}="[^"]*")}
|
17
|
+
|
18
|
+
ERB_TAG = %r{<%.*?%>}
|
19
|
+
HTML_ATTR = %r{\s+#{SINGLE_QUOTE_ATTR}|\s+#{DOUBLE_QUOTE_ATTR}|\s+#{UNQUOTED_ATTR}|\s+#{ATTR_NAME}}
|
20
|
+
HTML_TAG = %r{(<\w+)((?:#{HTML_ATTR})*)(\s*)(/>|>)}m
|
21
|
+
|
22
|
+
# (credit goes to the Deface gem for the original implementation)
|
10
23
|
def erb2html(source)
|
11
24
|
source = +source
|
12
25
|
|
13
|
-
# all
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
]
|
21
|
-
|
22
|
-
# rubocop:disable Linter/ShadowingOuterLocalVariable
|
23
|
-
replace_line = erb_attrs_regexs.inject(line.clone) do |replace_line, regex|
|
24
|
-
replace_line = line.scan(regex).inject(replace_line) do |replace_line, match|
|
25
|
-
replace_line.sub("#{match[0]}#{match[1]}#{match[2]}#{match[3]}#{match[2]}") { "data-erb-#{match[0]}=\"#{CGI.escapeHTML(match[3])}\"" }
|
26
|
-
end
|
26
|
+
# encode all erb tags so that the HTML looks valid
|
27
|
+
erb_tags = {}
|
28
|
+
source.gsub!(ERB_TAG) do |tag|
|
29
|
+
uid = ["ERB_", SecureRandom.uuid].join.delete('-')
|
30
|
+
erb_tags[uid] = tag
|
31
|
+
uid
|
32
|
+
end
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
erb_tags_matcher = Regexp.union(erb_tags.keys)
|
35
|
+
|
36
|
+
# transform/escape all the erb-attributes first
|
37
|
+
source.gsub!(HTML_TAG).each do |match|
|
38
|
+
line = Regexp.last_match.to_a[1..-1]
|
39
|
+
tag = [line[0], line[2]+line[3]]
|
40
|
+
|
41
|
+
# scan each attribute into an array
|
42
|
+
attr_scanner = StringScanner.new(line[1])
|
43
|
+
attributes = []
|
44
|
+
attributes << (attr_scanner.scan(HTML_ATTR) or raise "Can't scan: #{attr_scanner.string}") until attr_scanner.eos?
|
45
|
+
# attributes.compact!
|
31
46
|
|
32
47
|
i = -1
|
48
|
+
attributes.map! do |attribute|
|
49
|
+
if attribute.match?(erb_tags_matcher)
|
50
|
+
space, attribute = attribute.scan(/\A(\s+)(.*)\z/m).flatten
|
51
|
+
attribute.gsub!(erb_tags_matcher, erb_tags)
|
52
|
+
|
53
|
+
attribute =
|
54
|
+
case attribute
|
55
|
+
when /\A#{ERB_TAG}\z/
|
56
|
+
%{data-erb-#{i += 1}="#{CGI.escapeHTML(attribute)}"}
|
57
|
+
when /\A#{ATTR_NAME}=/
|
58
|
+
name, value = attribute.split("=", 2)
|
59
|
+
quote = '"'
|
60
|
+
if value.match(/\A['"]/)
|
61
|
+
quote = value[0]
|
62
|
+
value = value[1...-1]
|
63
|
+
end
|
64
|
+
%{data-erb-#{name}=#{quote}#{CGI.escapeHTML(value)}#{quote}}
|
65
|
+
else
|
66
|
+
raise "Don't know how to process attribute: #{attribute.inspect}"
|
67
|
+
end
|
33
68
|
|
34
|
-
|
35
|
-
|
36
|
-
|
69
|
+
"#{space}#{attribute}"
|
70
|
+
else
|
71
|
+
attribute
|
72
|
+
end
|
37
73
|
end
|
38
74
|
|
39
|
-
|
75
|
+
[tag[0], *attributes, tag[1]].join
|
40
76
|
end
|
41
77
|
|
78
|
+
# restore the encoded erb tags
|
79
|
+
source.gsub!(erb_tags_matcher, erb_tags)
|
80
|
+
|
42
81
|
# replaces all <% %> not inside opening html tags
|
43
82
|
replacements = [
|
44
83
|
{ %r{<%\s*end\s*-?%>} => "</erb>" },
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: erb-linter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elia Schito
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -31,13 +31,14 @@ executables: []
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files: []
|
33
33
|
files:
|
34
|
+
- ".github/workflows/test.yml"
|
34
35
|
- ".gitignore"
|
35
36
|
- Gemfile
|
36
|
-
- Gemfile.lock
|
37
37
|
- LICENSE.txt
|
38
38
|
- README.md
|
39
39
|
- Rakefile
|
40
40
|
- bin/console
|
41
|
+
- bin/rake
|
41
42
|
- bin/setup
|
42
43
|
- erb-linter.gemspec
|
43
44
|
- lib/erb/linter.rb
|
data/Gemfile.lock
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
erb-linter (0.0.1)
|
5
|
-
rake
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
minitest (5.14.4)
|
11
|
-
rake (13.0.3)
|
12
|
-
|
13
|
-
PLATFORMS
|
14
|
-
x86_64-darwin-20
|
15
|
-
|
16
|
-
DEPENDENCIES
|
17
|
-
erb-linter!
|
18
|
-
minitest (~> 5.0)
|
19
|
-
rake (~> 13.0)
|
20
|
-
|
21
|
-
BUNDLED WITH
|
22
|
-
2.2.3
|