theme-check 0.9.0 → 1.0.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/CHANGELOG.md +37 -0
- data/CONTRIBUTING.md +20 -91
- data/Rakefile +31 -0
- data/config/default.yml +31 -3
- data/data/shopify_liquid/objects.yml +2 -0
- data/docs/api/check.md +15 -0
- data/docs/api/html_check.md +46 -0
- data/docs/api/json_check.md +19 -0
- data/docs/api/liquid_check.md +99 -0
- data/docs/checks/{CHECK_DOCS_TEMPLATE.md → TEMPLATE.md.erb} +5 -5
- data/docs/checks/asset_size_css_stylesheet_tag.md +50 -0
- data/docs/checks/asset_url_filters.md +56 -0
- data/docs/checks/deprecate_bgsizes.md +66 -0
- data/docs/checks/deprecate_lazysizes.md +61 -0
- data/docs/checks/html_parsing_error.md +50 -0
- data/docs/checks/img_lazy_loading.md +61 -0
- data/docs/checks/liquid_tag.md +2 -2
- data/docs/checks/template_length.md +12 -2
- data/lib/theme_check/check.rb +1 -1
- data/lib/theme_check/checks/TEMPLATE.rb.erb +11 -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 +10 -36
- data/lib/theme_check/checks/asset_url_filters.rb +46 -0
- 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/html_parsing_error.rb +12 -0
- data/lib/theme_check/checks/img_lazy_loading.rb +20 -0
- data/lib/theme_check/checks/liquid_tag.rb +2 -2
- data/lib/theme_check/checks/remote_asset.rb +23 -79
- data/lib/theme_check/checks/template_length.rb +18 -4
- data/lib/theme_check/html_check.rb +2 -0
- data/lib/theme_check/html_node.rb +4 -0
- data/lib/theme_check/html_visitor.rb +5 -1
- data/lib/theme_check/json_file.rb +5 -0
- data/lib/theme_check/language_server/diagnostics_tracker.rb +2 -0
- data/lib/theme_check/liquid_check.rb +0 -11
- data/lib/theme_check/offense.rb +5 -5
- data/lib/theme_check/parsing_helpers.rb +3 -1
- data/lib/theme_check/regex_helpers.rb +17 -0
- data/lib/theme_check/tags.rb +37 -0
- data/lib/theme_check/template.rb +1 -0
- data/lib/theme_check/version.rb +1 -1
- metadata +21 -4
@@ -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
|
@@ -13,19 +13,23 @@ module ThemeCheck
|
|
13
13
|
def visit_template(template)
|
14
14
|
doc = parse(template)
|
15
15
|
visit(HtmlNode.new(doc, template))
|
16
|
+
rescue ArgumentError => e
|
17
|
+
call_checks(:on_parse_error, e, template)
|
16
18
|
end
|
17
19
|
|
18
20
|
private
|
19
21
|
|
20
22
|
def parse(template)
|
21
|
-
Nokogiri::HTML5.fragment(template.source)
|
23
|
+
Nokogiri::HTML5.fragment(template.source, max_tree_depth: 400, max_attributes: 400)
|
22
24
|
end
|
23
25
|
|
24
26
|
def visit(node)
|
27
|
+
call_checks(:on_element, node) if node.element?
|
25
28
|
call_checks(:"on_#{node.name}", node)
|
26
29
|
node.children.each { |child| visit(child) }
|
27
30
|
unless node.literal?
|
28
31
|
call_checks(:"after_#{node.name}", node)
|
32
|
+
call_checks(:after_element, node) if node.element?
|
29
33
|
end
|
30
34
|
end
|
31
35
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require "logger"
|
2
3
|
|
3
4
|
module ThemeCheck
|
4
5
|
module LanguageServer
|
@@ -16,6 +17,7 @@ module ThemeCheck
|
|
16
17
|
def build_diagnostics(offenses, analyzed_files: nil)
|
17
18
|
reported_files = Set.new
|
18
19
|
new_single_file_offenses = {}
|
20
|
+
analyzed_files = analyzed_files.map { |path| Pathname.new(path) } if analyzed_files
|
19
21
|
|
20
22
|
offenses.group_by(&:template).each do |template, template_offenses|
|
21
23
|
next unless template
|
@@ -5,16 +5,5 @@ module ThemeCheck
|
|
5
5
|
class LiquidCheck < Check
|
6
6
|
extend ChecksTracking
|
7
7
|
include ParsingHelpers
|
8
|
-
|
9
|
-
TAG = /#{Liquid::TagStart}.*?#{Liquid::TagEnd}/om
|
10
|
-
VARIABLE = /#{Liquid::VariableStart}.*?#{Liquid::VariableEnd}/om
|
11
|
-
START_OR_END_QUOTE = /(^['"])|(['"]$)/
|
12
|
-
QUOTED_LIQUID_ATTRIBUTE = %r{
|
13
|
-
'(?:#{TAG}|#{VARIABLE}|[^'])*'| # any combination of tag/variable or non straight quote inside straight quotes
|
14
|
-
"(?:#{TAG}|#{VARIABLE}|[^"])*" # any combination of tag/variable or non double quotes inside double quotes
|
15
|
-
}omix
|
16
|
-
ATTR = /[a-z0-9-]+/i
|
17
|
-
HTML_ATTRIBUTE = /#{ATTR}(?:=#{QUOTED_LIQUID_ATTRIBUTE})?/omix
|
18
|
-
HTML_ATTRIBUTES = /(?:#{HTML_ATTRIBUTE}|\s)*/omix
|
19
8
|
end
|
20
9
|
end
|
data/lib/theme_check/offense.rb
CHANGED
@@ -124,13 +124,13 @@ module ThemeCheck
|
|
124
124
|
|
125
125
|
def ==(other)
|
126
126
|
other.is_a?(Offense) &&
|
127
|
-
|
127
|
+
code_name == other.code_name &&
|
128
128
|
message == other.message &&
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
line_number == other.line_number
|
129
|
+
location == other.location &&
|
130
|
+
start_index == other.start_index &&
|
131
|
+
end_index == other.end_index
|
133
132
|
end
|
133
|
+
alias_method :eql?, :==
|
134
134
|
|
135
135
|
def to_s
|
136
136
|
if template
|
@@ -7,8 +7,10 @@ module ThemeCheck
|
|
7
7
|
|
8
8
|
while scanner.scan(/.*?("|')/)
|
9
9
|
yield scanner.matched[0..-2]
|
10
|
+
quote = scanner.matched[-1] == "'" ? "'" : "\""
|
10
11
|
# Skip to the end of the string
|
11
|
-
|
12
|
+
# Check for empty string first, since follow regexp uses lookahead
|
13
|
+
scanner.skip(/#{quote}/) || scanner.skip_until(/[^\\]#{quote}/)
|
12
14
|
end
|
13
15
|
|
14
16
|
yield scanner.rest if scanner.rest?
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
module ThemeCheck
|
4
4
|
module RegexHelpers
|
5
|
+
VARIABLE = /#{Liquid::VariableStart}.*?#{Liquid::VariableEnd}/om
|
6
|
+
START_OR_END_QUOTE = /(^['"])|(['"]$)/
|
5
7
|
def matches(s, re)
|
6
8
|
start_at = 0
|
7
9
|
matches = []
|
@@ -11,5 +13,20 @@ module ThemeCheck
|
|
11
13
|
end
|
12
14
|
matches
|
13
15
|
end
|
16
|
+
|
17
|
+
def href_to_file_size(href)
|
18
|
+
# asset_url (+ optional stylesheet_tag) variables
|
19
|
+
if href =~ /^#{VARIABLE}$/o && href =~ /asset_url/ && href =~ Liquid::QuotedString
|
20
|
+
asset_id = Regexp.last_match(0).gsub(START_OR_END_QUOTE, "")
|
21
|
+
asset = @theme.assets.find { |a| a.name.end_with?("/" + asset_id) }
|
22
|
+
return if asset.nil?
|
23
|
+
asset.gzipped_size
|
24
|
+
|
25
|
+
# remote URLs
|
26
|
+
elsif href =~ %r{^(https?:)?//}
|
27
|
+
asset = RemoteAssetFile.from_src(href)
|
28
|
+
asset.gzipped_size
|
29
|
+
end
|
30
|
+
end
|
14
31
|
end
|
15
32
|
end
|
data/lib/theme_check/tags.rb
CHANGED
@@ -125,6 +125,42 @@ module ThemeCheck
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
|
128
|
+
class Render < Liquid::Tag
|
129
|
+
SYNTAX = /((?:#{Liquid::QuotedString}|#{Liquid::VariableSegment})+)(\s+(with|#{Liquid::Render::FOR})\s+(#{Liquid::QuotedFragment}+))?(\s+(?:as)\s+(#{Liquid::VariableSegment}+))?/o
|
130
|
+
|
131
|
+
disable_tags "include"
|
132
|
+
|
133
|
+
attr_reader :template_name_expr, :attributes
|
134
|
+
|
135
|
+
def initialize(tag_name, markup, options)
|
136
|
+
super
|
137
|
+
|
138
|
+
raise SyntaxError, options[:locale].t("errors.syntax.render") unless markup =~ SYNTAX
|
139
|
+
|
140
|
+
template_name = Regexp.last_match(1)
|
141
|
+
with_or_for = Regexp.last_match(3)
|
142
|
+
variable_name = Regexp.last_match(4)
|
143
|
+
|
144
|
+
@alias_name = Regexp.last_match(6)
|
145
|
+
@variable_name_expr = variable_name ? parse_expression(variable_name) : nil
|
146
|
+
@template_name_expr = parse_expression(template_name)
|
147
|
+
@for = (with_or_for == Liquid::Render::FOR)
|
148
|
+
|
149
|
+
@attributes = {}
|
150
|
+
markup.scan(Liquid::TagAttributes) do |key, value|
|
151
|
+
@attributes[key] = parse_expression(value)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
class ParseTreeVisitor < Liquid::ParseTreeVisitor
|
156
|
+
def children
|
157
|
+
[
|
158
|
+
@node.template_name_expr,
|
159
|
+
] + @node.attributes.values
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
128
164
|
class Style < Liquid::Block; end
|
129
165
|
|
130
166
|
class Schema < Liquid::Raw; end
|
@@ -135,6 +171,7 @@ module ThemeCheck
|
|
135
171
|
|
136
172
|
Liquid::Template.register_tag('form', Form)
|
137
173
|
Liquid::Template.register_tag('layout', Layout)
|
174
|
+
Liquid::Template.register_tag('render', Render)
|
138
175
|
Liquid::Template.register_tag('paginate', Paginate)
|
139
176
|
Liquid::Template.register_tag('section', Section)
|
140
177
|
Liquid::Template.register_tag('style', Style)
|
data/lib/theme_check/template.rb
CHANGED
data/lib/theme_check/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: theme-check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc-André Cournoyer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: liquid
|
@@ -69,13 +69,23 @@ files:
|
|
69
69
|
- data/shopify_liquid/tags.yml
|
70
70
|
- data/shopify_translation_keys.yml
|
71
71
|
- dev.yml
|
72
|
-
- docs/
|
72
|
+
- docs/api/check.md
|
73
|
+
- docs/api/html_check.md
|
74
|
+
- docs/api/json_check.md
|
75
|
+
- docs/api/liquid_check.md
|
76
|
+
- docs/checks/TEMPLATE.md.erb
|
73
77
|
- docs/checks/asset_size_css.md
|
78
|
+
- docs/checks/asset_size_css_stylesheet_tag.md
|
74
79
|
- docs/checks/asset_size_javascript.md
|
80
|
+
- docs/checks/asset_url_filters.md
|
75
81
|
- docs/checks/content_for_header_modification.md
|
76
82
|
- docs/checks/convert_include_to_render.md
|
77
83
|
- docs/checks/default_locale.md
|
84
|
+
- docs/checks/deprecate_bgsizes.md
|
85
|
+
- docs/checks/deprecate_lazysizes.md
|
78
86
|
- docs/checks/deprecated_filter.md
|
87
|
+
- docs/checks/html_parsing_error.md
|
88
|
+
- docs/checks/img_lazy_loading.md
|
79
89
|
- docs/checks/img_width_and_height.md
|
80
90
|
- docs/checks/liquid_tag.md
|
81
91
|
- docs/checks/matching_schema_translations.md
|
@@ -109,12 +119,19 @@ files:
|
|
109
119
|
- lib/theme_check/bug.rb
|
110
120
|
- lib/theme_check/check.rb
|
111
121
|
- lib/theme_check/checks.rb
|
122
|
+
- lib/theme_check/checks/TEMPLATE.rb.erb
|
112
123
|
- lib/theme_check/checks/asset_size_css.rb
|
124
|
+
- lib/theme_check/checks/asset_size_css_stylesheet_tag.rb
|
113
125
|
- lib/theme_check/checks/asset_size_javascript.rb
|
126
|
+
- lib/theme_check/checks/asset_url_filters.rb
|
114
127
|
- lib/theme_check/checks/content_for_header_modification.rb
|
115
128
|
- lib/theme_check/checks/convert_include_to_render.rb
|
116
129
|
- lib/theme_check/checks/default_locale.rb
|
130
|
+
- lib/theme_check/checks/deprecate_bgsizes.rb
|
131
|
+
- lib/theme_check/checks/deprecate_lazysizes.rb
|
117
132
|
- lib/theme_check/checks/deprecated_filter.rb
|
133
|
+
- lib/theme_check/checks/html_parsing_error.rb
|
134
|
+
- lib/theme_check/checks/img_lazy_loading.rb
|
118
135
|
- lib/theme_check/checks/img_width_and_height.rb
|
119
136
|
- lib/theme_check/checks/liquid_tag.rb
|
120
137
|
- lib/theme_check/checks/matching_schema_translations.rb
|
@@ -216,7 +233,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
216
233
|
- !ruby/object:Gem::Version
|
217
234
|
version: '0'
|
218
235
|
requirements: []
|
219
|
-
rubygems_version: 3.2.
|
236
|
+
rubygems_version: 3.2.20
|
220
237
|
signing_key:
|
221
238
|
specification_version: 4
|
222
239
|
summary: A Shopify Theme Linter
|