theme-check 0.9.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -0
  3. data/CONTRIBUTING.md +20 -91
  4. data/README.md +39 -0
  5. data/Rakefile +31 -0
  6. data/config/default.yml +43 -3
  7. data/config/nothing.yml +11 -0
  8. data/config/theme_app_extension.yml +153 -0
  9. data/data/shopify_liquid/objects.yml +2 -0
  10. data/docs/api/check.md +15 -0
  11. data/docs/api/html_check.md +46 -0
  12. data/docs/api/json_check.md +19 -0
  13. data/docs/api/liquid_check.md +99 -0
  14. data/docs/checks/{CHECK_DOCS_TEMPLATE.md → TEMPLATE.md.erb} +5 -5
  15. data/docs/checks/asset_size_app_block_css.md +52 -0
  16. data/docs/checks/asset_size_app_block_javascript.md +57 -0
  17. data/docs/checks/asset_size_css_stylesheet_tag.md +50 -0
  18. data/docs/checks/deprecate_bgsizes.md +66 -0
  19. data/docs/checks/deprecate_lazysizes.md +61 -0
  20. data/docs/checks/html_parsing_error.md +50 -0
  21. data/docs/checks/img_lazy_loading.md +61 -0
  22. data/docs/checks/liquid_tag.md +2 -2
  23. data/docs/checks/template_length.md +12 -2
  24. data/lib/theme_check.rb +15 -0
  25. data/lib/theme_check/analyzer.rb +25 -21
  26. data/lib/theme_check/asset_file.rb +3 -15
  27. data/lib/theme_check/bug.rb +3 -1
  28. data/lib/theme_check/check.rb +24 -2
  29. data/lib/theme_check/checks/TEMPLATE.rb.erb +11 -0
  30. data/lib/theme_check/checks/asset_size_app_block_css.rb +44 -0
  31. data/lib/theme_check/checks/asset_size_app_block_javascript.rb +44 -0
  32. data/lib/theme_check/checks/asset_size_css.rb +11 -74
  33. data/lib/theme_check/checks/asset_size_css_stylesheet_tag.rb +24 -0
  34. data/lib/theme_check/checks/asset_size_javascript.rb +10 -36
  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/html_parsing_error.rb +12 -0
  38. data/lib/theme_check/checks/img_lazy_loading.rb +20 -0
  39. data/lib/theme_check/checks/liquid_tag.rb +2 -2
  40. data/lib/theme_check/checks/remote_asset.rb +2 -0
  41. data/lib/theme_check/checks/template_length.rb +18 -4
  42. data/lib/theme_check/cli.rb +34 -13
  43. data/lib/theme_check/config.rb +56 -10
  44. data/lib/theme_check/exceptions.rb +29 -27
  45. data/lib/theme_check/html_check.rb +2 -0
  46. data/lib/theme_check/html_visitor.rb +3 -1
  47. data/lib/theme_check/json_file.rb +2 -24
  48. data/lib/theme_check/language_server/constants.rb +8 -0
  49. data/lib/theme_check/language_server/diagnostics_tracker.rb +2 -0
  50. data/lib/theme_check/language_server/document_link_engine.rb +40 -4
  51. data/lib/theme_check/liquid_check.rb +0 -12
  52. data/lib/theme_check/offense.rb +5 -5
  53. data/lib/theme_check/parsing_helpers.rb +3 -1
  54. data/lib/theme_check/regex_helpers.rb +17 -0
  55. data/lib/theme_check/tags.rb +62 -8
  56. data/lib/theme_check/template.rb +3 -31
  57. data/lib/theme_check/theme_file.rb +40 -0
  58. data/lib/theme_check/version.rb +1 -1
  59. metadata +26 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a114e025e51ad2a09395b4ae0dca33e9417942a76ed781fdd639e7d7d1b35928
4
- data.tar.gz: ff3c7f9b43f5ccae262cd22c8547d308a71e214cdd7f924208c25122624a48dc
3
+ metadata.gz: adc4aaf3260408a9b52d9afaa59662308f173a5d5dcd0f3663cbcc68da1d7f39
4
+ data.tar.gz: 50cd7e0d42fda99ad3816a846c25868c38b92ea521e0be759c515548dd82f70b
5
5
  SHA512:
6
- metadata.gz: 3e4ead0f1d63cc68dfbaff6dd5462f08b9008c04dd87fae9499875cf967e501c68327adec0ac3c1f253bbdbf1343d14ddeb63fe58b4c9f4cb24f494315898d70
7
- data.tar.gz: 62baa63bcf203d2bd0a7894787011f23d363cb6192920ac67c2ce0dfbe89f382c461a3d5a989c23234e5e1a9db7bfd9d10c4801bca121c1993a082b58887705d
6
+ metadata.gz: 7ffad3310e441edd678143de233584a09167ffff1e09b96109cef417d360d797821dc9ef3491af4564608cd3b35aa59be41ebea6bb76030e1544d53bc9db8d02
7
+ data.tar.gz: 30b6d8f3b58b95c833a78bc30ceea6cfcfa35d563e3d184b6aee51817965be87b352c2dbad5ff67a74f2a64479fe1945c11db738c1bfb6e64f610ae15b862cb3
data/CHANGELOG.md CHANGED
@@ -1,4 +1,48 @@
1
1
 
2
+ v1.1.0 / 2021-07-06
3
+ ==================
4
+
5
+ * Add `--fail-level` CLI flag to configure exit code
6
+ * Refactor all theme file classes to inherit from `ThemeFile`
7
+ * Fix `undefined method liquid?` error when scanning from LSP
8
+ * Adding asset document links
9
+ * Allow initializing theme app extension configuration files
10
+ * Allow disabling registering mock Liquid tags w/ `ThemeCheck::Tags.register_tags = false`
11
+ * Support Theme App Extensions
12
+ * Add checks for theme app extension block JS/CSS
13
+ * Disable Liquid::C when parsing Liquid templates
14
+
15
+ v1.0.0 / 2021-06-28
16
+ ==================
17
+
18
+ * Convert `AssetSizeCSS` to `HtmlCheck`
19
+ * Add `DeprecateLazysizes` & `DeprecateBgsizes` checks
20
+ * Allow hardcoded CDN urls in `RemoteAsset`
21
+ * Bump `LiquidTag` `min_consecutive_statements` default to 5
22
+ * Exclude {% javascript %} and {% stylesheet %} from line counts in `TemplateLength`
23
+ * Bump `TemplateLength` `max_length` default to 500
24
+ * Fix `StringScanner#skip(String)` not being supported on some Rubies
25
+ * Fix `ParsingHelpers#outside_of_strings` handling of empty strings
26
+ * Update to support new `{% render %}` syntax
27
+ * Converted `AssetSizeJavaScript` to `HtmlCheck`
28
+
29
+ v0.10.2 / 2021-06-18
30
+ ==================
31
+
32
+ * Fix error when parsing a template with lots of HTML attributes.
33
+ * Add `HtmlParsingError` check for reporting errors during HTML parsing.
34
+
35
+ v0.10.1 / 2021-06-11
36
+ ==================
37
+
38
+ * Fix LSP diagnostics not being merged properly when analyzing a single file.
39
+ Causing VSCode problems not being cleared after fixing.
40
+
41
+ v0.10.0 / 2021-06-08
42
+ ==================
43
+
44
+ * Add ImgLazyLoading check for recommending loading="lazy" attribute
45
+
2
46
  v0.9.1 / 2021-06-04
3
47
  ==================
4
48
 
data/CONTRIBUTING.md CHANGED
@@ -36,103 +36,32 @@ bundle exec theme-check /path/to/your/theme
36
36
 
37
37
  ## Creating a new "Check"
38
38
 
39
- Under `lib/theme_check/checks`, create new Ruby file with a unique name describing what you want to check for.
39
+ Run `bundle exec rake "new_check[MyNewCheckName]"` to generate all the files required to create a new check.
40
40
 
41
- ```ruby
42
- module ThemeCheck
43
- # Does one thing, and does it well!
44
- # NOTE: inherit from `JsonCheck` to implement a JSON-based check, and from `HtmlCheck`
45
- # to implement an HTML-based one. See other checks in `lib/theme_check/checks` for examples.
46
- class MyCheckName < LiquidCheck
47
- severity :suggestion # :error or :style
48
-
49
- def on_document(node)
50
- # Called with the root node of all templates
51
- node.value # is the original Liquid object for this node. See Liquid source code for details.
52
- node.template # is the template being analyzed, See lib/theme_check/template.rb.
53
- node.parent # is the parent node.
54
- node.children # are the children nodes.
55
- # See lib/theme_check/node.rb for more helper methods
56
- theme # Gives you access to all the templates in the theme. See lib/theme_check/theme.rb.
57
- end
58
-
59
- def on_node(node)
60
- # Called for every node
61
- end
62
-
63
- def on_tag(node)
64
- # Called for each tag (if, include, for, assign, etc.)
65
- end
66
-
67
- def after_tag(node)
68
- # Called after the tag children have been visited
69
-
70
- # If you find an issue, add an offense:
71
- add_offense("Describe the problem...", node: node)
72
- # Or, if the offense is related to the whole template:
73
- add_offense("Describe the problem...", template: node.template)
74
- end
75
-
76
- def on_assign(node)
77
- # Called only for {% assign ... %} tags
78
- end
79
-
80
- def on_string(node)
81
- # Called for every `String` (including inside if conditions).
82
- if node.parent.block?
83
- # If parent is a block, `node.value` is a String written directly to the output when
84
- # the template is rendered.
85
- end
86
- end
87
-
88
- def on_error(exception)
89
- # Called each time a Liquid exception is raised while parsing the template
90
- end
91
-
92
- def on_end
93
- # A special callback after we're done visiting all the templates
94
- end
95
-
96
- # Each type of node has a corresponding `on_node_class_name` & `after_node_class_name`
97
- # A few common examples:
98
- # on_block_body(node)
99
- # on_capture(node)
100
- # on_case(node)
101
- # on_comment(node)
102
- # on_condition(node)
103
- # on_document(node)
104
- # on_else_condition(node)
105
- # on_for(node)
106
- # on_form(node)
107
- # on_if(node)
108
- # on_include(node)
109
- # on_integer(node)
110
- # on_layout(node)
111
- # on_method_literal(node)
112
- # on_paginate(node)
113
- # on_range(node)
114
- # on_render(node)
115
- # on_schema(node)
116
- # on_section(node)
117
- # on_style(node)
118
- # on_unless(node)
119
- # on_variable(node)
120
- # on_variable_lookup(node)
121
- end
122
- end
123
- ```
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).
124
42
 
125
- Add the new check to `config/default.yml` to enable it. If the check is configurable, the `initialize` argument name and default values should also be duplicated inside `config/default.yml`.
43
+ We done implementing your check, add it to `config/default.yml` to enable it:
126
44
 
127
45
  ```yaml
128
- MyCheckName:
46
+ MyNewCheckName:
129
47
  enabled: true
48
+ ignore: []
130
49
  ```
131
50
 
132
- Add a corresponding test file under `test/checks`.
133
-
134
- 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.:
135
52
 
136
- When done, run the tests with `dev test`.
53
+ ```ruby
54
+ class MyCheckName < LiquidCheck
55
+ def initialize(muffin_mode: true)
56
+ @muffin_mode = muffin_mode
57
+ end
58
+ # ...
59
+ end
60
+ ```
137
61
 
138
- [doctemplate]: /docs/checks/CHECK_DOCS_TEMPLATE.md
62
+ ```yaml
63
+ MyNewCheckName:
64
+ enabled: true
65
+ ignore: []
66
+ muffin_mode: true
67
+ ```
data/README.md CHANGED
@@ -100,6 +100,8 @@ TemplateLength:
100
100
  # Or ignore certain paths
101
101
  ignore:
102
102
  - snippets/icon-*
103
+ # Or change the severity (error|suggestion|style)
104
+ severity: suggestion
103
105
 
104
106
  # Enable a custom check
105
107
  MyCustomCheck
@@ -141,3 +143,40 @@ Disable checks for the _entire document_ by placing the comment on the first lin
141
143
 
142
144
  {%assign x = 1%}
143
145
  ```
146
+
147
+ ## Exit Code and `--fail-level`
148
+
149
+ Use the `--fail-level` (default: `error`) flag to configure the exit code of theme-check. Useful in CI scenarios.
150
+
151
+ Example:
152
+
153
+ ```
154
+ # Make CI fail on styles warnings, suggestions, and errors
155
+ theme-check --fail-level style path_to_theme
156
+
157
+ # Make CI fail on suggestions, and errors
158
+ theme-check --fail-level suggestion path_to_theme
159
+
160
+ # Make CI fail on errors
161
+ theme-check path_to_theme
162
+ ```
163
+
164
+ There are three fail levels:
165
+
166
+ - `error`
167
+ - `suggestion`
168
+ - `style`
169
+
170
+ Exit code meanings:
171
+
172
+ - 0: Success!
173
+ - 1: Your code doesn't pass the checks
174
+ - 2: There's a bug in theme-check
175
+
176
+ If you would like to change the severity of a check, you can do so with the `severity` attribute. Example:
177
+
178
+ ```yaml
179
+ DeprecateLazysizes:
180
+ enabled: true
181
+ severity: error
182
+ ```
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_source}"
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
@@ -1,7 +1,13 @@
1
1
  root: .
2
2
 
3
+ extends: :nothing
4
+
3
5
  require: []
4
6
 
7
+ include_categories: []
8
+
9
+ exclude_categories: []
10
+
5
11
  ignore:
6
12
  - node_modules/*
7
13
 
@@ -12,7 +18,7 @@ ConvertIncludeToRender:
12
18
  LiquidTag:
13
19
  enabled: true
14
20
  ignore: []
15
- min_consecutive_statements: 4
21
+ min_consecutive_statements: 5
16
22
 
17
23
  MissingTemplate:
18
24
  enabled: true
@@ -38,9 +44,13 @@ SyntaxError:
38
44
  TemplateLength:
39
45
  enabled: true
40
46
  ignore: []
41
- max_length: 200
47
+ max_length: 500
42
48
  # Exclude content of {% schema %} in line count
43
49
  exclude_schema: true
50
+ # Exclude content of {% stylesheet %} in line count
51
+ exclude_stylesheet: true
52
+ # Exclude content of {% javascript %} in line count
53
+ exclude_javascript: true
44
54
 
45
55
  UnknownFilter:
46
56
  enabled: true
@@ -99,6 +109,14 @@ DeprecatedFilter:
99
109
  enabled: true
100
110
  ignore: []
101
111
 
112
+ DeprecateLazysizes:
113
+ enabled: true
114
+ ignore: []
115
+
116
+ DeprecateBgsizes:
117
+ enabled: true
118
+ ignore: []
119
+
102
120
  MissingEnableComment:
103
121
  enabled: true
104
122
  ignore: []
@@ -109,16 +127,20 @@ ParserBlockingJavaScript:
109
127
 
110
128
  ParserBlockingScriptTag:
111
129
  enabled: true
130
+ ignore: []
112
131
 
113
132
  AssetSizeJavaScript:
114
133
  enabled: false
115
- ignore: []
116
134
  threshold_in_bytes: 10_000
117
135
  ignore: []
118
136
 
119
137
  AssetSizeCSS:
120
138
  enabled: false
139
+ threshold_in_bytes: 100_000
121
140
  ignore: []
141
+
142
+ AssetSizeCSSStylesheetTag:
143
+ enabled: false
122
144
  threshold_in_bytes: 100_000
123
145
  ignore: []
124
146
 
@@ -137,3 +159,21 @@ AssetUrlFilters:
137
159
  ContentForHeaderModification:
138
160
  enabled: true
139
161
  ignore: []
162
+
163
+ ImgLazyLoading:
164
+ enabled: true
165
+ ignore: []
166
+
167
+ HtmlParsingError:
168
+ enabled: true
169
+ ignore: []
170
+
171
+ AssetSizeAppBlockJavaScript:
172
+ enabled: false
173
+ ignore: []
174
+ threshold_in_bytes: 10_000
175
+
176
+ AssetSizeAppBlockCSS:
177
+ enabled: false
178
+ ignore: []
179
+ threshold_in_bytes: 100_000
@@ -0,0 +1,11 @@
1
+ root: .
2
+
3
+ require: []
4
+
5
+ include_categories: []
6
+
7
+ exclude_categories: []
8
+
9
+ ignore:
10
+ - node_modules/*
11
+
@@ -0,0 +1,153 @@
1
+ root: .
2
+
3
+ extends: :nothing
4
+
5
+ require: []
6
+
7
+ include_categories: []
8
+
9
+ exclude_categories: []
10
+
11
+ ignore:
12
+ - node_modules/*
13
+
14
+ ConvertIncludeToRender:
15
+ enabled: true
16
+ ignore: []
17
+
18
+ LiquidTag:
19
+ enabled: true
20
+ ignore: []
21
+ min_consecutive_statements: 4
22
+
23
+ MissingTemplate:
24
+ enabled: true
25
+ ignore: []
26
+
27
+ NestedSnippet:
28
+ enabled: true
29
+ ignore: []
30
+ max_nesting_level: 3
31
+
32
+ RequiredLayoutThemeObject:
33
+ enabled: true
34
+ ignore: []
35
+
36
+ SpaceInsideBraces:
37
+ enabled: true
38
+ ignore: []
39
+
40
+ SyntaxError:
41
+ enabled: true
42
+ ignore: []
43
+
44
+ TemplateLength:
45
+ enabled: true
46
+ ignore: []
47
+ max_length: 200
48
+ # Exclude content of {% schema %} in line count
49
+ exclude_schema: true
50
+
51
+ UnknownFilter:
52
+ enabled: true
53
+ ignore: []
54
+
55
+ UnusedAssign:
56
+ enabled: true
57
+ ignore: []
58
+
59
+ UnusedSnippet:
60
+ enabled: true
61
+ ignore: []
62
+
63
+ MatchingSchemaTranslations:
64
+ enabled: true
65
+ ignore: []
66
+
67
+ MatchingTranslations:
68
+ enabled: true
69
+ ignore: []
70
+
71
+ TranslationKeyExists:
72
+ enabled: true
73
+ ignore: []
74
+
75
+ ValidHTMLTranslation:
76
+ enabled: true
77
+ ignore: []
78
+
79
+ ValidJson:
80
+ enabled: true
81
+ ignore: []
82
+
83
+ ValidSchema:
84
+ enabled: true
85
+ ignore: []
86
+
87
+ UndefinedObject:
88
+ enabled: true
89
+ ignore: []
90
+ exclude_snippets: true
91
+
92
+ RequiredDirectories:
93
+ enabled: false
94
+ ignore: []
95
+
96
+ DeprecatedFilter:
97
+ enabled: true
98
+ ignore: []
99
+
100
+ MissingEnableComment:
101
+ enabled: true
102
+ ignore: []
103
+
104
+ ParserBlockingJavaScript:
105
+ enabled: true
106
+ ignore: []
107
+
108
+ ParserBlockingScriptTag:
109
+ enabled: true
110
+
111
+ AssetSizeJavaScript:
112
+ enabled: true
113
+ ignore: []
114
+ threshold_in_bytes: 10_000
115
+
116
+ AssetSizeCSS:
117
+ enabled: true
118
+ ignore: []
119
+ threshold_in_bytes: 100_000
120
+
121
+ ImgWidthAndHeight:
122
+ enabled: true
123
+ ignore: []
124
+
125
+ RemoteAsset:
126
+ enabled: true
127
+ ignore: []
128
+
129
+ AssetUrlFilters:
130
+ enabled: true
131
+ ignore: []
132
+
133
+ ContentForHeaderModification:
134
+ enabled: true
135
+ ignore: []
136
+
137
+ ImgLazyLoading:
138
+ enabled: true
139
+ ignore: []
140
+
141
+ HtmlParsingError:
142
+ enabled: true
143
+ ignore: []
144
+
145
+ AssetSizeAppBlockJavaScript:
146
+ enabled: true
147
+ ignore: []
148
+ threshold_in_bytes: 10_000
149
+
150
+ AssetSizeAppBlockCSS:
151
+ enabled: true
152
+ ignore: []
153
+ threshold_in_bytes: 100_000