theme-check 0.10.2 → 1.3.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/theme-check.yml +2 -6
- data/CHANGELOG.md +51 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +39 -0
- data/RELEASING.md +34 -2
- data/bin/theme-check +29 -0
- data/bin/theme-check-language-server +29 -0
- data/config/default.yml +46 -3
- data/config/nothing.yml +11 -0
- data/config/theme_app_extension.yml +168 -0
- data/data/shopify_liquid/objects.yml +2 -0
- data/docs/checks/app_block_valid_tags.md +40 -0
- data/docs/checks/asset_size_app_block_css.md +52 -0
- data/docs/checks/asset_size_app_block_javascript.md +57 -0
- data/docs/checks/asset_size_css_stylesheet_tag.md +50 -0
- data/docs/checks/deprecate_bgsizes.md +66 -0
- data/docs/checks/deprecate_lazysizes.md +61 -0
- data/docs/checks/liquid_tag.md +2 -2
- data/docs/checks/missing_template.md +25 -0
- data/docs/checks/pagination_size.md +44 -0
- data/docs/checks/template_length.md +12 -2
- data/docs/checks/undefined_object.md +5 -0
- data/lib/theme_check/analyzer.rb +25 -21
- data/lib/theme_check/asset_file.rb +3 -15
- data/lib/theme_check/bug.rb +3 -1
- data/lib/theme_check/check.rb +26 -4
- data/lib/theme_check/checks/app_block_valid_tags.rb +36 -0
- data/lib/theme_check/checks/asset_size_app_block_css.rb +44 -0
- data/lib/theme_check/checks/asset_size_app_block_javascript.rb +44 -0
- data/lib/theme_check/checks/asset_size_css.rb +11 -74
- data/lib/theme_check/checks/asset_size_css_stylesheet_tag.rb +24 -0
- data/lib/theme_check/checks/asset_size_javascript.rb +11 -37
- data/lib/theme_check/checks/convert_include_to_render.rb +3 -1
- data/lib/theme_check/checks/deprecate_bgsizes.rb +14 -0
- data/lib/theme_check/checks/deprecate_lazysizes.rb +16 -0
- data/lib/theme_check/checks/img_lazy_loading.rb +2 -7
- data/lib/theme_check/checks/img_width_and_height.rb +3 -3
- data/lib/theme_check/checks/liquid_tag.rb +2 -2
- data/lib/theme_check/checks/missing_template.rb +21 -5
- data/lib/theme_check/checks/pagination_size.rb +65 -0
- data/lib/theme_check/checks/parser_blocking_javascript.rb +1 -1
- data/lib/theme_check/checks/remote_asset.rb +4 -2
- data/lib/theme_check/checks/space_inside_braces.rb +27 -7
- data/lib/theme_check/checks/template_length.rb +18 -4
- data/lib/theme_check/checks/undefined_object.rb +1 -1
- data/lib/theme_check/checks/valid_html_translation.rb +1 -1
- data/lib/theme_check/checks.rb +11 -1
- data/lib/theme_check/cli.rb +52 -15
- data/lib/theme_check/config.rb +56 -10
- data/lib/theme_check/corrector.rb +4 -0
- data/lib/theme_check/exceptions.rb +29 -27
- data/lib/theme_check/file_system_storage.rb +12 -0
- data/lib/theme_check/html_check.rb +1 -0
- data/lib/theme_check/html_node.rb +37 -16
- data/lib/theme_check/html_visitor.rb +17 -3
- data/lib/theme_check/json_check.rb +2 -2
- data/lib/theme_check/json_file.rb +2 -29
- data/lib/theme_check/json_printer.rb +26 -0
- data/lib/theme_check/language_server/constants.rb +8 -0
- data/lib/theme_check/language_server/document_link_engine.rb +40 -4
- data/lib/theme_check/language_server/handler.rb +6 -2
- data/lib/theme_check/language_server/server.rb +13 -2
- data/lib/theme_check/liquid_check.rb +0 -12
- data/lib/theme_check/node.rb +6 -4
- data/lib/theme_check/offense.rb +56 -3
- data/lib/theme_check/parsing_helpers.rb +7 -4
- data/lib/theme_check/position.rb +98 -14
- data/lib/theme_check/regex_helpers.rb +20 -0
- data/lib/theme_check/tags.rb +62 -8
- data/lib/theme_check/template.rb +3 -32
- data/lib/theme_check/theme.rb +2 -0
- data/lib/theme_check/theme_file.rb +40 -0
- data/lib/theme_check/version.rb +1 -1
- data/lib/theme_check.rb +16 -0
- data/theme-check.gemspec +1 -1
- metadata +26 -7
- data/bin/liquid-server +0 -4
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ThemeCheck
|
3
|
+
class AssetSizeCSSStylesheetTag < LiquidCheck
|
4
|
+
include RegexHelpers
|
5
|
+
severity :error
|
6
|
+
category :liquid, :performance
|
7
|
+
doc docs_url(__FILE__)
|
8
|
+
|
9
|
+
def initialize(threshold_in_bytes: 100_000)
|
10
|
+
@threshold_in_bytes = threshold_in_bytes
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_variable(node)
|
14
|
+
used_filters = node.value.filters.map { |name, *_rest| name }
|
15
|
+
return unless used_filters.include?("stylesheet_tag")
|
16
|
+
file_size = href_to_file_size('{{' + node.markup + '}}')
|
17
|
+
return if file_size <= @threshold_in_bytes
|
18
|
+
add_offense(
|
19
|
+
"CSS on every page load exceeding compressed size threshold (#{@threshold_in_bytes} Bytes).",
|
20
|
+
node: node
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -3,58 +3,32 @@ module ThemeCheck
|
|
3
3
|
# Reports errors when trying to use too much JavaScript on page load
|
4
4
|
# Encourages the use of the Import on Interaction pattern [1].
|
5
5
|
# [1]: https://addyosmani.com/blog/import-on-interaction/
|
6
|
-
class AssetSizeJavaScript <
|
6
|
+
class AssetSizeJavaScript < HtmlCheck
|
7
7
|
include RegexHelpers
|
8
8
|
severity :error
|
9
|
-
category :performance
|
9
|
+
category :html, :performance
|
10
10
|
doc docs_url(__FILE__)
|
11
11
|
|
12
|
-
Script = Struct.new(:src, :match)
|
13
|
-
|
14
|
-
SCRIPT_TAG_SRC = %r{
|
15
|
-
<script
|
16
|
-
[^>]+ # any non closing tag character
|
17
|
-
src= # src attribute start
|
18
|
-
(?<src>#{QUOTED_LIQUID_ATTRIBUTE}) # src attribute value (may contain liquid)
|
19
|
-
[^>]* # any non closing character till the end
|
20
|
-
>
|
21
|
-
}omix
|
22
|
-
|
23
12
|
attr_reader :threshold_in_bytes
|
24
13
|
|
25
14
|
def initialize(threshold_in_bytes: 10000)
|
26
15
|
@threshold_in_bytes = threshold_in_bytes
|
27
16
|
end
|
28
17
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
file_size = src_to_file_size(script.src)
|
38
|
-
next if file_size.nil?
|
39
|
-
next if file_size <= threshold_in_bytes
|
40
|
-
add_offense(
|
41
|
-
"JavaScript on every page load exceding compressed size threshold (#{threshold_in_bytes} Bytes), consider using the import on interaction pattern.",
|
42
|
-
node: @node,
|
43
|
-
markup: script.src,
|
44
|
-
line_number: @source[0...script.match.begin(:src)].count("\n") + 1
|
45
|
-
)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def scripts(source)
|
50
|
-
matches(source, SCRIPT_TAG_SRC)
|
51
|
-
.map { |m| Script.new(m[:src].gsub(START_OR_END_QUOTE, ""), m) }
|
18
|
+
def on_script(node)
|
19
|
+
file_size = src_to_file_size(node.attributes['src'])
|
20
|
+
return if file_size.nil?
|
21
|
+
return if file_size <= threshold_in_bytes
|
22
|
+
add_offense(
|
23
|
+
"JavaScript on every page load exceeds compressed size threshold (#{threshold_in_bytes} Bytes), consider using the import on interaction pattern.",
|
24
|
+
node: node
|
25
|
+
)
|
52
26
|
end
|
53
27
|
|
54
28
|
def src_to_file_size(src)
|
55
29
|
# We're kind of intentionally only looking at {{ 'asset' | asset_url }} or full urls in here.
|
56
30
|
# More complicated liquid statements are not in scope.
|
57
|
-
if src =~ /^#{
|
31
|
+
if src =~ /^#{LIQUID_VARIABLE}$/o && src =~ /asset_url/ && src =~ Liquid::QuotedString
|
58
32
|
asset_id = Regexp.last_match(0).gsub(START_OR_END_QUOTE, "")
|
59
33
|
asset = @theme.assets.find { |a| a.name.end_with?("/" + asset_id) }
|
60
34
|
return if asset.nil?
|
@@ -7,7 +7,9 @@ module ThemeCheck
|
|
7
7
|
doc docs_url(__FILE__)
|
8
8
|
|
9
9
|
def on_include(node)
|
10
|
-
add_offense("`include` is deprecated - convert it to `render`", node: node)
|
10
|
+
add_offense("`include` is deprecated - convert it to `render`", node: node) do |corrector|
|
11
|
+
corrector.replace(node, "render \'#{node.value.template_name_expr}\' ")
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ThemeCheck
|
3
|
+
class DeprecateBgsizes < HtmlCheck
|
4
|
+
severity :suggestion
|
5
|
+
category :html, :performance
|
6
|
+
doc docs_url(__FILE__)
|
7
|
+
|
8
|
+
def on_div(node)
|
9
|
+
class_list = node.attributes["class"]&.split(" ")
|
10
|
+
add_offense("Use the native loading=\"lazy\" attribute instead of lazysizes", node: node) if class_list&.include?("lazyload")
|
11
|
+
add_offense("Use the CSS imageset attribute instead of data-bgset", node: node) if node.attributes["data-bgset"]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ThemeCheck
|
3
|
+
class DeprecateLazysizes < HtmlCheck
|
4
|
+
severity :suggestion
|
5
|
+
category :html, :performance
|
6
|
+
doc docs_url(__FILE__)
|
7
|
+
|
8
|
+
def on_img(node)
|
9
|
+
class_list = node.attributes["class"]&.split(" ")
|
10
|
+
add_offense("Use the native loading=\"lazy\" attribute instead of lazysizes", node: node) if class_list&.include?("lazyload")
|
11
|
+
add_offense("Use the native srcset attribute instead of data-srcset", node: node) if node.attributes["data-srcset"]
|
12
|
+
add_offense("Use the native sizes attribute instead of data-sizes", node: node) if node.attributes["data-sizes"]
|
13
|
+
add_offense("Do not set the data-sizes attribute to auto", node: node) if node.attributes["data-sizes"] == "auto"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -8,14 +8,9 @@ module ThemeCheck
|
|
8
8
|
ACCEPTED_LOADING_VALUES = %w[lazy eager]
|
9
9
|
|
10
10
|
def on_img(node)
|
11
|
-
loading = node.attributes["loading"]&.
|
11
|
+
loading = node.attributes["loading"]&.downcase
|
12
12
|
return if ACCEPTED_LOADING_VALUES.include?(loading)
|
13
|
-
|
14
|
-
class_list = node.attributes["class"]&.value&.split(" ")
|
15
|
-
|
16
|
-
if class_list&.include?("lazyload")
|
17
|
-
add_offense("Use the native loading=\"lazy\" attribute instead of lazysizes", node: node)
|
18
|
-
elsif loading == "auto"
|
13
|
+
if loading == "auto"
|
19
14
|
add_offense("Prefer loading=\"lazy\" to defer loading of images", node: node)
|
20
15
|
else
|
21
16
|
add_offense("Add a loading=\"lazy\" attribute to defer loading of images", node: node)
|
@@ -9,8 +9,8 @@ module ThemeCheck
|
|
9
9
|
ENDS_IN_CSS_UNIT = /(cm|mm|in|px|pt|pc|em|ex|ch|rem|vw|vh|vmin|vmax|%)$/i
|
10
10
|
|
11
11
|
def on_img(node)
|
12
|
-
width = node.attributes["width"]
|
13
|
-
height = node.attributes["height"]
|
12
|
+
width = node.attributes["width"]
|
13
|
+
height = node.attributes["height"]
|
14
14
|
|
15
15
|
record_units_in_field_offenses("width", width, node: node)
|
16
16
|
record_units_in_field_offenses("height", height, node: node)
|
@@ -35,7 +35,7 @@ module ThemeCheck
|
|
35
35
|
return unless value =~ ENDS_IN_CSS_UNIT
|
36
36
|
value_without_units = value.gsub(ENDS_IN_CSS_UNIT, '')
|
37
37
|
add_offense(
|
38
|
-
"The #{attribute} attribute does not take units. Replace with \"#{value_without_units}\"
|
38
|
+
"The #{attribute} attribute does not take units. Replace with \"#{value_without_units}\"",
|
39
39
|
node: node,
|
40
40
|
)
|
41
41
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module ThemeCheck
|
3
|
-
# Recommends using {% liquid ... %} if
|
3
|
+
# Recommends using {% liquid ... %} if 5 or more consecutive {% ... %} are found.
|
4
4
|
class LiquidTag < LiquidCheck
|
5
5
|
severity :suggestion
|
6
6
|
category :liquid
|
7
7
|
doc docs_url(__FILE__)
|
8
8
|
|
9
|
-
def initialize(min_consecutive_statements:
|
9
|
+
def initialize(min_consecutive_statements: 5)
|
10
10
|
@first_statement = nil
|
11
11
|
@consecutive_statements = 0
|
12
12
|
@min_consecutive_statements = min_consecutive_statements
|
@@ -7,20 +7,36 @@ module ThemeCheck
|
|
7
7
|
doc docs_url(__FILE__)
|
8
8
|
single_file false
|
9
9
|
|
10
|
+
def initialize(ignore_missing: [])
|
11
|
+
@ignore_missing = ignore_missing
|
12
|
+
end
|
13
|
+
|
10
14
|
def on_include(node)
|
11
15
|
template = node.value.template_name_expr
|
12
16
|
if template.is_a?(String)
|
13
|
-
|
14
|
-
add_offense("'snippets/#{template}.liquid' is not found", node: node)
|
15
|
-
end
|
17
|
+
add_missing_offense("snippets/#{template}", node: node)
|
16
18
|
end
|
17
19
|
end
|
20
|
+
|
18
21
|
alias_method :on_render, :on_include
|
19
22
|
|
20
23
|
def on_section(node)
|
21
24
|
template = node.value.section_name
|
22
|
-
|
23
|
-
|
25
|
+
add_missing_offense("sections/#{template}", node: node)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def ignore?(path)
|
31
|
+
@ignore_missing.any? { |pattern| File.fnmatch?(pattern, path) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_missing_offense(name, node:)
|
35
|
+
path = "#{name}.liquid"
|
36
|
+
unless ignore?(path) || theme[name]
|
37
|
+
add_offense("'#{path}' is not found", node: node) do |corrector|
|
38
|
+
corrector.create(@theme, "#{name}.liquid", "")
|
39
|
+
end
|
24
40
|
end
|
25
41
|
end
|
26
42
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ThemeCheck
|
3
|
+
class PaginationSize < LiquidCheck
|
4
|
+
severity :suggestion
|
5
|
+
categories :performance
|
6
|
+
doc docs_url(__FILE__)
|
7
|
+
|
8
|
+
attr_reader :min_size
|
9
|
+
attr_reader :max_size
|
10
|
+
|
11
|
+
def initialize(min_size: 1, max_size: 50)
|
12
|
+
@min_size = min_size
|
13
|
+
@max_size = max_size
|
14
|
+
end
|
15
|
+
|
16
|
+
def on_document(_node)
|
17
|
+
@paginations = {}
|
18
|
+
@schema_settings = {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_paginate(node)
|
22
|
+
size = node.value.page_size
|
23
|
+
unless @paginations.key?(size)
|
24
|
+
@paginations[size] = []
|
25
|
+
end
|
26
|
+
@paginations[size].push(node)
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_schema(node)
|
30
|
+
schema = JSON.parse(node.value.nodelist.join)
|
31
|
+
|
32
|
+
if (settings = schema["settings"])
|
33
|
+
@schema_settings = settings
|
34
|
+
end
|
35
|
+
rescue JSON::ParserError
|
36
|
+
# Ignored, handled in ValidSchema.
|
37
|
+
end
|
38
|
+
|
39
|
+
def after_document(_node)
|
40
|
+
@paginations.each_pair do |size, nodes|
|
41
|
+
numerical_size = if size.is_a?(Numeric)
|
42
|
+
size
|
43
|
+
else
|
44
|
+
get_setting_default_value(size.lookups.last)
|
45
|
+
end
|
46
|
+
if numerical_size.nil?
|
47
|
+
nodes.each { |node| add_offense("Default pagination size should be defined in the section settings", node: node) }
|
48
|
+
elsif numerical_size > @max_size || numerical_size < @min_size || !numerical_size.is_a?(Integer)
|
49
|
+
nodes.each { |node| add_offense("Pagination size must be a positive integer between #{@min_size} and #{@max_size}", node: node) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def get_setting_default_value(setting_id)
|
57
|
+
setting = @schema_settings.select { |s| s['id'] == setting_id }
|
58
|
+
unless setting.empty?
|
59
|
+
return setting.last['default']
|
60
|
+
end
|
61
|
+
# Setting does not exist
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -8,7 +8,7 @@ module ThemeCheck
|
|
8
8
|
|
9
9
|
def on_script(node)
|
10
10
|
return unless node.attributes["src"]
|
11
|
-
return if node.attributes["defer"] || node.attributes["async"] || node.attributes["type"]
|
11
|
+
return if node.attributes["defer"] || node.attributes["async"] || node.attributes["type"] == "module"
|
12
12
|
|
13
13
|
add_offense("Missing async or defer attribute on script tag", node: node)
|
14
14
|
end
|
@@ -9,21 +9,23 @@ module ThemeCheck
|
|
9
9
|
PROTOCOL = %r{(https?:)?//}
|
10
10
|
ABSOLUTE_PATH = %r{\A/[^/]}im
|
11
11
|
RELATIVE_PATH = %r{\A(?!#{PROTOCOL})[^/\{]}oim
|
12
|
+
CDN_ROOT = "https://cdn.shopify.com/"
|
12
13
|
|
13
14
|
def on_element(node)
|
14
15
|
return unless TAGS.include?(node.name)
|
15
16
|
|
16
|
-
resource_url = node.attributes["src"]
|
17
|
+
resource_url = node.attributes["src"] || node.attributes["href"]
|
17
18
|
return if resource_url.nil? || resource_url.empty?
|
18
19
|
|
19
20
|
# Ignore if URL is Liquid, taken care of by AssetUrlFilters check
|
21
|
+
return if resource_url.start_with?(CDN_ROOT)
|
20
22
|
return if resource_url =~ ABSOLUTE_PATH
|
21
23
|
return if resource_url =~ RELATIVE_PATH
|
22
24
|
return if url_hosted_by_shopify?(resource_url)
|
23
25
|
|
24
26
|
# Ignore non-stylesheet rel tags
|
25
27
|
rel = node.attributes["rel"]
|
26
|
-
return if rel && rel
|
28
|
+
return if rel && rel != "stylesheet"
|
27
29
|
|
28
30
|
add_offense(
|
29
31
|
"Asset should be served by the Shopify CDN for better performance.",
|
@@ -14,18 +14,38 @@ module ThemeCheck
|
|
14
14
|
return unless node.markup
|
15
15
|
return if :assign == node.type_name
|
16
16
|
|
17
|
-
outside_of_strings(node.markup) do |chunk|
|
17
|
+
outside_of_strings(node.markup) do |chunk, chunk_start|
|
18
18
|
chunk.scan(/([,:|]|==|<>|<=|>=|<|>|!=) +/) do |_match|
|
19
|
-
add_offense(
|
19
|
+
add_offense(
|
20
|
+
"Too many spaces after '#{Regexp.last_match(1)}'",
|
21
|
+
node: node,
|
22
|
+
markup: Regexp.last_match(0),
|
23
|
+
node_markup_offset: chunk_start + Regexp.last_match.begin(0)
|
24
|
+
)
|
20
25
|
end
|
21
26
|
chunk.scan(/([,:|]|==|<>|<=|>=|<\b|>\b|!=)(\S|\z)/) do |_match|
|
22
|
-
add_offense(
|
27
|
+
add_offense(
|
28
|
+
"Space missing after '#{Regexp.last_match(1)}'",
|
29
|
+
node: node,
|
30
|
+
markup: Regexp.last_match(0),
|
31
|
+
node_markup_offset: chunk_start + Regexp.last_match.begin(0),
|
32
|
+
)
|
23
33
|
end
|
24
34
|
chunk.scan(/ (\||==|<>|<=|>=|<|>|!=)+/) do |_match|
|
25
|
-
add_offense(
|
35
|
+
add_offense(
|
36
|
+
"Too many spaces before '#{Regexp.last_match(1)}'",
|
37
|
+
node: node,
|
38
|
+
markup: Regexp.last_match(0),
|
39
|
+
node_markup_offset: chunk_start + Regexp.last_match.begin(0)
|
40
|
+
)
|
26
41
|
end
|
27
42
|
chunk.scan(/(\A|\S)(?<match>\||==|<>|<=|>=|<|\b>|!=)/) do |_match|
|
28
|
-
add_offense(
|
43
|
+
add_offense(
|
44
|
+
"Space missing before '#{Regexp.last_match(1)}'",
|
45
|
+
node: node,
|
46
|
+
markup: Regexp.last_match(0),
|
47
|
+
node_markup_offset: chunk_start + Regexp.last_match.begin(0)
|
48
|
+
)
|
29
49
|
end
|
30
50
|
end
|
31
51
|
end
|
@@ -51,13 +71,13 @@ module ThemeCheck
|
|
51
71
|
end
|
52
72
|
|
53
73
|
def on_variable(node)
|
54
|
-
return if @ignore
|
74
|
+
return if @ignore || node.markup.empty?
|
55
75
|
if node.markup[0] != " "
|
56
76
|
add_offense("Space missing after '{{'", node: node) do |corrector|
|
57
77
|
corrector.insert_before(node, " ")
|
58
78
|
end
|
59
79
|
end
|
60
|
-
if node.markup[-1] != " "
|
80
|
+
if node.markup[-1] != " " && node.markup[-1] != "\n"
|
61
81
|
add_offense("Space missing before '}}'", node: node) do |corrector|
|
62
82
|
corrector.insert_after(node, " ")
|
63
83
|
end
|
@@ -5,9 +5,11 @@ module ThemeCheck
|
|
5
5
|
category :liquid
|
6
6
|
doc docs_url(__FILE__)
|
7
7
|
|
8
|
-
def initialize(max_length:
|
8
|
+
def initialize(max_length: 500, exclude_schema: true, exclude_stylesheet: true, exclude_javascript: true)
|
9
9
|
@max_length = max_length
|
10
10
|
@exclude_schema = exclude_schema
|
11
|
+
@exclude_stylesheet = exclude_stylesheet
|
12
|
+
@exclude_javascript = exclude_javascript
|
11
13
|
end
|
12
14
|
|
13
15
|
def on_document(_node)
|
@@ -15,9 +17,15 @@ module ThemeCheck
|
|
15
17
|
end
|
16
18
|
|
17
19
|
def on_schema(node)
|
18
|
-
if @exclude_schema
|
19
|
-
|
20
|
-
|
20
|
+
exclude_node_lines(node) if @exclude_schema
|
21
|
+
end
|
22
|
+
|
23
|
+
def on_stylesheet(node)
|
24
|
+
exclude_node_lines(node) if @exclude_stylesheet
|
25
|
+
end
|
26
|
+
|
27
|
+
def on_javascript(node)
|
28
|
+
exclude_node_lines(node) if @exclude_javascript
|
21
29
|
end
|
22
30
|
|
23
31
|
def after_document(node)
|
@@ -26,5 +34,11 @@ module ThemeCheck
|
|
26
34
|
add_offense("Template has too many lines [#{lines}/#{@max_length}]", template: node.template)
|
27
35
|
end
|
28
36
|
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def exclude_node_lines(node)
|
41
|
+
@excluded_lines += node.value.nodelist.join.count("\n")
|
42
|
+
end
|
29
43
|
end
|
30
44
|
end
|