theme-check 0.10.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/theme-check.yml +2 -6
  3. data/CHANGELOG.md +51 -0
  4. data/CONTRIBUTING.md +1 -1
  5. data/README.md +39 -0
  6. data/RELEASING.md +34 -2
  7. data/bin/theme-check +29 -0
  8. data/bin/theme-check-language-server +29 -0
  9. data/config/default.yml +46 -3
  10. data/config/nothing.yml +11 -0
  11. data/config/theme_app_extension.yml +168 -0
  12. data/data/shopify_liquid/objects.yml +2 -0
  13. data/docs/checks/app_block_valid_tags.md +40 -0
  14. data/docs/checks/asset_size_app_block_css.md +52 -0
  15. data/docs/checks/asset_size_app_block_javascript.md +57 -0
  16. data/docs/checks/asset_size_css_stylesheet_tag.md +50 -0
  17. data/docs/checks/deprecate_bgsizes.md +66 -0
  18. data/docs/checks/deprecate_lazysizes.md +61 -0
  19. data/docs/checks/liquid_tag.md +2 -2
  20. data/docs/checks/missing_template.md +25 -0
  21. data/docs/checks/pagination_size.md +44 -0
  22. data/docs/checks/template_length.md +12 -2
  23. data/docs/checks/undefined_object.md +5 -0
  24. data/lib/theme_check/analyzer.rb +25 -21
  25. data/lib/theme_check/asset_file.rb +3 -15
  26. data/lib/theme_check/bug.rb +3 -1
  27. data/lib/theme_check/check.rb +26 -4
  28. data/lib/theme_check/checks/app_block_valid_tags.rb +36 -0
  29. data/lib/theme_check/checks/asset_size_app_block_css.rb +44 -0
  30. data/lib/theme_check/checks/asset_size_app_block_javascript.rb +44 -0
  31. data/lib/theme_check/checks/asset_size_css.rb +11 -74
  32. data/lib/theme_check/checks/asset_size_css_stylesheet_tag.rb +24 -0
  33. data/lib/theme_check/checks/asset_size_javascript.rb +11 -37
  34. data/lib/theme_check/checks/convert_include_to_render.rb +3 -1
  35. data/lib/theme_check/checks/deprecate_bgsizes.rb +14 -0
  36. data/lib/theme_check/checks/deprecate_lazysizes.rb +16 -0
  37. data/lib/theme_check/checks/img_lazy_loading.rb +2 -7
  38. data/lib/theme_check/checks/img_width_and_height.rb +3 -3
  39. data/lib/theme_check/checks/liquid_tag.rb +2 -2
  40. data/lib/theme_check/checks/missing_template.rb +21 -5
  41. data/lib/theme_check/checks/pagination_size.rb +65 -0
  42. data/lib/theme_check/checks/parser_blocking_javascript.rb +1 -1
  43. data/lib/theme_check/checks/remote_asset.rb +4 -2
  44. data/lib/theme_check/checks/space_inside_braces.rb +27 -7
  45. data/lib/theme_check/checks/template_length.rb +18 -4
  46. data/lib/theme_check/checks/undefined_object.rb +1 -1
  47. data/lib/theme_check/checks/valid_html_translation.rb +1 -1
  48. data/lib/theme_check/checks.rb +11 -1
  49. data/lib/theme_check/cli.rb +52 -15
  50. data/lib/theme_check/config.rb +56 -10
  51. data/lib/theme_check/corrector.rb +4 -0
  52. data/lib/theme_check/exceptions.rb +29 -27
  53. data/lib/theme_check/file_system_storage.rb +12 -0
  54. data/lib/theme_check/html_check.rb +1 -0
  55. data/lib/theme_check/html_node.rb +37 -16
  56. data/lib/theme_check/html_visitor.rb +17 -3
  57. data/lib/theme_check/json_check.rb +2 -2
  58. data/lib/theme_check/json_file.rb +2 -29
  59. data/lib/theme_check/json_printer.rb +26 -0
  60. data/lib/theme_check/language_server/constants.rb +8 -0
  61. data/lib/theme_check/language_server/document_link_engine.rb +40 -4
  62. data/lib/theme_check/language_server/handler.rb +6 -2
  63. data/lib/theme_check/language_server/server.rb +13 -2
  64. data/lib/theme_check/liquid_check.rb +0 -12
  65. data/lib/theme_check/node.rb +6 -4
  66. data/lib/theme_check/offense.rb +56 -3
  67. data/lib/theme_check/parsing_helpers.rb +7 -4
  68. data/lib/theme_check/position.rb +98 -14
  69. data/lib/theme_check/regex_helpers.rb +20 -0
  70. data/lib/theme_check/tags.rb +62 -8
  71. data/lib/theme_check/template.rb +3 -32
  72. data/lib/theme_check/theme.rb +2 -0
  73. data/lib/theme_check/theme_file.rb +40 -0
  74. data/lib/theme_check/version.rb +1 -1
  75. data/lib/theme_check.rb +16 -0
  76. data/theme-check.gemspec +1 -1
  77. metadata +26 -7
  78. data/bin/liquid-server +0 -4
@@ -2,6 +2,11 @@
2
2
 
3
3
  module ThemeCheck
4
4
  module RegexHelpers
5
+ LIQUID_TAG = /#{Liquid::TagStart}.*?#{Liquid::TagEnd}/om
6
+ LIQUID_VARIABLE = /#{Liquid::VariableStart}.*?#{Liquid::VariableEnd}/om
7
+ LIQUID_TAG_OR_VARIABLE = /#{LIQUID_TAG}|#{LIQUID_VARIABLE}/om
8
+ START_OR_END_QUOTE = /(^['"])|(['"]$)/
9
+
5
10
  def matches(s, re)
6
11
  start_at = 0
7
12
  matches = []
@@ -11,5 +16,20 @@ module ThemeCheck
11
16
  end
12
17
  matches
13
18
  end
19
+
20
+ def href_to_file_size(href)
21
+ # asset_url (+ optional stylesheet_tag) variables
22
+ if href =~ /^#{LIQUID_VARIABLE}$/o && href =~ /asset_url/ && href =~ Liquid::QuotedString
23
+ asset_id = Regexp.last_match(0).gsub(START_OR_END_QUOTE, "")
24
+ asset = @theme.assets.find { |a| a.name.end_with?("/" + asset_id) }
25
+ return if asset.nil?
26
+ asset.gzipped_size
27
+
28
+ # remote URLs
29
+ elsif href =~ %r{^(https?:)?//}
30
+ asset = RemoteAssetFile.from_src(href)
31
+ asset.gzipped_size
32
+ end
33
+ end
14
34
  end
15
35
  end
@@ -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
@@ -133,13 +169,31 @@ module ThemeCheck
133
169
 
134
170
  class Stylesheet < Liquid::Raw; end
135
171
 
136
- Liquid::Template.register_tag('form', Form)
137
- Liquid::Template.register_tag('layout', Layout)
138
- Liquid::Template.register_tag('paginate', Paginate)
139
- Liquid::Template.register_tag('section', Section)
140
- Liquid::Template.register_tag('style', Style)
141
- Liquid::Template.register_tag('schema', Schema)
142
- Liquid::Template.register_tag('javascript', Javascript)
143
- Liquid::Template.register_tag('stylesheet', Stylesheet)
172
+ class << self
173
+ attr_writer :register_tags
174
+
175
+ def register_tags?
176
+ @register_tags
177
+ end
178
+
179
+ def register_tag(name, klass)
180
+ Liquid::Template.register_tag(name, klass)
181
+ end
182
+
183
+ def register_tags!
184
+ return if !register_tags? || (defined?(@registered_tags) && @registered_tags)
185
+ @registered_tags = true
186
+ register_tag('form', Form)
187
+ register_tag('layout', Layout)
188
+ register_tag('render', Render)
189
+ register_tag('paginate', Paginate)
190
+ register_tag('section', Section)
191
+ register_tag('style', Style)
192
+ register_tag('schema', Schema)
193
+ register_tag('javascript', Javascript)
194
+ register_tag('stylesheet', Stylesheet)
195
+ end
196
+ end
197
+ self.register_tags = true
144
198
  end
145
199
  end
@@ -1,25 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require "pathname"
3
2
 
4
3
  module ThemeCheck
5
- class Template
6
- def initialize(relative_path, storage)
7
- @storage = storage
8
- @relative_path = relative_path
9
- end
10
-
11
- def path
12
- @storage.path(@relative_path)
13
- end
14
-
15
- def relative_path
16
- @relative_pathname ||= Pathname.new(@relative_path)
17
- end
18
-
19
- def source
20
- @source ||= @storage.read(@relative_path)
21
- end
22
-
4
+ class Template < ThemeFile
23
5
  def write
24
6
  content = updated_content
25
7
  if source != content
@@ -28,14 +10,6 @@ module ThemeCheck
28
10
  end
29
11
  end
30
12
 
31
- def name
32
- relative_path.sub_ext('').to_s
33
- end
34
-
35
- def json?
36
- false
37
- end
38
-
39
13
  def liquid?
40
14
  true
41
15
  end
@@ -88,16 +62,13 @@ module ThemeCheck
88
62
  parse.root
89
63
  end
90
64
 
91
- def ==(other)
92
- other.is_a?(Template) && relative_path == other.relative_path
93
- end
94
- alias_method :eql?, :==
95
-
96
65
  def self.parse(source)
66
+ Tags.register_tags!
97
67
  Liquid::Template.parse(
98
68
  source,
99
69
  line_numbers: true,
100
70
  error_mode: :warn,
71
+ disable_liquid_c_nodes: true,
101
72
  )
102
73
  end
103
74
  end
@@ -7,6 +7,8 @@ module ThemeCheck
7
7
  LIQUID_REGEX = /\.liquid$/i
8
8
  JSON_REGEX = /\.json$/i
9
9
 
10
+ attr_accessor :storage
11
+
10
12
  def initialize(storage)
11
13
  @storage = storage
12
14
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ require "pathname"
3
+
4
+ module ThemeCheck
5
+ class ThemeFile
6
+ def initialize(relative_path, storage)
7
+ @relative_path = relative_path
8
+ @storage = storage
9
+ end
10
+
11
+ def path
12
+ @storage.path(@relative_path)
13
+ end
14
+
15
+ def relative_path
16
+ @relative_pathname ||= Pathname.new(@relative_path)
17
+ end
18
+
19
+ def name
20
+ relative_path.sub_ext('').to_s
21
+ end
22
+
23
+ def source
24
+ @source ||= @storage.read(@relative_path)
25
+ end
26
+
27
+ def json?
28
+ false
29
+ end
30
+
31
+ def liquid?
32
+ false
33
+ end
34
+
35
+ def ==(other)
36
+ other.is_a?(self.class) && relative_path == other.relative_path
37
+ end
38
+ alias_method :eql?, :==
39
+ end
40
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ThemeCheck
3
- VERSION = "0.10.2"
3
+ VERSION = "1.3.0"
4
4
  end
data/lib/theme_check.rb CHANGED
@@ -4,6 +4,7 @@ require "liquid"
4
4
  require_relative "theme_check/version"
5
5
  require_relative "theme_check/bug"
6
6
  require_relative "theme_check/exceptions"
7
+ require_relative "theme_check/theme_file"
7
8
  require_relative "theme_check/analyzer"
8
9
  require_relative "theme_check/check"
9
10
  require_relative "theme_check/checks_tracking"
@@ -26,6 +27,7 @@ require_relative "theme_check/config"
26
27
  require_relative "theme_check/node"
27
28
  require_relative "theme_check/offense"
28
29
  require_relative "theme_check/printer"
30
+ require_relative "theme_check/json_printer"
29
31
  require_relative "theme_check/shopify_liquid"
30
32
  require_relative "theme_check/storage"
31
33
  require_relative "theme_check/string_helpers"
@@ -45,3 +47,17 @@ Dir[__dir__ + "/theme_check/checks/*.rb"].each { |file| require file }
45
47
  # UTF-8 is the default internal and external encoding, like in Rails & Shopify.
46
48
  Encoding.default_external = Encoding::UTF_8
47
49
  Encoding.default_internal = Encoding::UTF_8
50
+
51
+ module ThemeCheck
52
+ def self.with_liquid_c_disabled
53
+ if defined?(Liquid::C)
54
+ was_enabled = Liquid::C.enabled
55
+ Liquid::C.enabled = false if was_enabled
56
+ end
57
+ yield
58
+ ensure
59
+ if defined?(Liquid::C) && was_enabled
60
+ Liquid::C.enabled = true
61
+ end
62
+ end
63
+ end
data/theme-check.gemspec CHANGED
@@ -25,5 +25,5 @@ Gem::Specification.new do |spec|
25
25
  spec.require_paths = ["lib"]
26
26
 
27
27
  spec.add_dependency('liquid', '>= 5.0.1')
28
- spec.add_dependency('nokogumbo')
28
+ spec.add_dependency('nokogiri', '>= 1.12')
29
29
  end
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.10.2
4
+ version: 1.3.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-06-18 00:00:00.000000000 Z
11
+ date: 2021-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -25,19 +25,19 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: 5.0.1
27
27
  - !ruby/object:Gem::Dependency
28
- name: nokogumbo
28
+ name: nokogiri
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.12'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.12'
41
41
  description:
42
42
  email:
43
43
  - marcandre.cournoyer@shopify.com
@@ -60,8 +60,11 @@ files:
60
60
  - README.md
61
61
  - RELEASING.md
62
62
  - Rakefile
63
- - bin/liquid-server
63
+ - bin/theme-check
64
+ - bin/theme-check-language-server
64
65
  - config/default.yml
66
+ - config/nothing.yml
67
+ - config/theme_app_extension.yml
65
68
  - data/shopify_liquid/deprecated_filters.yml
66
69
  - data/shopify_liquid/filters.yml
67
70
  - data/shopify_liquid/objects.yml
@@ -74,12 +77,18 @@ files:
74
77
  - docs/api/json_check.md
75
78
  - docs/api/liquid_check.md
76
79
  - docs/checks/TEMPLATE.md.erb
80
+ - docs/checks/app_block_valid_tags.md
81
+ - docs/checks/asset_size_app_block_css.md
82
+ - docs/checks/asset_size_app_block_javascript.md
77
83
  - docs/checks/asset_size_css.md
84
+ - docs/checks/asset_size_css_stylesheet_tag.md
78
85
  - docs/checks/asset_size_javascript.md
79
86
  - docs/checks/asset_url_filters.md
80
87
  - docs/checks/content_for_header_modification.md
81
88
  - docs/checks/convert_include_to_render.md
82
89
  - docs/checks/default_locale.md
90
+ - docs/checks/deprecate_bgsizes.md
91
+ - docs/checks/deprecate_lazysizes.md
83
92
  - docs/checks/deprecated_filter.md
84
93
  - docs/checks/html_parsing_error.md
85
94
  - docs/checks/img_lazy_loading.md
@@ -91,6 +100,7 @@ files:
91
100
  - docs/checks/missing_required_template_files.md
92
101
  - docs/checks/missing_template.md
93
102
  - docs/checks/nested_snippet.md
103
+ - docs/checks/pagination_size.md
94
104
  - docs/checks/parser_blocking_javascript.md
95
105
  - docs/checks/parser_blocking_script_tag.md
96
106
  - docs/checks/remote_asset.md
@@ -117,12 +127,18 @@ files:
117
127
  - lib/theme_check/check.rb
118
128
  - lib/theme_check/checks.rb
119
129
  - lib/theme_check/checks/TEMPLATE.rb.erb
130
+ - lib/theme_check/checks/app_block_valid_tags.rb
131
+ - lib/theme_check/checks/asset_size_app_block_css.rb
132
+ - lib/theme_check/checks/asset_size_app_block_javascript.rb
120
133
  - lib/theme_check/checks/asset_size_css.rb
134
+ - lib/theme_check/checks/asset_size_css_stylesheet_tag.rb
121
135
  - lib/theme_check/checks/asset_size_javascript.rb
122
136
  - lib/theme_check/checks/asset_url_filters.rb
123
137
  - lib/theme_check/checks/content_for_header_modification.rb
124
138
  - lib/theme_check/checks/convert_include_to_render.rb
125
139
  - lib/theme_check/checks/default_locale.rb
140
+ - lib/theme_check/checks/deprecate_bgsizes.rb
141
+ - lib/theme_check/checks/deprecate_lazysizes.rb
126
142
  - lib/theme_check/checks/deprecated_filter.rb
127
143
  - lib/theme_check/checks/html_parsing_error.rb
128
144
  - lib/theme_check/checks/img_lazy_loading.rb
@@ -134,6 +150,7 @@ files:
134
150
  - lib/theme_check/checks/missing_required_template_files.rb
135
151
  - lib/theme_check/checks/missing_template.rb
136
152
  - lib/theme_check/checks/nested_snippet.rb
153
+ - lib/theme_check/checks/pagination_size.rb
137
154
  - lib/theme_check/checks/parser_blocking_javascript.rb
138
155
  - lib/theme_check/checks/parser_blocking_script_tag.rb
139
156
  - lib/theme_check/checks/remote_asset.rb
@@ -165,6 +182,7 @@ files:
165
182
  - lib/theme_check/json_check.rb
166
183
  - lib/theme_check/json_file.rb
167
184
  - lib/theme_check/json_helpers.rb
185
+ - lib/theme_check/json_printer.rb
168
186
  - lib/theme_check/language_server.rb
169
187
  - lib/theme_check/language_server/completion_engine.rb
170
188
  - lib/theme_check/language_server/completion_helper.rb
@@ -203,6 +221,7 @@ files:
203
221
  - lib/theme_check/tags.rb
204
222
  - lib/theme_check/template.rb
205
223
  - lib/theme_check/theme.rb
224
+ - lib/theme_check/theme_file.rb
206
225
  - lib/theme_check/version.rb
207
226
  - lib/theme_check/visitor.rb
208
227
  - packaging/homebrew/theme_check.base.rb
@@ -227,7 +246,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
246
  - !ruby/object:Gem::Version
228
247
  version: '0'
229
248
  requirements: []
230
- rubygems_version: 3.2.17
249
+ rubygems_version: 3.2.20
231
250
  signing_key:
232
251
  specification_version: 4
233
252
  summary: A Shopify Theme Linter
data/bin/liquid-server DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env bash
2
- dev="/opt/dev/bin/dev"
3
- cd "$($dev project-path theme-check)"
4
- "$dev" language-server