haml_lint 0.13.0 → 0.14.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/config/default.yml +1 -0
- data/lib/haml_lint/cli.rb +25 -8
- data/lib/haml_lint/configuration.rb +56 -34
- data/lib/haml_lint/configuration_loader.rb +22 -6
- data/lib/haml_lint/constants.rb +1 -1
- data/lib/haml_lint/document.rb +102 -0
- data/lib/haml_lint/file_finder.rb +14 -5
- data/lib/haml_lint/lint.rb +17 -1
- data/lib/haml_lint/linter/alt_text.rb +1 -1
- data/lib/haml_lint/linter/class_attribute_with_static_value.rb +2 -2
- data/lib/haml_lint/linter/classes_before_ids.rb +2 -2
- data/lib/haml_lint/linter/consecutive_comments.rb +3 -5
- data/lib/haml_lint/linter/consecutive_silent_scripts.rb +5 -5
- data/lib/haml_lint/linter/empty_script.rb +1 -1
- data/lib/haml_lint/linter/html_attributes.rb +2 -2
- data/lib/haml_lint/linter/implicit_div.rb +3 -3
- data/lib/haml_lint/linter/leading_comment_space.rb +1 -1
- data/lib/haml_lint/linter/line_length.rb +2 -2
- data/lib/haml_lint/linter/multiline_pipe.rb +3 -3
- data/lib/haml_lint/linter/multiline_script.rb +3 -3
- data/lib/haml_lint/linter/object_reference_attributes.rb +1 -1
- data/lib/haml_lint/linter/rubocop.rb +60 -34
- data/lib/haml_lint/linter/ruby_comments.rb +1 -1
- data/lib/haml_lint/linter/space_before_script.rb +4 -4
- data/lib/haml_lint/linter/space_inside_hash_attributes.rb +2 -2
- data/lib/haml_lint/linter/tag_name.rb +1 -1
- data/lib/haml_lint/linter/trailing_whitespace.rb +2 -2
- data/lib/haml_lint/linter/unnecessary_interpolation.rb +3 -3
- data/lib/haml_lint/linter/unnecessary_string_output.rb +10 -3
- data/lib/haml_lint/linter.rb +30 -10
- data/lib/haml_lint/linter_registry.rb +13 -2
- data/lib/haml_lint/linter_selector.rb +77 -0
- data/lib/haml_lint/node_transformer.rb +5 -5
- data/lib/haml_lint/options.rb +13 -6
- data/lib/haml_lint/rake_task.rb +18 -3
- data/lib/haml_lint/report.rb +7 -0
- data/lib/haml_lint/reporter/default_reporter.rb +2 -2
- data/lib/haml_lint/reporter/json_reporter.rb +15 -10
- data/lib/haml_lint/reporter.rb +17 -11
- data/lib/haml_lint/{script_extractor.rb → ruby_extractor.rb} +26 -17
- data/lib/haml_lint/runner.rb +44 -44
- data/lib/haml_lint/tree/node.rb +7 -8
- data/lib/haml_lint/utils.rb +88 -21
- data/lib/haml_lint/version.rb +1 -1
- data/lib/haml_lint.rb +2 -1
- metadata +5 -4
- data/lib/haml_lint/parser.rb +0 -87
@@ -1,29 +1,34 @@
|
|
1
1
|
module HamlLint
|
2
2
|
# Outputs report as a JSON document.
|
3
3
|
class Reporter::JsonReporter < Reporter
|
4
|
-
def
|
4
|
+
def display_report(report)
|
5
|
+
lints = report.lints
|
5
6
|
grouped = lints.group_by(&:filename)
|
6
7
|
|
7
|
-
|
8
|
-
metadata:
|
9
|
-
hamllint_version: VERSION,
|
10
|
-
ruby_engine: RUBY_ENGINE,
|
11
|
-
ruby_patchlevel: RUBY_PATCHLEVEL.to_s,
|
12
|
-
ruby_platform: RUBY_PLATFORM,
|
13
|
-
},
|
8
|
+
report_hash = {
|
9
|
+
metadata: metadata,
|
14
10
|
files: grouped.map { |l| map_file(l) },
|
15
11
|
summary: {
|
16
12
|
offense_count: lints.length,
|
17
13
|
target_file_count: grouped.length,
|
18
|
-
inspected_file_count: files.length,
|
14
|
+
inspected_file_count: report.files.length,
|
19
15
|
},
|
20
16
|
}
|
21
17
|
|
22
|
-
log.log
|
18
|
+
log.log report_hash.to_json
|
23
19
|
end
|
24
20
|
|
25
21
|
private
|
26
22
|
|
23
|
+
def metadata
|
24
|
+
{
|
25
|
+
haml_lint_version: HamlLint::VERSION,
|
26
|
+
ruby_engine: RUBY_ENGINE,
|
27
|
+
ruby_patchlevel: RUBY_PATCHLEVEL.to_s,
|
28
|
+
ruby_platform: RUBY_PLATFORM,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
27
32
|
def map_file(file)
|
28
33
|
{
|
29
34
|
path: file.first,
|
data/lib/haml_lint/reporter.rb
CHANGED
@@ -1,36 +1,42 @@
|
|
1
1
|
module HamlLint
|
2
|
-
# Abstract lint reporter. Subclass and override {#
|
2
|
+
# Abstract lint reporter. Subclass and override {#display_report} to
|
3
3
|
# implement a custom lint reporter.
|
4
4
|
#
|
5
5
|
# @abstract
|
6
6
|
class Reporter
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
# Creates the reporter that will display the given report.
|
8
|
+
#
|
10
9
|
# @param logger [HamlLint::Logger]
|
11
|
-
|
12
|
-
def initialize(logger, report)
|
10
|
+
def initialize(logger)
|
13
11
|
@log = logger
|
14
|
-
@lints = report.lints
|
15
|
-
@files = report.files
|
16
12
|
end
|
17
13
|
|
18
14
|
# Implemented by subclasses to display lints from a {HamlLint::Report}.
|
19
|
-
|
20
|
-
|
15
|
+
#
|
16
|
+
# @param report [HamlLint::Report]
|
17
|
+
def display_report(report)
|
18
|
+
raise NotImplementedError,
|
19
|
+
"Implement `display_report` to display #{report}"
|
21
20
|
end
|
22
21
|
|
23
|
-
# Keep tracking all the descendants of this class for the list of available
|
22
|
+
# Keep tracking all the descendants of this class for the list of available
|
23
|
+
# reporters.
|
24
|
+
#
|
25
|
+
# @return [Array<Class>]
|
24
26
|
def self.descendants
|
25
27
|
@descendants ||= []
|
26
28
|
end
|
27
29
|
|
30
|
+
# Executed when this class is subclassed.
|
31
|
+
#
|
32
|
+
# @param descendant [Class]
|
28
33
|
def self.inherited(descendant)
|
29
34
|
descendants << descendant
|
30
35
|
end
|
31
36
|
|
32
37
|
private
|
33
38
|
|
39
|
+
# @return [HamlLint::Logger] logger to send output to
|
34
40
|
attr_reader :log
|
35
41
|
end
|
36
42
|
end
|
@@ -19,24 +19,33 @@ module HamlLint
|
|
19
19
|
# link_to 'Sign In', sign_in_path
|
20
20
|
# end
|
21
21
|
#
|
22
|
-
|
22
|
+
# The translation won't be perfect, and won't make any real sense, but the
|
23
|
+
# relationship between variable declarations/uses and the flow control graph
|
24
|
+
# will remain intact.
|
25
|
+
class RubyExtractor
|
23
26
|
include HamlVisitor
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
# Stores the extracted source and a map of lines of generated source to the
|
29
|
+
# original source that created them.
|
30
|
+
#
|
31
|
+
# @attr_reader source [String] generated source code
|
32
|
+
# @attr_reader source_map [Hash] map of line numbers from generated source
|
33
|
+
# to original source line number
|
34
|
+
RubySource = Struct.new(:source, :source_map)
|
35
|
+
|
36
|
+
# Extracts Ruby code from Sexp representing a Slim document.
|
37
|
+
#
|
38
|
+
# @param document [HamlLint::Document]
|
39
|
+
# @return [HamlLint::RubyExtractor::RubySource]
|
40
|
+
def extract(document)
|
41
|
+
visit(document.tree)
|
42
|
+
RubySource.new(@source_lines.join("\n"), @source_map)
|
34
43
|
end
|
35
44
|
|
36
45
|
def visit_root(_node)
|
37
|
-
@
|
38
|
-
@total_lines = 0
|
46
|
+
@source_lines = []
|
39
47
|
@source_map = {}
|
48
|
+
@line_count = 0
|
40
49
|
@indent_level = 0
|
41
50
|
|
42
51
|
yield # Collect lines of code from children
|
@@ -104,8 +113,8 @@ module HamlLint
|
|
104
113
|
end
|
105
114
|
else
|
106
115
|
add_line('puts', node)
|
107
|
-
HamlLint::Utils.extract_interpolated_values(node.text) do |interpolated_code|
|
108
|
-
add_line(interpolated_code, node)
|
116
|
+
HamlLint::Utils.extract_interpolated_values(node.text) do |interpolated_code, line|
|
117
|
+
add_line(interpolated_code, node.line + line)
|
109
118
|
end
|
110
119
|
end
|
111
120
|
end
|
@@ -140,7 +149,7 @@ module HamlLint
|
|
140
149
|
|
141
150
|
indent = (' ' * 2 * indent_level)
|
142
151
|
|
143
|
-
@
|
152
|
+
@source_lines << indent + code
|
144
153
|
|
145
154
|
original_line =
|
146
155
|
node_or_line.respond_to?(:line) ? node_or_line.line : node_or_line
|
@@ -149,8 +158,8 @@ module HamlLint
|
|
149
158
|
# resulting code will span multiple lines, so we need to create a
|
150
159
|
# mapping for each line.
|
151
160
|
(code.count("\n") + 1).times do
|
152
|
-
@
|
153
|
-
@source_map[@
|
161
|
+
@line_count += 1
|
162
|
+
@source_map[@line_count] = original_line
|
154
163
|
end
|
155
164
|
end
|
156
165
|
|
data/lib/haml_lint/runner.rb
CHANGED
@@ -1,76 +1,76 @@
|
|
1
1
|
module HamlLint
|
2
2
|
# Responsible for running the applicable linters against the desired files.
|
3
3
|
class Runner
|
4
|
-
# Make the list of applicable files available
|
5
|
-
attr_reader :files
|
6
|
-
|
7
4
|
# Runs the appropriate linters against the desired files given the specified
|
8
5
|
# options.
|
9
6
|
#
|
10
|
-
# @param
|
11
|
-
# @
|
7
|
+
# @param [Hash] options
|
8
|
+
# @option options :config_file [String] path of configuration file to load
|
9
|
+
# @option options :config [HamlLint::Configuration] configuration to use
|
10
|
+
# @option options :excluded_files [Array<String>]
|
11
|
+
# @option options :included_linters [Array<String>]
|
12
|
+
# @option options :excluded_linters [Array<String>]
|
12
13
|
# @return [HamlLint::Report] a summary of all lints found
|
13
14
|
def run(options = {})
|
14
15
|
config = load_applicable_config(options)
|
15
|
-
files = extract_applicable_files(
|
16
|
-
linters = extract_enabled_linters(config, options)
|
16
|
+
files = extract_applicable_files(config, options)
|
17
17
|
|
18
|
-
|
18
|
+
linter_selector = HamlLint::LinterSelector.new(config, options)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
linters.each do |linter|
|
26
|
-
@lints += linter.lints
|
27
|
-
end
|
20
|
+
lints = files.map do |file|
|
21
|
+
collect_lints(file, linter_selector, config)
|
22
|
+
end.flatten
|
28
23
|
|
29
|
-
HamlLint::Report.new(
|
24
|
+
HamlLint::Report.new(lints, files)
|
30
25
|
end
|
31
26
|
|
32
27
|
private
|
33
28
|
|
29
|
+
# Returns the {HamlLint::Configuration} that should be used given the
|
30
|
+
# specified options.
|
31
|
+
#
|
32
|
+
# @param options [Hash]
|
33
|
+
# @return [HamlLint::Configuration]
|
34
34
|
def load_applicable_config(options)
|
35
35
|
if options[:config_file]
|
36
36
|
HamlLint::ConfigurationLoader.load_file(options[:config_file])
|
37
|
+
elsif options[:config]
|
38
|
+
options[:config]
|
37
39
|
else
|
38
40
|
HamlLint::ConfigurationLoader.load_applicable_config
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
(included_linters - excluded_linters).map do |linter_class|
|
54
|
-
linter_config = config.for_linter(linter_class)
|
55
|
-
linter_class.new(linter_config) if linter_config['enabled']
|
56
|
-
end.compact
|
57
|
-
end
|
58
|
-
|
59
|
-
def find_lints(file, linters, config)
|
60
|
-
parser = Parser.new(file, config.hash)
|
61
|
-
|
62
|
-
linters.each do |linter|
|
63
|
-
linter.run(parser)
|
44
|
+
# Runs all provided linters using the specified config against the given
|
45
|
+
# file.
|
46
|
+
#
|
47
|
+
# @param file [String] path to file to lint
|
48
|
+
# @param linter_selector [HamlLint::LinterSelector]
|
49
|
+
# @param config [HamlLint::Configuration]
|
50
|
+
def collect_lints(file, linter_selector, config)
|
51
|
+
begin
|
52
|
+
document = HamlLint::Document.new(File.read(file), file: file, config: config)
|
53
|
+
rescue Haml::Error => ex
|
54
|
+
return [HamlLint::Lint.new(nil, file, ex.line, ex.to_s, :error)]
|
64
55
|
end
|
65
|
-
|
66
|
-
|
56
|
+
|
57
|
+
linter_selector.linters_for_file(file).map do |linter|
|
58
|
+
linter.run(document)
|
59
|
+
end.flatten
|
67
60
|
end
|
68
61
|
|
69
|
-
|
62
|
+
# Returns the list of files that should be linted given the specified
|
63
|
+
# configuration and options.
|
64
|
+
#
|
65
|
+
# @param config [HamlLint::Configuration]
|
66
|
+
# @param options [Hash]
|
67
|
+
# @return [Array<String>]
|
68
|
+
def extract_applicable_files(config, options)
|
70
69
|
included_patterns = options[:files]
|
71
|
-
|
70
|
+
excluded_patterns = config['exclude']
|
71
|
+
excluded_patterns += options.fetch(:excluded_files, [])
|
72
72
|
|
73
|
-
HamlLint::FileFinder.new(config).find(included_patterns,
|
73
|
+
HamlLint::FileFinder.new(config).find(included_patterns, excluded_patterns)
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
data/lib/haml_lint/tree/node.rb
CHANGED
@@ -14,12 +14,11 @@ module HamlLint::Tree
|
|
14
14
|
|
15
15
|
# Creates a node wrapping the given {Haml::Parser::ParseNode} struct.
|
16
16
|
#
|
17
|
-
# @param
|
17
|
+
# @param document [HamlLint::Document] Haml document that created this node
|
18
18
|
# @param parse_node [Haml::Parser::ParseNode] parse node created by HAML's parser
|
19
|
-
def initialize(
|
20
|
-
# TODO: Change signature to take source code object, not parser
|
19
|
+
def initialize(document, parse_node)
|
21
20
|
@line = parse_node.line
|
22
|
-
@
|
21
|
+
@document = document
|
23
22
|
@value = parse_node.value
|
24
23
|
@type = parse_node.type
|
25
24
|
end
|
@@ -50,12 +49,12 @@ module HamlLint::Tree
|
|
50
49
|
if next_node
|
51
50
|
next_node.line - 1
|
52
51
|
else
|
53
|
-
@
|
52
|
+
@document.source_lines.count + 1
|
54
53
|
end
|
55
54
|
|
56
|
-
@
|
57
|
-
|
58
|
-
|
55
|
+
@document.source_lines[@line - 1...next_node_line]
|
56
|
+
.join("\n")
|
57
|
+
.gsub(/^\s*\z/m, '') # Remove blank lines at the end
|
59
58
|
end
|
60
59
|
|
61
60
|
def inspect
|
data/lib/haml_lint/utils.rb
CHANGED
@@ -3,56 +3,123 @@ module HamlLint
|
|
3
3
|
module Utils
|
4
4
|
module_function
|
5
5
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
6
|
+
# Returns whether a glob pattern (or any of a list of patterns) matches the
|
7
|
+
# specified file.
|
8
|
+
#
|
9
|
+
# This is defined here so our file globbing options are consistent
|
10
|
+
# everywhere we perform globbing.
|
11
|
+
#
|
12
|
+
# @param glob [String, Array]
|
13
|
+
# @param file [String]
|
14
|
+
# @return [Boolean]
|
15
|
+
def any_glob_matches?(globs_or_glob, file)
|
16
|
+
Array(globs_or_glob).any? do |glob|
|
17
|
+
::File.fnmatch?(glob, file,
|
18
|
+
::File::FNM_PATHNAME | # Wildcards don't match path separators
|
19
|
+
::File::FNM_DOTMATCH) # `*` wildcard matches dotfiles
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Yields interpolated values within a block of text.
|
24
|
+
#
|
25
|
+
# @param text [String]
|
26
|
+
# @yield Passes interpolated code and line number that code appears on in
|
27
|
+
# the text.
|
28
|
+
# @yieldparam interpolated_code [String] code that was interpolated
|
29
|
+
# @yieldparam line [Integer] line number code appears on in text
|
30
|
+
def extract_interpolated_values(text) # rubocop:disable Metrics/AbcSize
|
31
|
+
dumped_text = text.dump
|
32
|
+
newline_positions = extract_substring_positions(dumped_text, '\\\n')
|
33
|
+
|
34
|
+
Haml::Util.handle_interpolation(dumped_text) do |scan|
|
35
|
+
line = (newline_positions.find_index { |marker| scan.pos <= marker } ||
|
36
|
+
newline_positions.size) + 1
|
37
|
+
|
9
38
|
escape_count = (scan[2].size - 1) / 2
|
10
|
-
|
39
|
+
break unless escape_count.even?
|
11
40
|
|
12
41
|
dumped_interpolated_str = Haml::Util.balance(scan, '{', '}', 1)[0][0...-1]
|
13
42
|
|
14
43
|
# Hacky way to turn a dumped string back into a regular string
|
15
|
-
yield eval('"' + dumped_interpolated_str + '"') # rubocop:disable Eval
|
44
|
+
yield [eval('"' + dumped_interpolated_str + '"'), line] # rubocop:disable Eval
|
16
45
|
end
|
17
46
|
end
|
18
47
|
|
48
|
+
# Returns indexes of all occurrences of a substring within a string.
|
49
|
+
#
|
50
|
+
# Note, this will not return overlaping substrings, so searching for "aa"
|
51
|
+
# in "aaa" will only find one substring, not two.
|
52
|
+
#
|
53
|
+
# @param text [String] the text to search
|
54
|
+
# @param substr [String] the substring to search for
|
55
|
+
# @return [Array<Integer>] list of indexes where the substring occurs
|
56
|
+
def extract_substring_positions(text, substr)
|
57
|
+
positions = []
|
58
|
+
scanner = StringScanner.new(text)
|
59
|
+
positions << scanner.pos while scanner.scan(/(.*?)#{substr}/)
|
60
|
+
positions
|
61
|
+
end
|
62
|
+
|
19
63
|
# Converts a string containing underscores/hyphens/spaces into CamelCase.
|
20
64
|
def camel_case(str)
|
21
65
|
str.split(/_|-| /).map { |part| part.sub(/^\w/) { |c| c.upcase } }.join
|
22
66
|
end
|
23
67
|
|
24
|
-
# Find all consecutive
|
25
|
-
#
|
68
|
+
# Find all consecutive items satisfying the given block of a minimum size,
|
69
|
+
# yielding each group of consecutive items to the provided block.
|
26
70
|
#
|
27
71
|
# @param items [Array]
|
28
|
-
# @param min_size [Fixnum] minimum number of consecutive items before
|
29
|
-
# yielding
|
30
72
|
# @param satisfies [Proc] function that takes an item and returns true/false
|
31
|
-
|
32
|
-
|
73
|
+
# @param min_consecutive [Fixnum] minimum number of consecutive items before
|
74
|
+
# yielding the group
|
75
|
+
# @yield Passes list of consecutive items all matching the criteria defined
|
76
|
+
# by the `satisfies` {Proc} to the provided block
|
77
|
+
# @yieldparam group [Array] List of consecutive items
|
78
|
+
# @yieldreturn [Boolean] block should return whether item matches criteria
|
79
|
+
# for inclusion
|
80
|
+
def for_consecutive_items(items, satisfies, min_consecutive = 2)
|
81
|
+
current_index = -1
|
33
82
|
|
34
|
-
while (
|
35
|
-
next unless satisfies[items[
|
83
|
+
while (current_index += 1) < items.count
|
84
|
+
next unless satisfies[items[current_index]]
|
36
85
|
|
37
|
-
count = count_consecutive(items,
|
38
|
-
next unless count >=
|
86
|
+
count = count_consecutive(items, current_index, &satisfies)
|
87
|
+
next unless count >= min_consecutive
|
39
88
|
|
40
89
|
# Yield the chunk of consecutive items
|
41
|
-
yield items[
|
90
|
+
yield items[current_index...(current_index + count)]
|
42
91
|
|
43
|
-
|
92
|
+
current_index += count # Skip this patch of consecutive items to find more
|
44
93
|
end
|
45
94
|
end
|
46
95
|
|
47
96
|
# Count the number of consecutive items satisfying the given {Proc}.
|
48
97
|
#
|
49
98
|
# @param items [Array]
|
50
|
-
# @param offset [Fixnum] index to start searching
|
51
|
-
# @
|
52
|
-
|
99
|
+
# @param offset [Fixnum] index to start searching from
|
100
|
+
# @yield [item] Passes item to the provided block.
|
101
|
+
# @yieldparam item [Object] Item to evaluate as matching criteria for
|
102
|
+
# inclusion
|
103
|
+
# @yieldreturn [Boolean] whether to include the item
|
104
|
+
# @return [Integer]
|
105
|
+
def count_consecutive(items, offset = 0, &block)
|
53
106
|
count = 1
|
54
|
-
count += 1 while (offset + count < items.count) &&
|
107
|
+
count += 1 while (offset + count < items.count) && block.call(items[offset + count])
|
55
108
|
count
|
56
109
|
end
|
110
|
+
|
111
|
+
# Calls a block of code with a modified set of environment variables,
|
112
|
+
# restoring them once the code has executed.
|
113
|
+
def with_environment(env)
|
114
|
+
old_env = {}
|
115
|
+
env.each do |var, value|
|
116
|
+
old_env[var] = ENV[var.to_s]
|
117
|
+
ENV[var.to_s] = value
|
118
|
+
end
|
119
|
+
|
120
|
+
yield
|
121
|
+
ensure
|
122
|
+
old_env.each { |var, value| ENV[var.to_s] = value }
|
123
|
+
end
|
57
124
|
end
|
58
125
|
end
|
data/lib/haml_lint/version.rb
CHANGED
data/lib/haml_lint.rb
CHANGED
@@ -2,7 +2,7 @@ require 'haml_lint/constants'
|
|
2
2
|
require 'haml_lint/exceptions'
|
3
3
|
require 'haml_lint/configuration'
|
4
4
|
require 'haml_lint/configuration_loader'
|
5
|
-
require 'haml_lint/
|
5
|
+
require 'haml_lint/document'
|
6
6
|
require 'haml_lint/haml_visitor'
|
7
7
|
require 'haml_lint/lint'
|
8
8
|
require 'haml_lint/linter_registry'
|
@@ -11,6 +11,7 @@ require 'haml_lint/linter'
|
|
11
11
|
require 'haml_lint/logger'
|
12
12
|
require 'haml_lint/reporter'
|
13
13
|
require 'haml_lint/report'
|
14
|
+
require 'haml_lint/linter_selector'
|
14
15
|
require 'haml_lint/file_finder'
|
15
16
|
require 'haml_lint/runner'
|
16
17
|
require 'haml_lint/utils'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml_lint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brigade Engineering
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-06-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: haml
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- lib/haml_lint/configuration.rb
|
98
98
|
- lib/haml_lint/configuration_loader.rb
|
99
99
|
- lib/haml_lint/constants.rb
|
100
|
+
- lib/haml_lint/document.rb
|
100
101
|
- lib/haml_lint/exceptions.rb
|
101
102
|
- lib/haml_lint/file_finder.rb
|
102
103
|
- lib/haml_lint/haml_visitor.rb
|
@@ -124,18 +125,18 @@ files:
|
|
124
125
|
- lib/haml_lint/linter/unnecessary_interpolation.rb
|
125
126
|
- lib/haml_lint/linter/unnecessary_string_output.rb
|
126
127
|
- lib/haml_lint/linter_registry.rb
|
128
|
+
- lib/haml_lint/linter_selector.rb
|
127
129
|
- lib/haml_lint/logger.rb
|
128
130
|
- lib/haml_lint/node_transformer.rb
|
129
131
|
- lib/haml_lint/options.rb
|
130
|
-
- lib/haml_lint/parser.rb
|
131
132
|
- lib/haml_lint/rake_task.rb
|
132
133
|
- lib/haml_lint/report.rb
|
133
134
|
- lib/haml_lint/reporter.rb
|
134
135
|
- lib/haml_lint/reporter/default_reporter.rb
|
135
136
|
- lib/haml_lint/reporter/json_reporter.rb
|
137
|
+
- lib/haml_lint/ruby_extractor.rb
|
136
138
|
- lib/haml_lint/ruby_parser.rb
|
137
139
|
- lib/haml_lint/runner.rb
|
138
|
-
- lib/haml_lint/script_extractor.rb
|
139
140
|
- lib/haml_lint/tree/comment_node.rb
|
140
141
|
- lib/haml_lint/tree/doctype_node.rb
|
141
142
|
- lib/haml_lint/tree/filter_node.rb
|
data/lib/haml_lint/parser.rb
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'haml'
|
2
|
-
|
3
|
-
module HamlLint
|
4
|
-
# Parses a HAML document for inspection by linters.
|
5
|
-
class Parser
|
6
|
-
attr_reader :contents, :filename, :lines, :tree
|
7
|
-
|
8
|
-
# Creates a parser containing the parse tree of a HAML document.
|
9
|
-
#
|
10
|
-
# @param haml_or_filename [String]
|
11
|
-
# @param options [Hash]
|
12
|
-
# @option options [true,false] 'skip_frontmatter' Whether to skip
|
13
|
-
# frontmatter included by frameworks such as Middleman or Jekyll
|
14
|
-
def initialize(haml_or_filename, options = {})
|
15
|
-
if File.exist?(haml_or_filename)
|
16
|
-
build_from_file(haml_or_filename)
|
17
|
-
else
|
18
|
-
build_from_string(haml_or_filename)
|
19
|
-
end
|
20
|
-
|
21
|
-
process_options(options)
|
22
|
-
|
23
|
-
build_parse_tree
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
# @param path [String]
|
29
|
-
def build_from_file(path)
|
30
|
-
@filename = path
|
31
|
-
@contents = File.read(path)
|
32
|
-
end
|
33
|
-
|
34
|
-
# @param haml [String]
|
35
|
-
def build_from_string(haml)
|
36
|
-
@contents = haml
|
37
|
-
end
|
38
|
-
|
39
|
-
def build_parse_tree
|
40
|
-
original_tree = Haml::Parser.new(@contents, Haml::Options.new).parse
|
41
|
-
|
42
|
-
# Remove the trailing empty HAML comment that the parser creates to signal
|
43
|
-
# the end of the HAML document
|
44
|
-
if Gem::Requirement.new('~> 4.0.0').satisfied_by?(Gem.loaded_specs['haml'].version)
|
45
|
-
original_tree.children.pop
|
46
|
-
end
|
47
|
-
|
48
|
-
@node_transformer = HamlLint::NodeTransformer.new(self)
|
49
|
-
@tree = convert_tree(original_tree)
|
50
|
-
end
|
51
|
-
|
52
|
-
def process_options(options)
|
53
|
-
if options['skip_frontmatter'] &&
|
54
|
-
@contents =~ /
|
55
|
-
# From the start of the string
|
56
|
-
\A
|
57
|
-
# First-capture match --- followed by optional whitespace up
|
58
|
-
# to a newline then 0 or more chars followed by an optional newline.
|
59
|
-
# This matches the --- and the contents of the frontmatter
|
60
|
-
(---\s*\n.*?\n?)
|
61
|
-
# From the start of the line
|
62
|
-
^
|
63
|
-
# Second capture match --- or ... followed by optional whitespace
|
64
|
-
# and newline. This matches the closing --- for the frontmatter.
|
65
|
-
(---|\.\.\.)\s*$\n?/mx
|
66
|
-
@contents = $POSTMATCH
|
67
|
-
end
|
68
|
-
|
69
|
-
@lines = @contents.split("\n")
|
70
|
-
end
|
71
|
-
|
72
|
-
# Converts a HAML parse tree to a tree of {HamlLint::Tree::Node} objects.
|
73
|
-
#
|
74
|
-
# This provides a cleaner interface with which the linters can interact with
|
75
|
-
# the parse tree.
|
76
|
-
def convert_tree(haml_node, parent = nil)
|
77
|
-
new_node = @node_transformer.transform(haml_node)
|
78
|
-
new_node.parent = parent
|
79
|
-
|
80
|
-
new_node.children = haml_node.children.map do |child|
|
81
|
-
convert_tree(child, new_node)
|
82
|
-
end
|
83
|
-
|
84
|
-
new_node
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|