theme-check 0.1.0 → 0.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/.gitignore +1 -0
- data/CONTRIBUTING.md +2 -0
- data/README.md +62 -1
- data/RELEASING.md +41 -0
- data/Rakefile +38 -4
- data/config/default.yml +18 -0
- data/data/shopify_liquid/deprecated_filters.yml +10 -0
- data/data/shopify_liquid/plus_objects.yml +15 -0
- data/dev.yml +2 -0
- data/lib/theme_check.rb +5 -0
- data/lib/theme_check/analyzer.rb +15 -5
- data/lib/theme_check/check.rb +11 -0
- data/lib/theme_check/checks.rb +10 -0
- data/lib/theme_check/checks/deprecated_filter.rb +22 -0
- data/lib/theme_check/checks/missing_enable_comment.rb +31 -0
- data/lib/theme_check/checks/missing_required_template_files.rb +12 -12
- data/lib/theme_check/checks/parser_blocking_javascript.rb +55 -0
- data/lib/theme_check/checks/space_inside_braces.rb +19 -7
- data/lib/theme_check/checks/template_length.rb +11 -3
- data/lib/theme_check/checks/undefined_object.rb +107 -34
- data/lib/theme_check/checks/valid_html_translation.rb +2 -2
- data/lib/theme_check/cli.rb +18 -4
- data/lib/theme_check/config.rb +97 -44
- data/lib/theme_check/corrector.rb +31 -0
- data/lib/theme_check/disabled_checks.rb +77 -0
- data/lib/theme_check/file_system_storage.rb +51 -0
- data/lib/theme_check/in_memory_storage.rb +37 -0
- data/lib/theme_check/json_file.rb +12 -10
- data/lib/theme_check/language_server/handler.rb +38 -13
- data/lib/theme_check/language_server/server.rb +2 -2
- data/lib/theme_check/liquid_check.rb +2 -2
- data/lib/theme_check/node.rb +13 -0
- data/lib/theme_check/offense.rb +25 -9
- data/lib/theme_check/packager.rb +51 -0
- data/lib/theme_check/printer.rb +13 -4
- data/lib/theme_check/shopify_liquid.rb +1 -0
- data/lib/theme_check/shopify_liquid/deprecated_filter.rb +28 -0
- data/lib/theme_check/shopify_liquid/object.rb +6 -0
- data/lib/theme_check/storage.rb +25 -0
- data/lib/theme_check/template.rb +32 -10
- data/lib/theme_check/theme.rb +14 -9
- data/lib/theme_check/version.rb +1 -1
- data/lib/theme_check/visitor.rb +14 -3
- data/packaging/homebrew/theme_check.base.rb +98 -0
- metadata +21 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a07597b217b1f596cd5e777726950e396934726f3572bc7660129bec2b3b30c8
|
4
|
+
data.tar.gz: 80e54966286e332f3308021b9347feb4cdb683497991b9bb451dcf58f138a2df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c7a1c159dd1b688618c95e1e5fb943a133b606878f57c91b12e5793b07022325c5cfb2e81c49cb45ea484cb3688c6f7c2b75af1b2a50f13da6db2ba0e8b0bb3
|
7
|
+
data.tar.gz: 83fe6a74375ecf2b58f14681c99bc672a710cd6bbc70cb5f58ff06332d4123171544f6cf73c6e7f5f750c1a870d17de0ce3bd3e1f9cbfca6e1bdc7fceb767b80
|
data/.gitignore
CHANGED
data/CONTRIBUTING.md
CHANGED
data/README.md
CHANGED
@@ -30,13 +30,32 @@ Theme Check currently checks for the following:
|
|
30
30
|
✅ Unmatching translation keys in locale files
|
31
31
|
✅ Using unknown translation keys in `{{ 'missing_key' | t }}`
|
32
32
|
✅ Using several `{% ... %}` instead of `{% liquid ... %}`
|
33
|
-
✅ Undefined [objects](https://shopify.dev/docs/themes/liquid/reference/objects)
|
33
|
+
✅ Undefined [objects](https://shopify.dev/docs/themes/liquid/reference/objects)
|
34
|
+
✅ Deprecated filters
|
35
|
+
✅ Missing `theme-check-enable` comment
|
34
36
|
|
35
37
|
And many more to come! Suggestions welcome ([create an issue](https://github.com/Shopify/theme-check/issues)).
|
36
38
|
|
39
|
+
## Requirements
|
40
|
+
|
41
|
+
- Ruby 2.7+
|
42
|
+
|
37
43
|
## Installation
|
38
44
|
|
45
|
+
Theme Check is available through Homebrew _or_ RubyGems.
|
46
|
+
|
47
|
+
**Homebrew**
|
48
|
+
|
49
|
+
You’ll need to run `brew tap` first to add Shopify’s third-party repositories to Homebrew.
|
50
|
+
|
51
|
+
```sh
|
52
|
+
brew tap shopify/shopify
|
53
|
+
brew install theme-check
|
39
54
|
```
|
55
|
+
|
56
|
+
**RubyGems**
|
57
|
+
|
58
|
+
```sh
|
40
59
|
gem install theme-check
|
41
60
|
```
|
42
61
|
|
@@ -61,11 +80,53 @@ Add a `.theme-check.yml` file at the root of your theme to configure:
|
|
61
80
|
# be uploaded to Shopify.
|
62
81
|
root: dist
|
63
82
|
|
83
|
+
# It is possible to extend theme-check with custom checks
|
84
|
+
require:
|
85
|
+
- ./path/to/my_custom_check.rb
|
86
|
+
|
64
87
|
# Disable some checks
|
65
88
|
TemplateLength:
|
66
89
|
enabled: false
|
67
90
|
# Or configure options
|
68
91
|
max_length: 300
|
92
|
+
|
93
|
+
# Enable a custom check
|
94
|
+
MyCustomCheck
|
95
|
+
enabled: true
|
69
96
|
```
|
70
97
|
|
71
98
|
See [config/default.yml](config/default.yml) for available options & defaults.
|
99
|
+
|
100
|
+
## Disable checks with comments
|
101
|
+
|
102
|
+
Use Liquid comments to disable and re-enable all checks for a section of your template:
|
103
|
+
|
104
|
+
```liquid
|
105
|
+
{% comment %}theme-check-disable{% endcomment %}
|
106
|
+
{% assign x = 1 %}
|
107
|
+
{% comment %}theme-check-enable{% endcomment %}
|
108
|
+
```
|
109
|
+
|
110
|
+
Disable a specific check by including it in the comment:
|
111
|
+
|
112
|
+
```liquid
|
113
|
+
{% comment %}theme-check-disable UnusedAssign{% endcomment %}
|
114
|
+
{% assign x = 1 %}
|
115
|
+
{% comment %}theme-check-enable UnusedAssign{% endcomment %}
|
116
|
+
```
|
117
|
+
|
118
|
+
Disable multiple checks by including them as a comma-separated list:
|
119
|
+
|
120
|
+
```liquid
|
121
|
+
{% comment %}theme-check-disable UnusedAssign,SpaceInsideBraces{% endcomment %}
|
122
|
+
{%assign x = 1%}
|
123
|
+
{% comment %}theme-check-enable UnusedAssign,SpaceInsideBraces{% endcomment %}
|
124
|
+
```
|
125
|
+
|
126
|
+
Disable checks for the _entire document_ by placing the comment on the first line:
|
127
|
+
|
128
|
+
```liquid
|
129
|
+
{% comment %}theme-check-disable SpaceInsideBraces{% endcomment %}
|
130
|
+
|
131
|
+
{%assign x = 1%}
|
132
|
+
```
|
data/RELEASING.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
## Releasing Theme Check
|
2
|
+
|
3
|
+
1. Check the Semantic Versioning page for info on how to version the new release: http://semver.org
|
4
|
+
|
5
|
+
2. Create a PR to update the version in `lib/theme_check/version.rb`
|
6
|
+
|
7
|
+
3. Merge your PR to master
|
8
|
+
|
9
|
+
4. On [Shipit](https://shipit.shopify.io/shopify/theme-check/rubygems), deploy your commit.
|
10
|
+
|
11
|
+
## Homebrew Release Process
|
12
|
+
|
13
|
+
1. Release `theme-check` on RubyGems by following the steps in the previous section.
|
14
|
+
|
15
|
+
2. Generate the homebrew formula.
|
16
|
+
|
17
|
+
```bash
|
18
|
+
rake package
|
19
|
+
```
|
20
|
+
|
21
|
+
3. Copy the formula over in the [`homebrew-shopify`](https://github.com/Shopify/homebrew-shopify) repository.
|
22
|
+
|
23
|
+
```bash
|
24
|
+
VERSION=X.X.X
|
25
|
+
cp packaging/builds/$VERSION/theme-check ../homebrew-shopify
|
26
|
+
```
|
27
|
+
|
28
|
+
4. Create a branch + a commit on the [`homebrew-shopify`](https://github.com/Shopify/homebrew-shopify) repository.
|
29
|
+
|
30
|
+
```bash
|
31
|
+
git checkout -b "bump/theme-check-$VERSION"
|
32
|
+
git add theme-check.rb
|
33
|
+
git commit -m "Bump theme-check version to $VERSION"
|
34
|
+
```
|
35
|
+
|
36
|
+
5. Create a pull-request for those changes on the [`homebrew-shopify`](https://github.com/Shopify/homebrew-shopify) repository.
|
37
|
+
|
38
|
+
```bash
|
39
|
+
# shortcut if you have `hub` installed
|
40
|
+
hub compare "master:bump/theme-check-$VERSION"
|
41
|
+
```
|
data/Rakefile
CHANGED
@@ -3,12 +3,46 @@ require "rake/testtask"
|
|
3
3
|
require "rubocop/rake_task"
|
4
4
|
require "bundler/gem_tasks"
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
namespace :tests do
|
7
|
+
task all: [:in_memory, :file_system]
|
8
|
+
|
9
|
+
Rake::TestTask.new(:suite) do |t|
|
10
|
+
t.libs << "test"
|
11
|
+
t.libs << "lib"
|
12
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
13
|
+
end
|
14
|
+
|
15
|
+
desc("Runs the tests with InMemoryStorage")
|
16
|
+
task :in_memory do
|
17
|
+
ENV["THEME_STORAGE"] = 'InMemoryStorage'
|
18
|
+
puts "Running tests with #{ENV['THEME_STORAGE']}"
|
19
|
+
Rake::Task['tests:suite'].execute
|
20
|
+
end
|
21
|
+
|
22
|
+
desc("Runs the tests with FileSystemStorage")
|
23
|
+
task :file_system do
|
24
|
+
ENV["THEME_STORAGE"] = 'FileSystemStorage'
|
25
|
+
puts "Running tests with #{ENV['THEME_STORAGE']}"
|
26
|
+
Rake::Task['tests:suite'].execute
|
27
|
+
end
|
10
28
|
end
|
11
29
|
|
30
|
+
task(test: 'tests:all')
|
31
|
+
|
12
32
|
RuboCop::RakeTask.new
|
13
33
|
|
14
34
|
task default: [:test, :rubocop]
|
35
|
+
|
36
|
+
namespace :package do
|
37
|
+
require 'theme_check/packager'
|
38
|
+
|
39
|
+
task all: [:homebrew]
|
40
|
+
|
41
|
+
desc("Builds a Homebrew package of the CLI")
|
42
|
+
task :homebrew do
|
43
|
+
ThemeCheck::Packager.new.build_homebrew
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
desc("Builds all distribution packages of the CLI")
|
48
|
+
task(package: 'package:all')
|
data/config/default.yml
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
root: .
|
2
|
+
|
3
|
+
require: []
|
4
|
+
|
5
|
+
ignore:
|
6
|
+
- node_modules/*
|
7
|
+
|
1
8
|
ConvertIncludeToRender:
|
2
9
|
enabled: true
|
3
10
|
|
@@ -22,6 +29,8 @@ SyntaxError:
|
|
22
29
|
TemplateLength:
|
23
30
|
enabled: true
|
24
31
|
max_length: 200
|
32
|
+
# Exclude content of {% schema %} in line count
|
33
|
+
exclude_schema: true
|
25
34
|
|
26
35
|
UnknownFilter:
|
27
36
|
enabled: true
|
@@ -61,3 +70,12 @@ UndefinedObject:
|
|
61
70
|
|
62
71
|
RequiredDirectories:
|
63
72
|
enabled: true
|
73
|
+
|
74
|
+
DeprecatedFilter:
|
75
|
+
enabled: true
|
76
|
+
|
77
|
+
MissingEnableComment:
|
78
|
+
enabled: true
|
79
|
+
|
80
|
+
ParserBlockingJavaScript:
|
81
|
+
enabled: true
|
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
- alternative_payment_methods
|
3
|
+
- breadcrumb
|
4
|
+
- checkout_html_classes
|
5
|
+
- checkout_scripts
|
6
|
+
- checkout_stylesheets
|
7
|
+
- content_for_footer
|
8
|
+
- content_for_logo
|
9
|
+
- content_for_order_summary
|
10
|
+
- direction
|
11
|
+
- locale
|
12
|
+
- order_summary_toggle
|
13
|
+
- page_title
|
14
|
+
- skip_to_content_link
|
15
|
+
- tracking_code
|
data/dev.yml
CHANGED
data/lib/theme_check.rb
CHANGED
@@ -5,6 +5,7 @@ require_relative "theme_check/analyzer"
|
|
5
5
|
require_relative "theme_check/check"
|
6
6
|
require_relative "theme_check/checks_tracking"
|
7
7
|
require_relative "theme_check/cli"
|
8
|
+
require_relative "theme_check/disabled_checks"
|
8
9
|
require_relative "theme_check/liquid_check"
|
9
10
|
require_relative "theme_check/locale_diff"
|
10
11
|
require_relative "theme_check/json_check"
|
@@ -17,9 +18,13 @@ require_relative "theme_check/node"
|
|
17
18
|
require_relative "theme_check/offense"
|
18
19
|
require_relative "theme_check/printer"
|
19
20
|
require_relative "theme_check/shopify_liquid"
|
21
|
+
require_relative "theme_check/storage"
|
22
|
+
require_relative "theme_check/file_system_storage"
|
23
|
+
require_relative "theme_check/in_memory_storage"
|
20
24
|
require_relative "theme_check/tags"
|
21
25
|
require_relative "theme_check/template"
|
22
26
|
require_relative "theme_check/theme"
|
23
27
|
require_relative "theme_check/visitor"
|
28
|
+
require_relative "theme_check/corrector"
|
24
29
|
|
25
30
|
Dir[__dir__ + "/theme_check/checks/*.rb"].each { |file| require file }
|
data/lib/theme_check/analyzer.rb
CHANGED
@@ -3,9 +3,10 @@ module ThemeCheck
|
|
3
3
|
class Analyzer
|
4
4
|
attr_reader :offenses
|
5
5
|
|
6
|
-
def initialize(theme, checks = Check.all.map(&:new))
|
6
|
+
def initialize(theme, checks = Check.all.map(&:new), auto_correct = false)
|
7
7
|
@theme = theme
|
8
8
|
@offenses = []
|
9
|
+
@auto_correct = auto_correct
|
9
10
|
|
10
11
|
@liquid_checks = Checks.new
|
11
12
|
@json_checks = Checks.new
|
@@ -34,10 +35,19 @@ module ThemeCheck
|
|
34
35
|
@offenses
|
35
36
|
end
|
36
37
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def uncorrectable_offenses
|
39
|
+
unless @auto_correct
|
40
|
+
return @offenses
|
41
|
+
end
|
42
|
+
|
43
|
+
@offenses.select { |offense| !offense.correctable? }
|
44
|
+
end
|
45
|
+
|
46
|
+
def correct_offenses
|
47
|
+
if @auto_correct
|
48
|
+
@offenses.each(&:correct)
|
49
|
+
@theme.liquid.each(&:write)
|
50
|
+
end
|
41
51
|
end
|
42
52
|
end
|
43
53
|
end
|
data/lib/theme_check/check.rb
CHANGED
@@ -50,6 +50,13 @@ module ThemeCheck
|
|
50
50
|
@doc = doc if doc
|
51
51
|
@doc if defined?(@doc)
|
52
52
|
end
|
53
|
+
|
54
|
+
def can_disable(disableable = nil)
|
55
|
+
unless disableable.nil?
|
56
|
+
@can_disable = disableable
|
57
|
+
end
|
58
|
+
defined?(@can_disable) ? @can_disable : true
|
59
|
+
end
|
53
60
|
end
|
54
61
|
|
55
62
|
def severity
|
@@ -80,6 +87,10 @@ module ThemeCheck
|
|
80
87
|
defined?(@ignored) && @ignored
|
81
88
|
end
|
82
89
|
|
90
|
+
def can_disable?
|
91
|
+
self.class.can_disable
|
92
|
+
end
|
93
|
+
|
83
94
|
def to_s
|
84
95
|
s = +"#{code_name}:\n"
|
85
96
|
properties = { severity: severity, category: category, doc: doc }.merge(options)
|
data/lib/theme_check/checks.rb
CHANGED
@@ -8,5 +8,15 @@ module ThemeCheck
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
end
|
11
|
+
|
12
|
+
def always_enabled
|
13
|
+
self.class.new(reject(&:can_disable?))
|
14
|
+
end
|
15
|
+
|
16
|
+
def except_for(disabled_checks)
|
17
|
+
still_enabled = reject { |check| disabled_checks.all.include?(check.code_name) }
|
18
|
+
|
19
|
+
self.class.new((always_enabled + still_enabled).uniq)
|
20
|
+
end
|
11
21
|
end
|
12
22
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ThemeCheck
|
3
|
+
class DeprecatedFilter < LiquidCheck
|
4
|
+
doc "https://shopify.dev/docs/themes/liquid/reference/filters/deprecated-filters"
|
5
|
+
category :liquid
|
6
|
+
severity :suggestion
|
7
|
+
|
8
|
+
def on_variable(node)
|
9
|
+
used_filters = node.value.filters.map { |name, *_rest| name }
|
10
|
+
used_filters.each do |filter|
|
11
|
+
alternatives = ShopifyLiquid::DeprecatedFilter.alternatives(filter)
|
12
|
+
next unless alternatives
|
13
|
+
|
14
|
+
alternatives = alternatives.map { |alt| "`#{alt}`" }
|
15
|
+
add_offense(
|
16
|
+
"Deprecated filter `#{filter}`, consider using an alternative: #{alternatives.join(', ')}",
|
17
|
+
node: node,
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ThemeCheck
|
3
|
+
class MissingEnableComment < LiquidCheck
|
4
|
+
severity :error
|
5
|
+
|
6
|
+
# Don't allow this check to be disabled with a comment,
|
7
|
+
# as we need to be able to check for disabled checks.
|
8
|
+
can_disable false
|
9
|
+
|
10
|
+
def on_document(_node)
|
11
|
+
@disabled_checks = DisabledChecks.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_comment(node)
|
15
|
+
@disabled_checks.update(node)
|
16
|
+
end
|
17
|
+
|
18
|
+
def after_document(node)
|
19
|
+
return if @disabled_checks.full_document_disabled?
|
20
|
+
return unless @disabled_checks.any?
|
21
|
+
|
22
|
+
message = if @disabled_checks.all_disabled?
|
23
|
+
"All checks were"
|
24
|
+
else
|
25
|
+
@disabled_checks.all.join(', ') + " " + (@disabled_checks.all.size == 1 ? "was" : "were")
|
26
|
+
end
|
27
|
+
|
28
|
+
add_offense("#{message} disabled but not re-enabled with theme-check-enable", node: node)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -9,21 +9,21 @@ module ThemeCheck
|
|
9
9
|
category :liquid
|
10
10
|
doc "https://shopify.dev/docs/themes/theme-templates"
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
REQUIRED_LIQUID_FILES = %w(layout/theme)
|
13
|
+
REQUIRED_TEMPLATE_FILES = %w(
|
14
|
+
index product collection cart blog article page list-collections search 404
|
15
|
+
gift_card customers/account customers/activate_account customers/addresses
|
16
|
+
customers/login customers/order customers/register customers/reset_password password
|
17
|
+
)
|
16
18
|
.map { |file| "templates/#{file}" }
|
17
19
|
|
18
20
|
def on_end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
def add_missing_file_offense(file)
|
26
|
-
add_offense("Theme is missing '#{file}.liquid' file")
|
21
|
+
(REQUIRED_LIQUID_FILES - theme.liquid.map(&:name)).each do |file|
|
22
|
+
add_offense("'#{file}.liquid' is missing")
|
23
|
+
end
|
24
|
+
(REQUIRED_TEMPLATE_FILES - (theme.liquid + theme.json).map(&:name)).each do |file|
|
25
|
+
add_offense("'#{file}.liquid' or '#{file}.json' is missing")
|
26
|
+
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|