theme-check 0.8.2 → 0.10.1
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 +3 -0
- data/CHANGELOG.md +45 -0
- data/CONTRIBUTING.md +20 -90
- data/README.md +4 -1
- data/RELEASING.md +5 -3
- data/Rakefile +31 -0
- data/config/default.yml +45 -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_url_filters.md +56 -0
- data/docs/checks/content_for_header_modification.md +42 -0
- data/docs/checks/img_lazy_loading.md +61 -0
- data/docs/checks/parser_blocking_script_tag.md +53 -0
- data/exe/theme-check-language-server +1 -2
- data/lib/theme_check.rb +8 -1
- data/lib/theme_check/analyzer.rb +72 -16
- data/lib/theme_check/bug.rb +1 -0
- data/lib/theme_check/check.rb +32 -7
- data/lib/theme_check/checks.rb +9 -1
- data/lib/theme_check/checks/TEMPLATE.rb.erb +11 -0
- data/lib/theme_check/checks/asset_url_filters.rb +46 -0
- data/lib/theme_check/checks/content_for_header_modification.rb +41 -0
- data/lib/theme_check/checks/img_lazy_loading.rb +25 -0
- data/lib/theme_check/checks/img_width_and_height.rb +18 -49
- data/lib/theme_check/checks/missing_template.rb +1 -0
- data/lib/theme_check/checks/parser_blocking_javascript.rb +6 -38
- data/lib/theme_check/checks/parser_blocking_script_tag.rb +20 -0
- data/lib/theme_check/checks/remote_asset.rb +21 -79
- data/lib/theme_check/checks/template_length.rb +3 -0
- data/lib/theme_check/checks/valid_html_translation.rb +1 -0
- data/lib/theme_check/config.rb +2 -0
- data/lib/theme_check/disabled_check.rb +6 -4
- data/lib/theme_check/disabled_checks.rb +25 -9
- data/lib/theme_check/html_check.rb +7 -0
- data/lib/theme_check/html_node.rb +56 -0
- data/lib/theme_check/html_visitor.rb +38 -0
- data/lib/theme_check/json_file.rb +13 -0
- data/lib/theme_check/language_server.rb +1 -0
- data/lib/theme_check/language_server/completion_providers/filter_completion_provider.rb +1 -0
- data/lib/theme_check/language_server/diagnostics_tracker.rb +66 -0
- data/lib/theme_check/language_server/handler.rb +31 -26
- data/lib/theme_check/language_server/server.rb +1 -1
- data/lib/theme_check/liquid_check.rb +1 -4
- data/lib/theme_check/offense.rb +18 -0
- data/lib/theme_check/template.rb +9 -0
- data/lib/theme_check/theme.rb +7 -2
- data/lib/theme_check/version.rb +1 -1
- data/lib/theme_check/visitor.rb +2 -11
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56b6a91e5ac4b1e2045b1e4fb2748e5ecb9600206f9ba07df401c1410bf494fc
|
4
|
+
data.tar.gz: b6fb1b3957ae5aecd7b2efbaa76a2e3c07390ec442f94d416ea5b20ca2cbf966
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2ca68b31968949dc52240c8ee5ca607e10e063b500cda0a7b06306589849f2bc0098f1b0742f962a91a0ca282aa504acb9f7c0de6b785afff0b577b84fa6eba
|
7
|
+
data.tar.gz: c7186299a1168c5ad1e3cd6544ee8c8248b96a492e1dc82481c26a69e75fb1f04172ceb58da61e310a393fd36c9b990464542e7528810c7bea556b5b8ce9b61d
|
@@ -34,3 +34,6 @@ jobs:
|
|
34
34
|
run: bundle install --jobs=3 --retry=3 --path=vendor/bundle
|
35
35
|
- name: Run tests
|
36
36
|
run: bundle exec rake
|
37
|
+
- name: Test runtime
|
38
|
+
# Testing that runtime can execute, not testing the results themselves
|
39
|
+
run: bundle exec theme-check ./test/theme | grep -q "files inspected"
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,49 @@
|
|
1
1
|
|
2
|
+
v0.10.1 / 2021-06-11
|
3
|
+
==================
|
4
|
+
|
5
|
+
* Fix LSP diagnostics not being merged properly when analyzing a single file.
|
6
|
+
Causing VSCode problems not being cleared after fixing.
|
7
|
+
|
8
|
+
v0.10.0 / 2021-06-08
|
9
|
+
==================
|
10
|
+
|
11
|
+
* Add ImgLazyLoading check for recommending loading="lazy" attribute
|
12
|
+
|
13
|
+
v0.9.1 / 2021-06-04
|
14
|
+
==================
|
15
|
+
|
16
|
+
* Convert `RemoteAsset` into an `HtmlCheck`
|
17
|
+
* Move Liquid logic from `RemoteAsset` to a new `AssetUrlFilters` check
|
18
|
+
|
19
|
+
v0.9.0 / 2021-05-28
|
20
|
+
==================
|
21
|
+
|
22
|
+
* Introduce HtmlCheck, and convert ParserBlockingJavaScript & ImgWidthAndHeight to it
|
23
|
+
* Move `script-tag` validation from ParserBlockingJavaScript to ParserBlockingScriptTag
|
24
|
+
* Add ability to ignore individual checks using file patterns
|
25
|
+
* Introduce single file and whole theme checks to optimize LSP diagnostics
|
26
|
+
* Fix TemplateLength counter not being reseted on each document
|
27
|
+
* Add missing category to ValidHTMLTranslation
|
28
|
+
* Set Ruby default encodings to UTF-8 to fix encoding issues
|
29
|
+
* Add ContentForHeaderModification check to prevent relying on the content of ``content_for_header`
|
30
|
+
* Fix `Content-Length` in LSP responses
|
31
|
+
* Fix disabling checks that emit offences in `on_end`
|
32
|
+
* Fix completion bug in `filter_completion_provider`
|
33
|
+
|
34
|
+
v0.8.3 / 2021-05-17
|
35
|
+
==================
|
36
|
+
|
37
|
+
* Making sure VERSION is set before referencing it
|
38
|
+
|
39
|
+
v0.8.2 / 2021-05-14
|
40
|
+
===================
|
41
|
+
|
42
|
+
* Bump NestedSnippet max_nesting_level to 3
|
43
|
+
* Add a message to help debug errors, and timeout checks after 5 sec
|
44
|
+
* Object Completions Everywhere!
|
45
|
+
* Include operators to space inside braces check
|
46
|
+
|
2
47
|
0.8.1 / 2021-04-22
|
3
48
|
==================
|
4
49
|
|
data/CONTRIBUTING.md
CHANGED
@@ -36,102 +36,32 @@ bundle exec theme-check /path/to/your/theme
|
|
36
36
|
|
37
37
|
## Creating a new "Check"
|
38
38
|
|
39
|
-
|
39
|
+
Run `bundle exec rake "new_check[MyNewCheckName]"` to generate all the files required to create a new check.
|
40
40
|
|
41
|
-
|
42
|
-
module ThemeCheck
|
43
|
-
# Does one thing, and does it well!
|
44
|
-
# NOTE: inherit from JsonCheck to implement a JSON based check.
|
45
|
-
class MyCheckName < LiquidCheck
|
46
|
-
severity :suggestion # :error or :style
|
47
|
-
|
48
|
-
def on_document(node)
|
49
|
-
# Called with the root node of all templates
|
50
|
-
node.value # is the original Liquid object for this node. See Liquid source code for details.
|
51
|
-
node.template # is the template being analyzed, See lib/theme_check/template.rb.
|
52
|
-
node.parent # is the parent node.
|
53
|
-
node.children # are the children nodes.
|
54
|
-
# See lib/theme_check/node.rb for more helper methods
|
55
|
-
theme # Gives you access to all the templates in the theme. See lib/theme_check/theme.rb.
|
56
|
-
end
|
57
|
-
|
58
|
-
def on_node(node)
|
59
|
-
# Called for every node
|
60
|
-
end
|
61
|
-
|
62
|
-
def on_tag(node)
|
63
|
-
# Called for each tag (if, include, for, assign, etc.)
|
64
|
-
end
|
65
|
-
|
66
|
-
def after_tag(node)
|
67
|
-
# Called after the tag children have been visited
|
68
|
-
|
69
|
-
# If you find an issue, add an offense:
|
70
|
-
add_offense("Describe the problem...", node: node)
|
71
|
-
# Or, if the offense is related to the whole template:
|
72
|
-
add_offense("Describe the problem...", template: node.template)
|
73
|
-
end
|
74
|
-
|
75
|
-
def on_assign(node)
|
76
|
-
# Called only for {% assign ... %} tags
|
77
|
-
end
|
78
|
-
|
79
|
-
def on_string(node)
|
80
|
-
# Called for every `String` (including inside if conditions).
|
81
|
-
if node.parent.block?
|
82
|
-
# If parent is a block, `node.value` is a String written directly to the output when
|
83
|
-
# the template is rendered.
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def on_error(exception)
|
88
|
-
# Called each time a Liquid exception is raised while parsing the template
|
89
|
-
end
|
90
|
-
|
91
|
-
def on_end
|
92
|
-
# A special callback after we're done visiting all the templates
|
93
|
-
end
|
94
|
-
|
95
|
-
# Each type of node has a corresponding `on_node_class_name` & `after_node_class_name`
|
96
|
-
# A few common examples:
|
97
|
-
# on_block_body(node)
|
98
|
-
# on_capture(node)
|
99
|
-
# on_case(node)
|
100
|
-
# on_comment(node)
|
101
|
-
# on_condition(node)
|
102
|
-
# on_document(node)
|
103
|
-
# on_else_condition(node)
|
104
|
-
# on_for(node)
|
105
|
-
# on_form(node)
|
106
|
-
# on_if(node)
|
107
|
-
# on_include(node)
|
108
|
-
# on_integer(node)
|
109
|
-
# on_layout(node)
|
110
|
-
# on_method_literal(node)
|
111
|
-
# on_paginate(node)
|
112
|
-
# on_range(node)
|
113
|
-
# on_render(node)
|
114
|
-
# on_schema(node)
|
115
|
-
# on_section(node)
|
116
|
-
# on_style(node)
|
117
|
-
# on_unless(node)
|
118
|
-
# on_variable(node)
|
119
|
-
# on_variable_lookup(node)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
```
|
41
|
+
Check the [Check API](/docs/api/check.md) for how to implement a check. Also take a look at other checks in [lib/theme_check/checks](/lib/theme_check/checks).
|
123
42
|
|
124
|
-
|
43
|
+
We done implementing your check, add it to `config/default.yml` to enable it:
|
125
44
|
|
126
45
|
```yaml
|
127
|
-
|
46
|
+
MyNewCheckName:
|
128
47
|
enabled: true
|
48
|
+
ignore: []
|
129
49
|
```
|
130
50
|
|
131
|
-
|
132
|
-
|
133
|
-
Add a documentation file in `docs/checks/#{name_of_check}.md` based off of the [check documentation template][doctemplate].
|
51
|
+
If the check is configurable, the `initialize` argument names and default values should also be duplicated inside `config/default.yml`. eg.:
|
134
52
|
|
135
|
-
|
53
|
+
```ruby
|
54
|
+
class MyCheckName < LiquidCheck
|
55
|
+
def initialize(muffin_mode: true)
|
56
|
+
@muffin_mode = muffin_mode
|
57
|
+
end
|
58
|
+
# ...
|
59
|
+
end
|
60
|
+
```
|
136
61
|
|
137
|
-
|
62
|
+
```yaml
|
63
|
+
MyNewCheckName:
|
64
|
+
enabled: true
|
65
|
+
ignore: []
|
66
|
+
muffin_mode: true
|
67
|
+
```
|
data/README.md
CHANGED
@@ -92,11 +92,14 @@ root: dist
|
|
92
92
|
require:
|
93
93
|
- ./path/to/my_custom_check.rb
|
94
94
|
|
95
|
-
# Disable some checks
|
96
95
|
TemplateLength:
|
96
|
+
# Disable some checks
|
97
97
|
enabled: false
|
98
98
|
# Or configure options
|
99
99
|
max_length: 300
|
100
|
+
# Or ignore certain paths
|
101
|
+
ignore:
|
102
|
+
- snippets/icon-*
|
100
103
|
|
101
104
|
# Enable a custom check
|
102
105
|
MyCustomCheck
|
data/RELEASING.md
CHANGED
@@ -9,11 +9,13 @@
|
|
9
9
|
rake prerelease[$VERSION]
|
10
10
|
```
|
11
11
|
|
12
|
-
3.
|
12
|
+
3. Run [`git changelog`](https://github.com/tj/git-extras) to update `CHANGELOG.md`.
|
13
13
|
|
14
|
-
4.
|
14
|
+
4. Commit your changes and make a PR.
|
15
15
|
|
16
|
-
5.
|
16
|
+
5. Merge your PR to master.
|
17
|
+
|
18
|
+
6. On [Shipit](https://shipit.shopify.io/shopify/theme-check/rubygems), deploy your commit.
|
17
19
|
|
18
20
|
## Homebrew Release Process
|
19
21
|
|
data/Rakefile
CHANGED
@@ -52,3 +52,34 @@ task :prerelease, [:version] do |_t, args|
|
|
52
52
|
require 'theme_check/releaser'
|
53
53
|
ThemeCheck::Releaser.new.release(args.version)
|
54
54
|
end
|
55
|
+
|
56
|
+
desc "Create a new check"
|
57
|
+
task :new_check, [:name] do |_t, args|
|
58
|
+
require "theme_check/string_helpers"
|
59
|
+
class_name = args.name
|
60
|
+
base_name = ThemeCheck::StringHelpers.underscore(class_name)
|
61
|
+
code_source = "lib/theme_check/checks/#{base_name}.rb"
|
62
|
+
doc_source = "docs/checks/#{base_name}.md"
|
63
|
+
test_source = "test/checks/#{base_name}_test.rb"
|
64
|
+
erb(
|
65
|
+
"lib/theme_check/checks/TEMPLATE.rb.erb", code_source,
|
66
|
+
class_name: class_name,
|
67
|
+
)
|
68
|
+
erb(
|
69
|
+
"test/checks/TEMPLATE.rb.erb", test_source,
|
70
|
+
class_name: class_name,
|
71
|
+
)
|
72
|
+
erb(
|
73
|
+
"docs/checks/TEMPLATE.md.erb", doc_source,
|
74
|
+
class_name: class_name,
|
75
|
+
code_source: code_source,
|
76
|
+
doc_source: doc_source,
|
77
|
+
)
|
78
|
+
sh "bundle exec ruby -Itest test/checks/my_new_check_test.rb"
|
79
|
+
end
|
80
|
+
|
81
|
+
def erb(file, to, **args)
|
82
|
+
require "erb"
|
83
|
+
File.write(to, ERB.new(File.read(file)).result_with_hash(args))
|
84
|
+
puts "Generated #{to}"
|
85
|
+
end
|
data/config/default.yml
CHANGED
@@ -7,92 +7,137 @@ ignore:
|
|
7
7
|
|
8
8
|
ConvertIncludeToRender:
|
9
9
|
enabled: true
|
10
|
+
ignore: []
|
10
11
|
|
11
12
|
LiquidTag:
|
12
13
|
enabled: true
|
14
|
+
ignore: []
|
13
15
|
min_consecutive_statements: 4
|
14
16
|
|
15
17
|
MissingTemplate:
|
16
18
|
enabled: true
|
19
|
+
ignore: []
|
17
20
|
|
18
21
|
NestedSnippet:
|
19
22
|
enabled: true
|
23
|
+
ignore: []
|
20
24
|
max_nesting_level: 3
|
21
25
|
|
22
26
|
RequiredLayoutThemeObject:
|
23
27
|
enabled: true
|
28
|
+
ignore: []
|
24
29
|
|
25
30
|
SpaceInsideBraces:
|
26
31
|
enabled: true
|
32
|
+
ignore: []
|
27
33
|
|
28
34
|
SyntaxError:
|
29
35
|
enabled: true
|
36
|
+
ignore: []
|
30
37
|
|
31
38
|
TemplateLength:
|
32
39
|
enabled: true
|
40
|
+
ignore: []
|
33
41
|
max_length: 200
|
34
42
|
# Exclude content of {% schema %} in line count
|
35
43
|
exclude_schema: true
|
36
44
|
|
37
45
|
UnknownFilter:
|
38
46
|
enabled: true
|
47
|
+
ignore: []
|
39
48
|
|
40
49
|
UnusedAssign:
|
41
50
|
enabled: true
|
51
|
+
ignore: []
|
42
52
|
|
43
53
|
UnusedSnippet:
|
44
54
|
enabled: true
|
55
|
+
ignore: []
|
45
56
|
|
46
57
|
MatchingSchemaTranslations:
|
47
58
|
enabled: true
|
59
|
+
ignore: []
|
48
60
|
|
49
61
|
MatchingTranslations:
|
50
62
|
enabled: true
|
63
|
+
ignore: []
|
51
64
|
|
52
65
|
DefaultLocale:
|
53
66
|
enabled: true
|
67
|
+
ignore: []
|
54
68
|
|
55
69
|
TranslationKeyExists:
|
56
70
|
enabled: true
|
71
|
+
ignore: []
|
57
72
|
|
58
73
|
ValidHTMLTranslation:
|
59
74
|
enabled: true
|
75
|
+
ignore: []
|
60
76
|
|
61
77
|
ValidJson:
|
62
78
|
enabled: true
|
79
|
+
ignore: []
|
63
80
|
|
64
81
|
ValidSchema:
|
65
82
|
enabled: true
|
83
|
+
ignore: []
|
66
84
|
|
67
85
|
MissingRequiredTemplateFiles:
|
68
86
|
enabled: true
|
87
|
+
ignore: []
|
69
88
|
|
70
89
|
UndefinedObject:
|
71
90
|
enabled: true
|
91
|
+
ignore: []
|
72
92
|
exclude_snippets: true
|
73
93
|
|
74
94
|
RequiredDirectories:
|
75
95
|
enabled: true
|
96
|
+
ignore: []
|
76
97
|
|
77
98
|
DeprecatedFilter:
|
78
99
|
enabled: true
|
100
|
+
ignore: []
|
79
101
|
|
80
102
|
MissingEnableComment:
|
81
103
|
enabled: true
|
104
|
+
ignore: []
|
82
105
|
|
83
106
|
ParserBlockingJavaScript:
|
84
107
|
enabled: true
|
108
|
+
ignore: []
|
109
|
+
|
110
|
+
ParserBlockingScriptTag:
|
111
|
+
enabled: true
|
85
112
|
|
86
113
|
AssetSizeJavaScript:
|
87
114
|
enabled: false
|
115
|
+
ignore: []
|
88
116
|
threshold_in_bytes: 10_000
|
117
|
+
ignore: []
|
89
118
|
|
90
119
|
AssetSizeCSS:
|
91
120
|
enabled: false
|
121
|
+
ignore: []
|
92
122
|
threshold_in_bytes: 100_000
|
123
|
+
ignore: []
|
93
124
|
|
94
125
|
ImgWidthAndHeight:
|
95
126
|
enabled: true
|
127
|
+
ignore: []
|
96
128
|
|
97
129
|
RemoteAsset:
|
98
130
|
enabled: true
|
131
|
+
ignore: []
|
132
|
+
|
133
|
+
AssetUrlFilters:
|
134
|
+
enabled: true
|
135
|
+
ignore: []
|
136
|
+
|
137
|
+
ContentForHeaderModification:
|
138
|
+
enabled: true
|
139
|
+
ignore: []
|
140
|
+
|
141
|
+
ImgLazyLoading:
|
142
|
+
enabled: true
|
143
|
+
ignore: []
|
data/docs/api/check.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Check API
|
2
|
+
|
3
|
+
Theme Check uses static analysis. It parses theme files into an AST, and then calls the appropriate checks to analyze it.
|
4
|
+
|
5
|
+
An [AST](https://en.wikipedia.org/wiki/Abstract_syntax_tree) is a tree of node, representing the theme file.
|
6
|
+
|
7
|
+
Checks are Ruby classes with callback methods:
|
8
|
+
- `on_TYPE` that runs before a node of the specific TYPE is visited.
|
9
|
+
- `after_TYPE` that runs after a node of the specific TYPE is visited.
|
10
|
+
|
11
|
+
There are three types of checks currently supported:
|
12
|
+
|
13
|
+
- [`LiquidCheck`](/docs/api/liquid_check.md)
|
14
|
+
- [`HtmlCheck`](/docs/api/html_check.md)
|
15
|
+
- [`JsonCheck`](/docs/api/html_check.md)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# HTML check API
|
2
|
+
|
3
|
+
For checking HTML elements in `.liquid` files.
|
4
|
+
|
5
|
+
If you need to check an HTML tag or its attributes, use an `HtmlCheck`.
|
6
|
+
|
7
|
+
The HTML in Liquid files is parsed using the Nokogiri, by consequence you will get [`Nokogiri::XML::Node`][nokogiri].
|
8
|
+
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
module ThemeCheck
|
12
|
+
class MyCheckName < HtmlCheck
|
13
|
+
category :html,
|
14
|
+
# A check can belong to multiple categories. Valid ones:
|
15
|
+
categories :translation, :performance
|
16
|
+
severity :suggestion # :error or :style
|
17
|
+
|
18
|
+
def on_document(node)
|
19
|
+
# Called with the root node of all templates
|
20
|
+
node.value # is an instance of Nokogiri::XML::Node
|
21
|
+
node.template # is the template being analyzed, See lib/theme_check/template.rb.
|
22
|
+
node.parent # is the parent node.
|
23
|
+
node.children # are the children nodes.
|
24
|
+
# See lib/theme_check/html_node.rb for more helper methods
|
25
|
+
theme # Gives you access to all the templates in the theme. See lib/theme_check/theme.rb.
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_img(node)
|
29
|
+
# Called for every <img> element in the file.
|
30
|
+
node.attrbutes["class"] # Get the class attribute of the img element.
|
31
|
+
end
|
32
|
+
|
33
|
+
def on_a(node)
|
34
|
+
# Called for every <a> element in the file.
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
## Resources
|
41
|
+
|
42
|
+
- [Nokogiri::XML::Node API doc][nokogiri]
|
43
|
+
|
44
|
+
[nokogiri]: https://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node
|
45
|
+
|
46
|
+
|