theme-check 0.6.0 → 0.8.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/theme-check.yml +11 -3
  3. data/.rubocop.yml +1 -1
  4. data/CHANGELOG.md +29 -0
  5. data/Gemfile +5 -5
  6. data/LICENSE.md +2 -0
  7. data/README.md +1 -0
  8. data/RELEASING.md +10 -3
  9. data/Rakefile +6 -0
  10. data/config/default.yml +3 -0
  11. data/dev.yml +1 -1
  12. data/docs/checks/remote_asset.md +82 -0
  13. data/exe/theme-check +1 -1
  14. data/lib/theme_check.rb +1 -0
  15. data/lib/theme_check/check.rb +1 -1
  16. data/lib/theme_check/checks/asset_size_css.rb +1 -1
  17. data/lib/theme_check/checks/asset_size_javascript.rb +1 -1
  18. data/lib/theme_check/checks/img_width_and_height.rb +2 -2
  19. data/lib/theme_check/checks/matching_translations.rb +1 -1
  20. data/lib/theme_check/checks/parser_blocking_javascript.rb +1 -1
  21. data/lib/theme_check/checks/remote_asset.rb +99 -0
  22. data/lib/theme_check/checks/translation_key_exists.rb +1 -4
  23. data/lib/theme_check/checks/undefined_object.rb +1 -1
  24. data/lib/theme_check/checks/valid_html_translation.rb +1 -1
  25. data/lib/theme_check/cli.rb +101 -57
  26. data/lib/theme_check/config.rb +6 -2
  27. data/lib/theme_check/disabled_checks.rb +2 -2
  28. data/lib/theme_check/in_memory_storage.rb +13 -16
  29. data/lib/theme_check/language_server/completion_engine.rb +2 -2
  30. data/lib/theme_check/language_server/completion_providers/filter_completion_provider.rb +1 -1
  31. data/lib/theme_check/language_server/completion_providers/object_completion_provider.rb +1 -1
  32. data/lib/theme_check/language_server/completion_providers/render_snippet_completion_provider.rb +1 -1
  33. data/lib/theme_check/language_server/completion_providers/tag_completion_provider.rb +2 -2
  34. data/lib/theme_check/language_server/constants.rb +2 -2
  35. data/lib/theme_check/language_server/document_link_engine.rb +4 -3
  36. data/lib/theme_check/language_server/handler.rb +29 -21
  37. data/lib/theme_check/language_server/server.rb +1 -2
  38. data/lib/theme_check/node.rb +1 -2
  39. data/lib/theme_check/offense.rb +3 -1
  40. data/lib/theme_check/packager.rb +1 -1
  41. data/lib/theme_check/parsing_helpers.rb +1 -1
  42. data/lib/theme_check/releaser.rb +39 -0
  43. data/lib/theme_check/shopify_liquid/deprecated_filter.rb +6 -8
  44. data/lib/theme_check/shopify_liquid/filter.rb +3 -5
  45. data/lib/theme_check/shopify_liquid/object.rb +2 -6
  46. data/lib/theme_check/shopify_liquid/tag.rb +1 -3
  47. data/lib/theme_check/storage.rb +3 -3
  48. data/lib/theme_check/string_helpers.rb +47 -0
  49. data/lib/theme_check/tags.rb +1 -2
  50. data/lib/theme_check/theme.rb +1 -1
  51. data/lib/theme_check/version.rb +1 -1
  52. data/packaging/homebrew/theme_check.base.rb +1 -1
  53. data/theme-check.gemspec +3 -2
  54. metadata +9 -19
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'json'
3
3
  require 'stringio'
4
- require 'active_support/core_ext/string/inflections'
5
4
 
6
5
  module ThemeCheck
7
6
  module LanguageServer
@@ -99,7 +98,7 @@ module ThemeCheck
99
98
  end
100
99
 
101
100
  def to_snake_case(method_name)
102
- method_name.gsub(/[^\w]/, '_').underscore
101
+ StringHelpers.underscore(method_name.gsub(/[^\w]/, '_'))
103
102
  end
104
103
 
105
104
  def initial_line
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require 'active_support/core_ext/string/inflections'
3
2
 
4
3
  module ThemeCheck
5
4
  # A node from the Liquid AST, the result of parsing a template.
@@ -101,7 +100,7 @@ module ThemeCheck
101
100
  # The `:under_score_name` of this type of node. Used to dispatch to the `on_<type_name>`
102
101
  # and `after_<type_name>` check methods.
103
102
  def type_name
104
- @type_name ||= @value.class.name.demodulize.underscore.to_sym
103
+ @type_name ||= StringHelpers.underscore(StringHelpers.demodulize(@value.class.name)).to_sym
105
104
  end
106
105
 
107
106
  # Is this node inside a `{% liquid ... %}` block?
@@ -32,6 +32,8 @@ module ThemeCheck
32
32
  node&.markup
33
33
  end
34
34
 
35
+ raise ArgumentError, "Offense markup cannot be an empty string" if @markup.is_a?(String) && @markup.empty?
36
+
35
37
  @line_number = if line_number
36
38
  line_number
37
39
  elsif @node
@@ -83,7 +85,7 @@ module ThemeCheck
83
85
  end
84
86
 
85
87
  def check_name
86
- check.class.name.demodulize
88
+ StringHelpers.demodulize(check.class.name)
87
89
  end
88
90
 
89
91
  def doc
@@ -24,7 +24,7 @@ module ThemeCheck
24
24
  puts "Grabbing sha256 checksum from Rubygems.org"
25
25
  require 'digest/sha2'
26
26
  require 'open-uri'
27
- gem_checksum = open("https://rubygems.org/downloads/theme-check-#{ThemeCheck::VERSION}.gem") do |io|
27
+ gem_checksum = URI.open("https://rubygems.org/downloads/theme-check-#{ThemeCheck::VERSION}.gem") do |io|
28
28
  Digest::SHA256.new.hexdigest(io.read)
29
29
  end
30
30
 
@@ -6,7 +6,7 @@ module ThemeCheck
6
6
  scanner = StringScanner.new(markup)
7
7
 
8
8
  while scanner.scan(/.*?("|')/)
9
- yield scanner.matched[..-2]
9
+ yield scanner.matched[0..-2]
10
10
  # Skip to the end of the string
11
11
  scanner.skip_until(scanner.matched[-1] == "'" ? /[^\\]'/ : /[^\\]"/)
12
12
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ require 'theme_check/version'
3
+
4
+ module ThemeCheck
5
+ class Releaser
6
+ ROOT = File.expand_path('../../..', __FILE__)
7
+ LIB = File.join(ROOT, 'lib')
8
+
9
+ class VersionError < StandardError; end
10
+
11
+ def release(version)
12
+ raise VersionError, "Missing version argument." if version.nil?
13
+ raise VersionError, "Version should be a string." unless version.is_a?(String)
14
+ raise VersionError, "Version should be a valid semver version." unless version =~ /^\d+\.\d+.\d+$/
15
+ update_docs(version)
16
+ update_version(version)
17
+ end
18
+
19
+ def update_version(version)
20
+ version_file_path = File.join(LIB, 'theme_check/version.rb')
21
+ version_file = File.read(version_file_path)
22
+ updated_version_file = version_file.gsub(ThemeCheck::VERSION, version)
23
+
24
+ return if updated_version_file == version_file
25
+ puts "Updating version to #{version} in #{version_file_path}."
26
+ File.write(version_file_path, updated_version_file)
27
+ end
28
+
29
+ def update_docs(version)
30
+ Dir[ROOT + '/docs/checks/*.md'].each do |filename|
31
+ doc_content = File.read(filename)
32
+ updated_doc_content = doc_content.gsub('THEME_CHECK_VERSION', version)
33
+ next if updated_doc_content == doc_content
34
+ puts "Replacing `THEME_CHECK_VERSION` with #{version} in #{Pathname.new(filename).relative_path_from(ROOT)}"
35
+ File.write(filename, updated_doc_content)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -17,14 +17,12 @@ module ThemeCheck
17
17
  private
18
18
 
19
19
  def all
20
- @all ||= begin
21
- YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/deprecated_filters.yml"))
22
- .values
23
- .each_with_object({}) do |filters, acc|
24
- filters.each do |(filter, alternatives)|
25
- acc[filter] = alternatives
26
- end
27
- end
20
+ @all ||= YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/deprecated_filters.yml"))
21
+ .values
22
+ .each_with_object({}) do |filters, acc|
23
+ filters.each do |(filter, alternatives)|
24
+ acc[filter] = alternatives
25
+ end
28
26
  end
29
27
  end
30
28
  end
@@ -7,11 +7,9 @@ module ThemeCheck
7
7
  extend self
8
8
 
9
9
  def labels
10
- @labels ||= begin
11
- YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/filters.yml"))
12
- .values
13
- .flatten
14
- end
10
+ @labels ||= YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/filters.yml"))
11
+ .values
12
+ .flatten
15
13
  end
16
14
  end
17
15
  end
@@ -7,15 +7,11 @@ module ThemeCheck
7
7
  extend self
8
8
 
9
9
  def labels
10
- @labels ||= begin
11
- YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/objects.yml"))
12
- end
10
+ @labels ||= YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/objects.yml"))
13
11
  end
14
12
 
15
13
  def plus_labels
16
- @plus_labels ||= begin
17
- YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/plus_objects.yml"))
18
- end
14
+ @plus_labels ||= YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/plus_objects.yml"))
19
15
  end
20
16
  end
21
17
  end
@@ -7,9 +7,7 @@ module ThemeCheck
7
7
  extend self
8
8
 
9
9
  def labels
10
- @tags ||= begin
11
- YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/tags.yml"))
12
- end
10
+ @tags ||= YAML.load(File.read("#{__dir__}/../../../data/shopify_liquid/tags.yml"))
13
11
  end
14
12
  end
15
13
  end
@@ -2,15 +2,15 @@
2
2
 
3
3
  module ThemeCheck
4
4
  class Storage
5
- def read(relative_path)
5
+ def path(relative_path)
6
6
  raise NotImplementedError
7
7
  end
8
8
 
9
- def write(relative_path, content)
9
+ def read(relative_path)
10
10
  raise NotImplementedError
11
11
  end
12
12
 
13
- def path(relative_path)
13
+ def write(relative_path, content)
14
14
  raise NotImplementedError
15
15
  end
16
16
 
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ThemeCheck
4
+ module StringHelpers
5
+ extend self
6
+
7
+ # Removes the module part from the expression in the string.
8
+ # Ported from ActiveSupport
9
+ #
10
+ # demodulize('ActiveSupport::Inflector::Inflections') # => "Inflections"
11
+ # demodulize('Inflections') # => "Inflections"
12
+ # demodulize('::Inflections') # => "Inflections"
13
+ # demodulize('') # => ""
14
+ #
15
+ # See also #deconstantize.
16
+ def demodulize(path)
17
+ path = path.to_s
18
+ if (i = path.rindex("::"))
19
+ path[(i + 2)..-1]
20
+ else
21
+ path
22
+ end
23
+ end
24
+
25
+ # Makes an underscored, lowercase form from the expression in the string.
26
+ # Base on ActiveSupport's
27
+ #
28
+ # Changes '::' to '/' to convert namespaces to paths.
29
+ #
30
+ # underscore('ActiveModel') # => "active_model"
31
+ # underscore('ActiveModel::Errors') # => "active_model/errors"
32
+ #
33
+ # As a rule of thumb you can think of +underscore+ as the inverse of
34
+ # #camelize, though there are cases where that does not hold:
35
+ #
36
+ # camelize(underscore('SSLError')) # => "SslError"
37
+ def underscore(camel_cased_word)
38
+ return camel_cased_word unless /[A-Z-]|::/.match?(camel_cased_word)
39
+ word = camel_cased_word.to_s.gsub("::", "/")
40
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
41
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
42
+ word.tr!("-", "_")
43
+ word.downcase!
44
+ word
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,4 @@
1
1
  # frozen_string_literal: true
2
- require "active_support/core_ext/string/starts_ends_with"
3
2
 
4
3
  module ThemeCheck
5
4
  module Tags
@@ -19,7 +18,7 @@ module ThemeCheck
19
18
  "Error in tag 'section' - Valid syntax: section '[type]'",
20
19
  ) unless match
21
20
  @section_name = match[:section_name].tr(%('"), '')
22
- @section_name.chomp!(".liquid") if @section_name.ends_with?(".liquid")
21
+ @section_name.chomp!(".liquid") if @section_name.end_with?(".liquid")
23
22
  end
24
23
  end
25
24
 
@@ -13,7 +13,7 @@ module ThemeCheck
13
13
 
14
14
  def assets
15
15
  @assets ||= @storage.files
16
- .select { |path| path.starts_with?("assets/") }
16
+ .select { |path| path.start_with?("assets/") }
17
17
  .map { |path| AssetFile.new(path, @storage) }
18
18
  end
19
19
 
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ThemeCheck
3
- VERSION = "0.6.0"
3
+ VERSION = "0.8.0"
4
4
  end
@@ -13,7 +13,7 @@ class ThemeCheck < Formula
13
13
  class RubyGemsDownloadStrategy < AbstractDownloadStrategy
14
14
  include RubyBin
15
15
 
16
- def fetch
16
+ def fetch(_timeout: nil, **_options)
17
17
  ohai("Fetching theme-check from gem source")
18
18
  cache.cd do
19
19
  ENV['GEM_SPEC_CACHE'] = "#{cache}/gem_spec_cache"
data/theme-check.gemspec CHANGED
@@ -13,6 +13,8 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/Shopify/theme-check"
14
14
  spec.license = "MIT"
15
15
 
16
+ spec.required_ruby_version = ">= 2.6"
17
+
16
18
  spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
19
 
18
20
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
@@ -22,7 +24,6 @@ Gem::Specification.new do |spec|
22
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
25
  spec.require_paths = ["lib"]
24
26
 
25
- spec.add_dependency('liquid', '>= 5')
26
- spec.add_dependency('activesupport')
27
+ spec.add_dependency('liquid', '>= 5.0.1')
27
28
  spec.add_dependency('nokogumbo')
28
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.6.0
4
+ version: 0.8.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-03-23 00:00:00.000000000 Z
11
+ date: 2021-04-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -16,28 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '5'
19
+ version: 5.0.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '5'
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
26
+ version: 5.0.1
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: nokogumbo
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -98,6 +84,7 @@ files:
98
84
  - docs/checks/missing_template.md
99
85
  - docs/checks/nested_snippet.md
100
86
  - docs/checks/parser_blocking_javascript.md
87
+ - docs/checks/remote_asset.md
101
88
  - docs/checks/required_directories.md
102
89
  - docs/checks/required_layout_theme_object.md
103
90
  - docs/checks/space_inside_braces.md
@@ -133,6 +120,7 @@ files:
133
120
  - lib/theme_check/checks/missing_template.rb
134
121
  - lib/theme_check/checks/nested_snippet.rb
135
122
  - lib/theme_check/checks/parser_blocking_javascript.rb
123
+ - lib/theme_check/checks/remote_asset.rb
136
124
  - lib/theme_check/checks/required_directories.rb
137
125
  - lib/theme_check/checks/required_layout_theme_object.rb
138
126
  - lib/theme_check/checks/space_inside_braces.rb
@@ -179,6 +167,7 @@ files:
179
167
  - lib/theme_check/parsing_helpers.rb
180
168
  - lib/theme_check/printer.rb
181
169
  - lib/theme_check/regex_helpers.rb
170
+ - lib/theme_check/releaser.rb
182
171
  - lib/theme_check/remote_asset_file.rb
183
172
  - lib/theme_check/shopify_liquid.rb
184
173
  - lib/theme_check/shopify_liquid/deprecated_filter.rb
@@ -186,6 +175,7 @@ files:
186
175
  - lib/theme_check/shopify_liquid/object.rb
187
176
  - lib/theme_check/shopify_liquid/tag.rb
188
177
  - lib/theme_check/storage.rb
178
+ - lib/theme_check/string_helpers.rb
189
179
  - lib/theme_check/tags.rb
190
180
  - lib/theme_check/template.rb
191
181
  - lib/theme_check/theme.rb
@@ -206,7 +196,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
206
196
  requirements:
207
197
  - - ">="
208
198
  - !ruby/object:Gem::Version
209
- version: '0'
199
+ version: '2.6'
210
200
  required_rubygems_version: !ruby/object:Gem::Requirement
211
201
  requirements:
212
202
  - - ">="