erb-linter 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![test](https://github.com/nebulab/erb-linter/actions/workflows/test.yml/badge.svg)](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
|