theme-check 0.8.3 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/theme-check.yml +3 -0
  3. data/CHANGELOG.md +15 -0
  4. data/CONTRIBUTING.md +2 -1
  5. data/README.md +4 -1
  6. data/config/default.yml +37 -0
  7. data/docs/checks/content_for_header_modification.md +42 -0
  8. data/docs/checks/parser_blocking_script_tag.md +53 -0
  9. data/exe/theme-check-language-server +1 -2
  10. data/lib/theme_check.rb +8 -1
  11. data/lib/theme_check/analyzer.rb +72 -16
  12. data/lib/theme_check/check.rb +31 -6
  13. data/lib/theme_check/checks.rb +9 -1
  14. data/lib/theme_check/checks/content_for_header_modification.rb +41 -0
  15. data/lib/theme_check/checks/img_width_and_height.rb +18 -49
  16. data/lib/theme_check/checks/missing_template.rb +1 -0
  17. data/lib/theme_check/checks/parser_blocking_javascript.rb +6 -38
  18. data/lib/theme_check/checks/parser_blocking_script_tag.rb +20 -0
  19. data/lib/theme_check/checks/template_length.rb +3 -0
  20. data/lib/theme_check/checks/valid_html_translation.rb +1 -0
  21. data/lib/theme_check/config.rb +2 -0
  22. data/lib/theme_check/disabled_check.rb +6 -4
  23. data/lib/theme_check/disabled_checks.rb +25 -9
  24. data/lib/theme_check/html_check.rb +7 -0
  25. data/lib/theme_check/html_node.rb +52 -0
  26. data/lib/theme_check/html_visitor.rb +36 -0
  27. data/lib/theme_check/json_file.rb +8 -0
  28. data/lib/theme_check/language_server.rb +1 -0
  29. data/lib/theme_check/language_server/completion_providers/filter_completion_provider.rb +1 -0
  30. data/lib/theme_check/language_server/diagnostics_tracker.rb +64 -0
  31. data/lib/theme_check/language_server/handler.rb +31 -26
  32. data/lib/theme_check/language_server/server.rb +1 -1
  33. data/lib/theme_check/liquid_check.rb +0 -4
  34. data/lib/theme_check/offense.rb +18 -0
  35. data/lib/theme_check/template.rb +8 -0
  36. data/lib/theme_check/theme.rb +7 -2
  37. data/lib/theme_check/version.rb +1 -1
  38. data/lib/theme_check/visitor.rb +2 -11
  39. metadata +10 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc820b814467926919858c11517a275e70dd07aea017285f315dc3309e4b49a3
4
- data.tar.gz: 949c2934821bb7270aa466c3430d8fb640e8af938fb239aa1a2a346c82580a50
3
+ metadata.gz: e5970832846bda5a0e7cb27c99ebef32382050c911350d1d208211849bef7d55
4
+ data.tar.gz: 89d3bb2d5a261c817dddfbf50ad9ac31a589f88fe4f2a2df23b8c5aaad51c4db
5
5
  SHA512:
6
- metadata.gz: 699907617f0401cd5737c7f774b7063fae97f17465a8ac06ad1e404992b969923e4de6ff877c5f85fb951a8af1433ac017ab651465132b69d6143ff77baa5495
7
- data.tar.gz: 93d69bd9b50561cc0f10940f4b5e7c5b19fcef43d105d0896b4ae484a3df13301cfc51f6470dff4b83b1e3410a3736f54d5097dca9a80763fa7c4790f1761018
6
+ metadata.gz: 2ee4f610dc461c6e70e870723f801ddb0f1e5381eebfc6622030af68486c2c6650c11e530be38456cf0df8666ecc5e78b26d16cf60428142e04f0ebde45edf9f
7
+ data.tar.gz: 36053d9337a817da4334a5341be1877f04d86b3f4d88606a2acccb2028c0a3a07227086183de5aa06bd44e9beeebd0a4650d08b746fdfbced854e945469d61a3
@@ -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,19 @@
1
1
 
2
+ v0.9.0 / 2021-05-28
3
+ ==================
4
+
5
+ * Introduce HtmlCheck, and convert ParserBlockingJavaScript & ImgWidthAndHeight to it
6
+ * Move `script-tag` validation from ParserBlockingJavaScript to ParserBlockingScriptTag
7
+ * Add ability to ignore individual checks using file patterns
8
+ * Introduce single file and whole theme checks to optimize LSP diagnostics
9
+ * Fix TemplateLength counter not being reseted on each document
10
+ * Add missing category to ValidHTMLTranslation
11
+ * Set Ruby default encodings to UTF-8 to fix encoding issues
12
+ * Add ContentForHeaderModification check to prevent relying on the content of ``content_for_header`
13
+ * Fix `Content-Length` in LSP responses
14
+ * Fix disabling checks that emit offences in `on_end`
15
+ * Fix completion bug in `filter_completion_provider`
16
+
2
17
  v0.8.3 / 2021-05-17
3
18
  ==================
4
19
 
data/CONTRIBUTING.md CHANGED
@@ -41,7 +41,8 @@ Under `lib/theme_check/checks`, create new Ruby file with a unique name describi
41
41
  ```ruby
42
42
  module ThemeCheck
43
43
  # Does one thing, and does it well!
44
- # NOTE: inherit from JsonCheck to implement a JSON based check.
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.
45
46
  class MyCheckName < LiquidCheck
46
47
  severity :suggestion # :error or :style
47
48
 
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/config/default.yml CHANGED
@@ -7,92 +7,129 @@ 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
+ ContentForHeaderModification:
134
+ enabled: true
135
+ ignore: []
@@ -0,0 +1,42 @@
1
+ # Do not depend on the content of `content_for_header` (`ContentForHeaderModification`)
2
+
3
+ Do not rely on the content of `content_for_header` as it might change in the future, which could cause your Liquid code behavior to change.
4
+
5
+ ## Check Details
6
+
7
+ :-1: Examples of **incorrect** code for this check:
8
+
9
+ ```liquid
10
+ {% assign parts = content_for_header | split: ',' %}
11
+ ```
12
+
13
+ :+1: Examples of **correct** code for this check:
14
+
15
+ The only acceptable usage of `content_for_header` is:
16
+
17
+ ```liquid
18
+ {{ content_for_header }}
19
+ ```
20
+
21
+ ## Check Options
22
+
23
+ The default configuration for this check is the following:
24
+
25
+ ```yaml
26
+ ContentForHeaderModification:
27
+ enabled: true
28
+ ```
29
+
30
+ ## Version
31
+
32
+ This check has been introduced in Theme Check 0.9.0.
33
+
34
+ ## Resources
35
+
36
+ - [Rule Source][codesource]
37
+ - [Documentation Source][docsource]
38
+ - [`theme.liquid` template considerations][considerations]
39
+
40
+ [codesource]: /lib/theme_check/checks/check_class_name.rb
41
+ [docsource]: /docs/checks/check_class_name.md
42
+ [considerations]: https://shopify.dev/docs/themes/theme-templates/theme-liquid#template-considerations
@@ -0,0 +1,53 @@
1
+ # Discourage use of parser-blocking `script_tag` filter (`ParserBlockingScriptTag`)
2
+
3
+ The `script_tag` filter emits a parser-blocking script tag.
4
+
5
+ See the [ParserBlockingJavaScript check documentation][parser_blocking_javascript] for why this is generally discouraged.
6
+
7
+ ## Check Details
8
+
9
+ This check is aimed at eliminating parser-blocking JavaScript on themes.
10
+
11
+ :-1: Examples of **incorrect** code for this check:
12
+
13
+ ```liquid
14
+ <!-- The script_tag filter outputs a parser-blocking script -->
15
+ {{ 'app-code.js' | asset_url | script_tag }}
16
+ ```
17
+
18
+ :+1: Examples of **correct** code for this check:
19
+
20
+ ```liquid
21
+ <!-- Good. Using the asset_url filter + defer -->
22
+ <script src="{{ 'theme.js' | asset_url }}" defer></script>
23
+
24
+ <!-- Also good. Using the asset_url filter + async -->
25
+ <script src="{{ 'theme.js' | asset_url }}" async></script>
26
+ ```
27
+
28
+ ## Check Options
29
+
30
+ The default configuration for this check is the following:
31
+
32
+ ```yaml
33
+ ParserBlockingScriptTag:
34
+ enabled: true
35
+ ```
36
+
37
+ ## When Not To Use It
38
+
39
+ This should only be turned off with the `theme-check-disable` comment when there's no better way to accomplish what you're doing than with a parser-blocking script.
40
+
41
+ It is discouraged to turn this rule off.
42
+
43
+ ## Version
44
+
45
+ This check has been introduced in Theme Check 0.9.0.
46
+
47
+ ## Resources
48
+
49
+ - [ParserBlockingJavaScript check][parser_blocking_javascript]
50
+ - [Documentation Source][docsource]
51
+
52
+ [parser_blocking_javascript]: /docs/checks/parser_blocking_javascript.md
53
+ [docsource]: /docs/checks/parser_blocking_script_tag.md
@@ -6,7 +6,6 @@ require 'theme_check'
6
6
  if ENV["THEME_CHECK_DEBUG"] == "true"
7
7
  $DEBUG = true
8
8
  end
9
- # Force encoding to UTF-8 to fix VSCode
10
- Encoding.default_external = Encoding::UTF_8
9
+
11
10
  status_code = ThemeCheck::LanguageServer.start
12
11
  exit! status_code
data/lib/theme_check.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require "liquid"
3
3
 
4
+ require_relative "theme_check/version"
4
5
  require_relative "theme_check/bug"
5
6
  require_relative "theme_check/exceptions"
6
7
  require_relative "theme_check/analyzer"
@@ -35,6 +36,12 @@ require_relative "theme_check/template"
35
36
  require_relative "theme_check/theme"
36
37
  require_relative "theme_check/visitor"
37
38
  require_relative "theme_check/corrector"
38
- require_relative "theme_check/version"
39
+ require_relative "theme_check/html_node"
40
+ require_relative "theme_check/html_visitor"
41
+ require_relative "theme_check/html_check"
39
42
 
40
43
  Dir[__dir__ + "/theme_check/checks/*.rb"].each { |file| require file }
44
+
45
+ # UTF-8 is the default internal and external encoding, like in Rails & Shopify.
46
+ Encoding.default_external = Encoding::UTF_8
47
+ Encoding.default_internal = Encoding::UTF_8
@@ -7,6 +7,7 @@ module ThemeCheck
7
7
 
8
8
  @liquid_checks = Checks.new
9
9
  @json_checks = Checks.new
10
+ @html_checks = Checks.new
10
11
 
11
12
  checks.each do |check|
12
13
  check.theme = @theme
@@ -16,33 +17,58 @@ module ThemeCheck
16
17
  @liquid_checks << check
17
18
  when JsonCheck
18
19
  @json_checks << check
20
+ when HtmlCheck
21
+ @html_checks << check
19
22
  end
20
23
  end
21
-
22
- @visitor = Visitor.new(@liquid_checks)
23
24
  end
24
25
 
25
26
  def offenses
26
- @liquid_checks.flat_map(&:offenses) + @json_checks.flat_map(&:offenses)
27
+ @liquid_checks.flat_map(&:offenses) +
28
+ @json_checks.flat_map(&:offenses) +
29
+ @html_checks.flat_map(&:offenses)
27
30
  end
28
31
 
29
- def offenses_clear!
30
- @liquid_checks.each do |check|
31
- check.offenses.clear
32
- end
32
+ def analyze_theme
33
+ reset
33
34
 
34
- @json_checks.each do |check|
35
- check.offenses.clear
35
+ liquid_visitor = Visitor.new(@liquid_checks, @disabled_checks)
36
+ html_visitor = HtmlVisitor.new(@html_checks)
37
+ @theme.liquid.each do |template|
38
+ liquid_visitor.visit_template(template)
39
+ html_visitor.visit_template(template)
36
40
  end
37
- end
38
41
 
39
- def analyze_theme
40
- offenses_clear!
41
- @theme.liquid.each { |template| @visitor.visit_template(template) }
42
42
  @theme.json.each { |json_file| @json_checks.call(:on_file, json_file) }
43
- @liquid_checks.call(:on_end)
44
- @json_checks.call(:on_end)
45
- offenses
43
+
44
+ finish
45
+ end
46
+
47
+ def analyze_files(files)
48
+ reset
49
+
50
+ # Call all checks that run on the whole theme
51
+ liquid_visitor = Visitor.new(@liquid_checks.whole_theme, @disabled_checks)
52
+ html_visitor = HtmlVisitor.new(@html_checks.whole_theme)
53
+ @theme.liquid.each do |template|
54
+ liquid_visitor.visit_template(template)
55
+ html_visitor.visit_template(template)
56
+ end
57
+ @theme.json.each { |json_file| @json_checks.whole_theme.call(:on_file, json_file) }
58
+
59
+ # Call checks that run on a single files, only on specified file
60
+ liquid_visitor = Visitor.new(@liquid_checks.single_file, @disabled_checks)
61
+ html_visitor = HtmlVisitor.new(@html_checks.single_file)
62
+ files.each do |file|
63
+ if file.liquid?
64
+ liquid_visitor.visit_template(file)
65
+ html_visitor.visit_template(file)
66
+ elsif file.json?
67
+ @json_checks.single_file.call(:on_file, file)
68
+ end
69
+ end
70
+
71
+ finish
46
72
  end
47
73
 
48
74
  def uncorrectable_offenses
@@ -59,5 +85,35 @@ module ThemeCheck
59
85
  @theme.liquid.each(&:write)
60
86
  end
61
87
  end
88
+
89
+ private
90
+
91
+ def reset
92
+ @disabled_checks = DisabledChecks.new
93
+
94
+ @liquid_checks.each do |check|
95
+ check.offenses.clear
96
+ end
97
+
98
+ @html_checks.each do |check|
99
+ check.offenses.clear
100
+ end
101
+
102
+ @json_checks.each do |check|
103
+ check.offenses.clear
104
+ end
105
+ end
106
+
107
+ def finish
108
+ @liquid_checks.call(:on_end)
109
+ @html_checks.call(:on_end)
110
+ @json_checks.call(:on_end)
111
+
112
+ @disabled_checks.remove_disabled_offenses(@liquid_checks)
113
+ @disabled_checks.remove_disabled_offenses(@json_checks)
114
+ @disabled_checks.remove_disabled_offenses(@html_checks)
115
+
116
+ offenses
117
+ end
62
118
  end
63
119
  end