theme-check 1.5.2 → 1.7.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/theme-check.yml +12 -4
  3. data/CHANGELOG.md +37 -0
  4. data/docs/api/html_check.md +7 -7
  5. data/docs/api/liquid_check.md +10 -10
  6. data/docs/checks/convert_include_to_render.md +1 -1
  7. data/docs/checks/missing_enable_comment.md +1 -1
  8. data/lib/theme_check/analyzer.rb +46 -17
  9. data/lib/theme_check/asset_file.rb +13 -2
  10. data/lib/theme_check/check.rb +3 -3
  11. data/lib/theme_check/checks/asset_size_css.rb +15 -0
  12. data/lib/theme_check/checks/asset_size_css_stylesheet_tag.rb +18 -1
  13. data/lib/theme_check/checks/convert_include_to_render.rb +2 -1
  14. data/lib/theme_check/checks/html_parsing_error.rb +2 -2
  15. data/lib/theme_check/checks/matching_translations.rb +1 -1
  16. data/lib/theme_check/checks/missing_required_template_files.rb +21 -7
  17. data/lib/theme_check/checks/missing_template.rb +6 -6
  18. data/lib/theme_check/checks/nested_snippet.rb +2 -2
  19. data/lib/theme_check/checks/required_layout_theme_object.rb +2 -2
  20. data/lib/theme_check/checks/syntax_error.rb +5 -5
  21. data/lib/theme_check/checks/template_length.rb +2 -2
  22. data/lib/theme_check/checks/translation_key_exists.rb +3 -1
  23. data/lib/theme_check/checks/undefined_object.rb +7 -7
  24. data/lib/theme_check/checks/unused_assign.rb +4 -4
  25. data/lib/theme_check/checks/unused_snippet.rb +8 -6
  26. data/lib/theme_check/checks/valid_json.rb +1 -1
  27. data/lib/theme_check/checks.rb +4 -2
  28. data/lib/theme_check/cli.rb +7 -4
  29. data/lib/theme_check/corrector.rb +21 -12
  30. data/lib/theme_check/disabled_check.rb +3 -3
  31. data/lib/theme_check/disabled_checks.rb +9 -9
  32. data/lib/theme_check/file_system_storage.rb +7 -2
  33. data/lib/theme_check/html_node.rb +40 -32
  34. data/lib/theme_check/html_visitor.rb +24 -12
  35. data/lib/theme_check/in_memory_storage.rb +5 -1
  36. data/lib/theme_check/json_check.rb +2 -2
  37. data/lib/theme_check/json_file.rb +9 -4
  38. data/lib/theme_check/language_server/diagnostics_tracker.rb +8 -8
  39. data/lib/theme_check/language_server/handler.rb +88 -6
  40. data/lib/theme_check/language_server/messenger.rb +57 -0
  41. data/lib/theme_check/language_server/server.rb +105 -40
  42. data/lib/theme_check/language_server.rb +1 -0
  43. data/lib/theme_check/{template.rb → liquid_file.rb} +6 -20
  44. data/lib/theme_check/liquid_node.rb +291 -0
  45. data/lib/theme_check/{visitor.rb → liquid_visitor.rb} +4 -4
  46. data/lib/theme_check/locale_diff.rb +5 -5
  47. data/lib/theme_check/node.rb +12 -230
  48. data/lib/theme_check/offense.rb +41 -15
  49. data/lib/theme_check/position.rb +1 -1
  50. data/lib/theme_check/regex_helpers.rb +1 -15
  51. data/lib/theme_check/theme.rb +1 -1
  52. data/lib/theme_check/theme_file.rb +18 -1
  53. data/lib/theme_check/theme_file_rewriter.rb +57 -0
  54. data/lib/theme_check/version.rb +1 -1
  55. data/lib/theme_check.rb +11 -9
  56. data/theme-check.gemspec +2 -1
  57. metadata +23 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 960f944628496ea317205e34678a78ec1e560dbfb48f40cfa33be2d82ebe4770
4
- data.tar.gz: 66e2abe15609c6e5a40d13d05aa0daedf9fbd783e31226bbfb0c6961c1d89ad6
3
+ metadata.gz: 943f8cb722f6c19c1c41e494622922e608a99b50e4ad67f2288a2ed99f406ff3
4
+ data.tar.gz: a8fd83f054895fd366bba2512ff6431d8c470bb3e013ff6c6bf9f6be5366bf38
5
5
  SHA512:
6
- metadata.gz: d920362e7729fc739c0a0202e00a605025db3d80c2fdfac5be9d6d9ea6c74bc4922baa82e093851432417863106c14964f6fdc76f66e55fd7947f33887b989c1
7
- data.tar.gz: 26eb4ba427e8380ece15160c2c27cd052802ec233bb61a4a17e36dcf7f008cc7bc569b71649c525c6d57a7d79654469af65ec664726665584806928cf7258483
6
+ metadata.gz: fb37aed715f2b9f2dd0a8c17f2abf69110d583280d88508ef3f6ee439989c63fe9819025d870cfc1ed64a8deaac19586ac48ab261495e7a371575d9971754980
7
+ data.tar.gz: 64727b7c9684fa094ce498c09a2a3f1dc06ce10fa99aed066af2aa327bd4de70fcc728f76ad127fd08d7b1b6e28b42b06acf96d83b26193814e7eed1b19a2008
@@ -8,15 +8,23 @@ jobs:
8
8
 
9
9
  strategy:
10
10
  matrix:
11
- platform: [ubuntu-latest, windows-latest]
11
+ platform:
12
+ - ubuntu-latest
13
+ - windows-latest
12
14
  version:
13
15
  - 3.0.0
14
16
  - 2.6.6
17
+ theme:
18
+ - Shopify/dawn
15
19
 
16
20
  name: Ruby ${{ matrix.platform }} ${{ matrix.version }}
17
21
 
18
22
  steps:
19
23
  - uses: actions/checkout@v2
24
+ - uses: actions/checkout@v2
25
+ with:
26
+ repository: ${{ matrix.theme }}
27
+ path: ./crash-test-theme
20
28
  - name: Set up Ruby ${{ matrix.version }}
21
29
  uses: ruby/setup-ruby@v1
22
30
  with:
@@ -30,6 +38,6 @@ jobs:
30
38
  run: bundle install --jobs=3 --retry=3 --path=vendor/bundle
31
39
  - name: Run tests
32
40
  run: bundle exec rake
33
- - name: Test runtime
34
- # Testing that runtime can execute, not testing the results themselves
35
- run: bundle exec theme-check ./test/theme | grep -q "files inspected"
41
+ - name: Crash test
42
+ run: |
43
+ bundle exec theme-check --fail-level crash ./crash-test-theme
data/CHANGELOG.md CHANGED
@@ -1,4 +1,41 @@
1
1
 
2
+ v1.7.0 / 2021-09-20
3
+ ===================
4
+
5
+ ### Features
6
+
7
+ * Handle LSP messages concurrently in the Language Server ([#459](https://github.com/shopify/theme-check/issues/459))
8
+ * Adds progress reporting while checking (:eyes: VS Code status bar)
9
+ * Makes completions work while checking (more noticeable on Windows since ruby is 3x slower on Windows)
10
+
11
+ v1.6.2 / 2021-09-16
12
+ ===================
13
+
14
+ * SpaceInsideBraces fixup for tags without arguments ([#458](https://github.com/shopify/theme-check/issues/458))
15
+ * Fix UnusedAssign bug when variable used in for loop range by bumping Liquid to 5.1 ([#456](https://github.com/shopify/theme-check/issues/456))
16
+
17
+ v1.6.1 / 2021-09-15
18
+ ===================
19
+
20
+ * Fix `Undefined method `-' for nil:NilClass` in Node when tag was missing surrounding spaces ([#454](https://github.com/shopify/theme-check/issues/454), [#452](https://github.com/shopify/theme-check/issues/452))
21
+
22
+ v1.6.0 / 2021-09-14
23
+ ===================
24
+
25
+ ### Features
26
+
27
+ * Add `--auto-correct` support to `TranslationKeyExists` (add missing translation as TODO to default locale) ([#422](https://github.com/shopify/theme-check/issues/422))
28
+ * Add `--auto-correct` support to `UnusedSnippet` (delete unused file) ([#416](https://github.com/shopify/theme-check/issues/416))
29
+ * Add `--auto-correct` support to `MissingRequiredTemplateFiles` (create missing files) ([#385](https://github.com/shopify/theme-check/issues/385))
30
+
31
+ ### Fixes
32
+
33
+ * Fix `undefined method [] of nil` in `replace_placeholders` ([#441](https://github.com/shopify/theme-check/issues/441), [#444](https://github.com/shopify/theme-check/issues/444))
34
+ * Disable ConvertIncludeToRender corrector until we fix [#445](https://github.com/shopify/theme-check/issues/445) ([#446](https://github.com/shopify/theme-check/issues/446))
35
+ * Fix a couple of correction bugs ([#442](https://github.com/shopify/theme-check/issues/442), [#439](https://github.com/shopify/theme-check/issues/439))
36
+ * Fix `AssetSizeCSS` error when size is nil ([#419](https://github.com/shopify/theme-check/issues/419))
37
+ * Write JSON to file, not a Ruby Hash. ([#434](https://github.com/shopify/theme-check/issues/434), [#432](https://github.com/shopify/theme-check/issues/432))
38
+
2
39
  v1.5.2 / 2021-09-09
3
40
  ===================
4
41
 
@@ -16,18 +16,18 @@ module ThemeCheck
16
16
  severity :suggestion # :error or :style
17
17
 
18
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.
19
+ # Called with the root node of all theme files
20
+ node.value # is an instance of Nokogiri::XML::Node
21
+ node.theme_file # is the html_file being analyzed, See lib/theme_check/theme_file.rb.
22
+ node.parent # is the parent node.
23
+ node.children # are the children nodes.
24
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.
25
+ theme # Gives you access to all the theme files in the theme. See lib/theme_check/theme.rb.
26
26
  end
27
27
 
28
28
  def on_img(node)
29
29
  # Called for every <img> element in the file.
30
- node.attrbutes["class"] # Get the class attribute of the img element.
30
+ node.attributes["class"] # Get the class attribute of the img element.
31
31
  end
32
32
 
33
33
  def on_a(node)
@@ -16,13 +16,13 @@ module ThemeCheck
16
16
  severity :suggestion # :error or :style
17
17
 
18
18
  def on_document(node)
19
- # Called with the root node of all templates
20
- node.value # is the original Liquid object for this node. See Liquid source code for details.
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.
19
+ # Called with the root node of all liquid_file
20
+ node.value # is the original Liquid object for this node. See Liquid source code for details.
21
+ node.theme_file # is the liquid_file being analyzed, See lib/theme_check/liquid_file.rb.
22
+ node.parent # is the parent node.
23
+ node.children # are the children nodes.
24
24
  # See lib/theme_check/node.rb for more helper methods
25
- theme # Gives you access to all the templates in the theme. See lib/theme_check/theme.rb.
25
+ theme # Gives you access to all the theme files in the theme. See lib/theme_check/theme.rb.
26
26
  end
27
27
 
28
28
  def on_node(node)
@@ -38,8 +38,8 @@ module ThemeCheck
38
38
 
39
39
  # If you find an issue, add an offense:
40
40
  add_offense("Describe the problem...", node: node)
41
- # Or, if the offense is related to the whole template:
42
- add_offense("Describe the problem...", template: node.template)
41
+ # Or, if the offense is related to the whole theme file:
42
+ add_offense("Describe the problem...", theme_file: node.theme_file)
43
43
  end
44
44
 
45
45
  def on_assign(node)
@@ -50,7 +50,7 @@ module ThemeCheck
50
50
  # Called for every `String` (including inside if conditions).
51
51
  if node.parent.block?
52
52
  # If parent is a block, `node.value` is a String written directly to the output when
53
- # the template is rendered.
53
+ # the theme file is rendered.
54
54
  end
55
55
  end
56
56
 
@@ -59,7 +59,7 @@ module ThemeCheck
59
59
  end
60
60
 
61
61
  def on_error(exception)
62
- # Called each time a Liquid exception is raised while parsing the template
62
+ # Called each time a Liquid exception is raised while parsing the theme file
63
63
  end
64
64
 
65
65
  def on_end
@@ -2,7 +2,7 @@
2
2
 
3
3
  The `include` tag is [deprecated][deprecated]. This tag exists to enforce the use of the `render` tag instead of `include`.
4
4
 
5
- The `include` tag works similarly to the `render` tag, but it lets the code inside of the snippet to access and overwrite the variables within its parent template. The `include` tag has been deprecated because the way that it handles variables reduces performance and makes theme code harder to both read and maintain.
5
+ The `include` tag works similarly to the `render` tag, but it lets the code inside of the snippet to access and overwrite the variables within its parent theme file. The `include` tag has been deprecated because the way that it handles variables reduces performance and makes theme code harder to both read and maintain.
6
6
 
7
7
  ## Check Details
8
8
 
@@ -1,6 +1,6 @@
1
1
  # Prevent missing theme-check-enable comments (`MissingEnableComment`)
2
2
 
3
- When `theme-check-disable` is used in the middle of a template, the corresponding `theme-check-enable` comment should also be included.
3
+ When `theme-check-disable` is used in the middle of a theme file, the corresponding `theme-check-enable` comment should also be included.
4
4
 
5
5
  ## Check Details
6
6
 
@@ -29,19 +29,36 @@ module ThemeCheck
29
29
  @html_checks.flat_map(&:offenses)
30
30
  end
31
31
 
32
+ def json_file_count
33
+ @json_file_count ||= @theme.json.size
34
+ end
35
+
36
+ def liquid_file_count
37
+ @liquid_file_count ||= @theme.liquid.size
38
+ end
39
+
40
+ def total_file_count
41
+ json_file_count + liquid_file_count
42
+ end
43
+
32
44
  def analyze_theme
33
45
  reset
34
46
 
35
- liquid_visitor = Visitor.new(@liquid_checks, @disabled_checks)
47
+ liquid_visitor = LiquidVisitor.new(@liquid_checks, @disabled_checks)
36
48
  html_visitor = HtmlVisitor.new(@html_checks)
49
+
37
50
  ThemeCheck.with_liquid_c_disabled do
38
- @theme.liquid.each do |template|
39
- liquid_visitor.visit_template(template)
40
- html_visitor.visit_template(template)
51
+ @theme.liquid.each_with_index do |liquid_file, i|
52
+ yield(liquid_file.relative_path.to_s, i, total_file_count) if block_given?
53
+ liquid_visitor.visit_liquid_file(liquid_file)
54
+ html_visitor.visit_liquid_file(liquid_file)
41
55
  end
42
56
  end
43
57
 
44
- @theme.json.each { |json_file| @json_checks.call(:on_file, json_file) }
58
+ @theme.json.each_with_index do |json_file, i|
59
+ yield(json_file.relative_path.to_s, liquid_file_count + i, total_file_count) if block_given?
60
+ @json_checks.call(:on_file, json_file)
61
+ end
45
62
 
46
63
  finish
47
64
  end
@@ -51,23 +68,30 @@ module ThemeCheck
51
68
 
52
69
  ThemeCheck.with_liquid_c_disabled do
53
70
  # Call all checks that run on the whole theme
54
- liquid_visitor = Visitor.new(@liquid_checks.whole_theme, @disabled_checks)
71
+ liquid_visitor = LiquidVisitor.new(@liquid_checks.whole_theme, @disabled_checks)
55
72
  html_visitor = HtmlVisitor.new(@html_checks.whole_theme)
56
- @theme.liquid.each do |template|
57
- liquid_visitor.visit_template(template)
58
- html_visitor.visit_template(template)
73
+ total = total_file_count + files.size
74
+ @theme.liquid.each_with_index do |liquid_file, i|
75
+ yield(liquid_file.relative_path.to_s, i, total) if block_given?
76
+ liquid_visitor.visit_liquid_file(liquid_file)
77
+ html_visitor.visit_liquid_file(liquid_file)
78
+ end
79
+
80
+ @theme.json.each_with_index do |json_file, i|
81
+ yield(json_file.relative_path.to_s, liquid_file_count + i, total) if block_given?
82
+ @json_checks.whole_theme.call(:on_file, json_file)
59
83
  end
60
- @theme.json.each { |json_file| @json_checks.whole_theme.call(:on_file, json_file) }
61
84
 
62
85
  # Call checks that run on a single files, only on specified file
63
- liquid_visitor = Visitor.new(@liquid_checks.single_file, @disabled_checks)
86
+ liquid_visitor = LiquidVisitor.new(@liquid_checks.single_file, @disabled_checks)
64
87
  html_visitor = HtmlVisitor.new(@html_checks.single_file)
65
- files.each do |file|
66
- if file.liquid?
67
- liquid_visitor.visit_template(file)
68
- html_visitor.visit_template(file)
69
- elsif file.json?
70
- @json_checks.single_file.call(:on_file, file)
88
+ files.each_with_index do |theme_file, i|
89
+ yield(theme_file.relative_path.to_s, total_file_count + i, total) if block_given?
90
+ if theme_file.liquid?
91
+ liquid_visitor.visit_liquid_file(theme_file)
92
+ html_visitor.visit_liquid_file(theme_file)
93
+ elsif theme_file.json?
94
+ @json_checks.single_file.call(:on_file, theme_file)
71
95
  end
72
96
  end
73
97
  end
@@ -86,6 +110,11 @@ module ThemeCheck
86
110
  def correct_offenses
87
111
  if @auto_correct
88
112
  offenses.each(&:correct)
113
+ end
114
+ end
115
+
116
+ def write_corrections
117
+ if @auto_correct
89
118
  @theme.liquid.each(&:write)
90
119
  @theme.json.each(&:write)
91
120
  end
@@ -9,10 +9,21 @@ module ThemeCheck
9
9
  @content = nil
10
10
  end
11
11
 
12
- alias_method :content, :source
12
+ def rewriter
13
+ @rewriter ||= ThemeFileRewriter.new(@relative_path, source)
14
+ end
15
+
16
+ def write
17
+ content = rewriter.to_s
18
+ if source != content
19
+ @storage.write(@relative_path, content.gsub("\n", @eol))
20
+ @source = content
21
+ @rewriter = nil
22
+ end
23
+ end
13
24
 
14
25
  def gzipped_size
15
- @gzipped_size ||= Zlib.gzip(content).bytesize
26
+ @gzipped_size ||= Zlib.gzip(source).bytesize
16
27
  end
17
28
 
18
29
  def name
@@ -46,7 +46,7 @@ module ThemeCheck
46
46
  end
47
47
 
48
48
  def severity_value(severity)
49
- SEVERITY_VALUES[severity]
49
+ SEVERITY_VALUES[severity] || -1
50
50
  end
51
51
 
52
52
  def categories(*categories)
@@ -91,8 +91,8 @@ module ThemeCheck
91
91
  @offenses ||= []
92
92
  end
93
93
 
94
- def add_offense(message, node: nil, template: node&.template, markup: nil, line_number: nil, node_markup_offset: 0, &block)
95
- offenses << Offense.new(check: self, message: message, template: template, node: node, markup: markup, line_number: line_number, node_markup_offset: node_markup_offset, correction: block)
94
+ def add_offense(message, node: nil, theme_file: node&.theme_file, markup: nil, line_number: nil, node_markup_offset: 0, &block)
95
+ offenses << Offense.new(check: self, message: message, theme_file: theme_file, node: node, markup: markup, line_number: line_number, node_markup_offset: node_markup_offset, correction: block)
96
96
  end
97
97
 
98
98
  def severity
@@ -22,5 +22,20 @@ module ThemeCheck
22
22
  node: node
23
23
  )
24
24
  end
25
+
26
+ def href_to_file_size(href)
27
+ # asset_url (+ optional stylesheet_tag) variables
28
+ if href =~ /^#{LIQUID_VARIABLE}$/o && href =~ /asset_url/ && href =~ Liquid::QuotedString
29
+ asset_id = Regexp.last_match(0).gsub(START_OR_END_QUOTE, "")
30
+ asset = @theme.assets.find { |a| a.name.end_with?("/" + asset_id) }
31
+ return if asset.nil?
32
+ asset.gzipped_size
33
+
34
+ # remote URLs
35
+ elsif href =~ %r{^(https?:)?//}
36
+ asset = RemoteAssetFile.from_src(href)
37
+ asset.gzipped_size
38
+ end
39
+ end
25
40
  end
26
41
  end
@@ -13,12 +13,29 @@ module ThemeCheck
13
13
  def on_variable(node)
14
14
  used_filters = node.value.filters.map { |name, *_rest| name }
15
15
  return unless used_filters.include?("stylesheet_tag")
16
- file_size = href_to_file_size('{{' + node.markup + '}}')
16
+ file_size = stylesheet_tag_pipeline_to_file_size(node.markup)
17
+ return if file_size.nil?
17
18
  return if file_size <= @threshold_in_bytes
18
19
  add_offense(
19
20
  "CSS on every page load exceeding compressed size threshold (#{@threshold_in_bytes} Bytes).",
20
21
  node: node
21
22
  )
22
23
  end
24
+
25
+ def stylesheet_tag_pipeline_to_file_size(href)
26
+ # asset_url
27
+ if href =~ /asset_url/ && href =~ Liquid::QuotedString
28
+ asset_id = Regexp.last_match(0).gsub(START_OR_END_QUOTE, "")
29
+ asset = @theme.assets.find { |a| a.name.end_with?("/" + asset_id) }
30
+ return if asset.nil?
31
+ asset.gzipped_size
32
+
33
+ # remote URLs
34
+ elsif href =~ %r{(https?:)?//[^'"]+}
35
+ url = Regexp.last_match(0)
36
+ asset = RemoteAssetFile.from_src(url)
37
+ asset.gzipped_size
38
+ end
39
+ end
23
40
  end
24
41
  end
@@ -8,7 +8,8 @@ module ThemeCheck
8
8
 
9
9
  def on_include(node)
10
10
  add_offense("`include` is deprecated - convert it to `render`", node: node) do |corrector|
11
- corrector.replace(node, "render \'#{node.value.template_name_expr}\' ")
11
+ # We need to fix #445 and pass the variables from the context or don't replace at all.
12
+ # corrector.replace(node, "render \'#{node.value.template_name_expr}\' ")
12
13
  end
13
14
  end
14
15
  end
@@ -5,8 +5,8 @@ module ThemeCheck
5
5
  category :html
6
6
  doc docs_url(__FILE__)
7
7
 
8
- def on_parse_error(exception, template)
9
- add_offense("HTML in this template can not be parsed: #{exception.message}", template: template)
8
+ def on_parse_error(exception, theme_file)
9
+ add_offense("HTML in this template can not be parsed: #{exception.message}", theme_file: theme_file)
10
10
  end
11
11
  end
12
12
  end
@@ -23,7 +23,7 @@ module ThemeCheck
23
23
 
24
24
  @files.each do |file|
25
25
  diff = LocaleDiff.new(@theme.default_locale_json.content, file.content)
26
- diff.add_as_offenses(self, template: file)
26
+ diff.add_as_offenses(self, theme_file: file)
27
27
  end
28
28
  end
29
29
  end
@@ -9,19 +9,33 @@ module ThemeCheck
9
9
  doc docs_url(__FILE__)
10
10
 
11
11
  REQUIRED_LIQUID_FILES = %w(layout/theme)
12
- REQUIRED_TEMPLATE_FILES = %w(
13
- index product collection cart blog article page list-collections search 404
12
+
13
+ REQUIRED_LIQUID_TEMPLATE_FILES = %w(
14
14
  gift_card customers/account customers/activate_account customers/addresses
15
- customers/login customers/order customers/register customers/reset_password password
16
- )
17
- .map { |file| "templates/#{file}" }
15
+ customers/login customers/order customers/register customers/reset_password
16
+ ).map { |file| "templates/#{file}" }
17
+
18
+ REQUIRED_JSON_TEMPLATE_FILES = %w(
19
+ index product collection cart blog article page list-collections search 404
20
+ password
21
+ ).map { |file| "templates/#{file}" }
22
+
23
+ REQUIRED_TEMPLATE_FILES = (REQUIRED_LIQUID_TEMPLATE_FILES + REQUIRED_JSON_TEMPLATE_FILES)
18
24
 
19
25
  def on_end
20
26
  (REQUIRED_LIQUID_FILES - theme.liquid.map(&:name)).each do |file|
21
- add_offense("'#{file}.liquid' is missing")
27
+ add_offense("'#{file}.liquid' is missing") do |corrector|
28
+ corrector.create(@theme, "#{file}.liquid", "")
29
+ end
22
30
  end
23
31
  (REQUIRED_TEMPLATE_FILES - (theme.liquid + theme.json).map(&:name)).each do |file|
24
- add_offense("'#{file}.liquid' or '#{file}.json' is missing")
32
+ add_offense("'#{file}.liquid' or '#{file}.json' is missing") do |corrector|
33
+ if REQUIRED_LIQUID_TEMPLATE_FILES.include?(file)
34
+ corrector.create(@theme, "#{file}.liquid", "")
35
+ else
36
+ corrector.create(@theme, "#{file}.json", "")
37
+ end
38
+ end
25
39
  end
26
40
  end
27
41
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module ThemeCheck
3
- # Reports missing include/render/section template
3
+ # Reports missing include/render/section liquid file
4
4
  class MissingTemplate < LiquidCheck
5
5
  severity :suggestion
6
6
  category :liquid
@@ -12,17 +12,17 @@ module ThemeCheck
12
12
  end
13
13
 
14
14
  def on_include(node)
15
- template = node.value.template_name_expr
16
- if template.is_a?(String)
17
- add_missing_offense("snippets/#{template}", node: node)
15
+ snippet = node.value.template_name_expr
16
+ if snippet.is_a?(String)
17
+ add_missing_offense("snippets/#{snippet}", node: node)
18
18
  end
19
19
  end
20
20
 
21
21
  alias_method :on_render, :on_include
22
22
 
23
23
  def on_section(node)
24
- template = node.value.section_name
25
- add_missing_offense("sections/#{template}", node: node)
24
+ section = node.value.section_name
25
+ add_missing_offense("sections/#{section}", node: node)
26
26
  end
27
27
 
28
28
  private
@@ -26,12 +26,12 @@ module ThemeCheck
26
26
  end
27
27
 
28
28
  def on_document(node)
29
- @templates[node.template.name] = TemplateInfo.new(Set.new)
29
+ @templates[node.theme_file.name] = TemplateInfo.new(Set.new)
30
30
  end
31
31
 
32
32
  def on_include(node)
33
33
  if node.value.template_name_expr.is_a?(String)
34
- @templates[node.template.name].includes << node
34
+ @templates[node.theme_file.name].includes << node
35
35
  end
36
36
  end
37
37
  alias_method :on_render, :on_include
@@ -14,7 +14,7 @@ module ThemeCheck
14
14
  end
15
15
 
16
16
  def on_document(node)
17
- @layout_theme_node = node if node.template.name == LAYOUT_FILENAME
17
+ @layout_theme_node = node if node.theme_file.name == LAYOUT_FILENAME
18
18
  end
19
19
 
20
20
  def on_variable(node)
@@ -25,7 +25,7 @@ module ThemeCheck
25
25
  end
26
26
 
27
27
  def after_document(node)
28
- return unless node.template.name == LAYOUT_FILENAME
28
+ return unless node.theme_file.name == LAYOUT_FILENAME
29
29
 
30
30
  add_missing_object_offense("content_for_layout") unless @content_for_layout_found
31
31
  add_missing_object_offense("content_for_header") unless @content_for_header_found
@@ -7,23 +7,23 @@ module ThemeCheck
7
7
  doc docs_url(__FILE__)
8
8
 
9
9
  def on_document(node)
10
- node.template.warnings.each do |warning|
11
- add_exception_as_offense(warning, template: node.template)
10
+ node.theme_file.warnings.each do |warning|
11
+ add_exception_as_offense(warning, theme_file: node.theme_file)
12
12
  end
13
13
  end
14
14
 
15
15
  def on_error(exception)
16
- add_exception_as_offense(exception, template: theme[exception.template_name])
16
+ add_exception_as_offense(exception, theme_file: theme[exception.template_name])
17
17
  end
18
18
 
19
19
  private
20
20
 
21
- def add_exception_as_offense(exception, template:)
21
+ def add_exception_as_offense(exception, theme_file:)
22
22
  add_offense(
23
23
  exception.to_s(false).sub(/ in ".*"$/, ''),
24
24
  line_number: exception.line_number,
25
25
  markup: exception.markup_context&.sub(/^in "(.*)"$/, '\1'),
26
- template: template,
26
+ theme_file: theme_file,
27
27
  )
28
28
  end
29
29
  end
@@ -29,9 +29,9 @@ module ThemeCheck
29
29
  end
30
30
 
31
31
  def after_document(node)
32
- lines = node.template.source.count("\n") - @excluded_lines
32
+ lines = node.theme_file.source.count("\n") - @excluded_lines
33
33
  if lines > @max_length
34
- add_offense("Template has too many lines [#{lines}/#{@max_length}]", template: node.template)
34
+ add_offense("Template has too many lines [#{lines}/#{@max_length}]", theme_file: node.theme_file)
35
35
  end
36
36
  end
37
37
 
@@ -29,7 +29,9 @@ module ThemeCheck
29
29
  "'#{key_node.value}' does not have a matching entry in '#{@theme.default_locale_json.relative_path}'",
30
30
  node: node,
31
31
  markup: key_node.value,
32
- )
32
+ ) do |corrector|
33
+ corrector.add_default_translation_key(@theme.default_locale_json, key_node.value.split("."), "TODO")
34
+ end
33
35
  end
34
36
  end
35
37
 
@@ -62,22 +62,22 @@ module ThemeCheck
62
62
 
63
63
  def on_document(node)
64
64
  return if ignore?(node)
65
- @files[node.template.name] = TemplateInfo.new
65
+ @files[node.theme_file.name] = TemplateInfo.new
66
66
  end
67
67
 
68
68
  def on_assign(node)
69
69
  return if ignore?(node)
70
- @files[node.template.name].all_assigns[node.value.to] = node
70
+ @files[node.theme_file.name].all_assigns[node.value.to] = node
71
71
  end
72
72
 
73
73
  def on_capture(node)
74
74
  return if ignore?(node)
75
- @files[node.template.name].all_captures[node.value.instance_variable_get('@to')] = node
75
+ @files[node.theme_file.name].all_captures[node.value.instance_variable_get('@to')] = node
76
76
  end
77
77
 
78
78
  def on_for(node)
79
79
  return if ignore?(node)
80
- @files[node.template.name].all_forloops[node.value.variable_name] = node
80
+ @files[node.theme_file.name].all_forloops[node.value.variable_name] = node
81
81
  end
82
82
 
83
83
  def on_include(_node)
@@ -90,7 +90,7 @@ module ThemeCheck
90
90
  return unless node.value.template_name_expr.is_a?(String)
91
91
 
92
92
  snippet_name = "snippets/#{node.value.template_name_expr}"
93
- @files[node.template.name].add_render(
93
+ @files[node.theme_file.name].add_render(
94
94
  name: snippet_name,
95
95
  node: node,
96
96
  )
@@ -98,7 +98,7 @@ module ThemeCheck
98
98
 
99
99
  def on_variable_lookup(node)
100
100
  return if ignore?(node)
101
- @files[node.template.name].add_variable_lookup(
101
+ @files[node.theme_file.name].add_variable_lookup(
102
102
  name: node.value.name,
103
103
  node: node,
104
104
  )
@@ -130,7 +130,7 @@ module ThemeCheck
130
130
  private
131
131
 
132
132
  def ignore?(node)
133
- @exclude_snippets && node.template.snippet?
133
+ @exclude_snippets && node.theme_file.snippet?
134
134
  end
135
135
 
136
136
  def each_template