theme-check 1.5.2 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
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