theme-check 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b606fffc2525680e6d47cf1d45b3fbdd514c79cf426dfd28baaec20e1cc083f
4
- data.tar.gz: f0b9e3b0da8f41ae48e11d91ff1ccd780e0ed6cc5b8ba80694c3cd70a33e04a0
3
+ metadata.gz: 56b6a91e5ac4b1e2045b1e4fb2748e5ecb9600206f9ba07df401c1410bf494fc
4
+ data.tar.gz: b6fb1b3957ae5aecd7b2efbaa76a2e3c07390ec442f94d416ea5b20ca2cbf966
5
5
  SHA512:
6
- metadata.gz: 23ce6e8b332e57cf523db93cf14ca9c948e569703633d5b82f106e95e66dd613ab30fa448226cf4f624b24da2675179220e7fc9fe206bfa9521f722c74356ba2
7
- data.tar.gz: 22e2469eba1fc8aca4e881cfc5d0ad5ea7c16a057cdba6327310906099497b72d18dbef2d4f69d328528d6801f0abb91fac78a692f68387f7378d2c8fd3986dd
6
+ metadata.gz: e2ca68b31968949dc52240c8ee5ca607e10e063b500cda0a7b06306589849f2bc0098f1b0742f962a91a0ca282aa504acb9f7c0de6b785afff0b577b84fa6eba
7
+ data.tar.gz: c7186299a1168c5ad1e3cd6544ee8c8248b96a492e1dc82481c26a69e75fb1f04172ceb58da61e310a393fd36c9b990464542e7528810c7bea556b5b8ce9b61d
data/CHANGELOG.md CHANGED
@@ -1,4 +1,10 @@
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
+
2
8
  v0.10.0 / 2021-06-08
3
9
  ==================
4
10
 
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/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/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
+
@@ -0,0 +1,19 @@
1
+ # JSON check API
2
+
3
+ For checking the content of `.json` files.
4
+
5
+ ```ruby
6
+ module ThemeCheck
7
+ class MyCheckName < JsonCheck
8
+ category :json,
9
+ # A check can belong to multiple categories. Valid ones:
10
+ categories :translation, :performance
11
+ severity :suggestion # :error or :style
12
+
13
+ def on_file(file)
14
+ file # an instance of `ThemeCheck::JsonFile`
15
+ file.content # the parsed JSON, as a Ruby object, usually a Hash
16
+ end
17
+ end
18
+ end
19
+ ```
@@ -0,0 +1,99 @@
1
+ # Liquid check API
2
+
3
+ For checking the Liquid code in `.liquid` files.
4
+
5
+ All code inside `{% ... %}` or `{{ ... }}` is Liquid code.
6
+
7
+ Liquid files are parsed using the Liquid parser, by consequence you will get Liquid nodes (tags, blocks) in your callback methods. Check the Liquid source for details on those nodes: [Liquid source][liquidsource].
8
+
9
+
10
+ ```ruby
11
+ module ThemeCheck
12
+ class MyCheckName < LiquidCheck
13
+ category :liquid,
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 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.
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.
26
+ end
27
+
28
+ def on_node(node)
29
+ # Called for every node
30
+ end
31
+
32
+ def on_tag(node)
33
+ # Called for each tag (if, include, for, assign, etc.)
34
+ end
35
+
36
+ def after_tag(node)
37
+ # Called after the tag children have been visited
38
+
39
+ # If you find an issue, add an offense:
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)
43
+ end
44
+
45
+ def on_assign(node)
46
+ # Called only for {% assign ... %} tags
47
+ end
48
+
49
+ def on_string(node)
50
+ # Called for every `String` (including inside if conditions).
51
+ if node.parent.block?
52
+ # If parent is a block, `node.value` is a String written directly to the output when
53
+ # the template is rendered.
54
+ end
55
+ end
56
+
57
+ def on_variable(node)
58
+ # Called for each {{ ... }}
59
+ end
60
+
61
+ def on_error(exception)
62
+ # Called each time a Liquid exception is raised while parsing the template
63
+ end
64
+
65
+ def on_end
66
+ # A special callback after we're done visiting all the files of the theme
67
+ end
68
+
69
+ # Each type of node has a corresponding `on_node_class_name` & `after_node_class_name`
70
+ # A few common examples:
71
+ # on_capture(node)
72
+ # on_case(node)
73
+ # on_comment(node)
74
+ # on_if(node)
75
+ # on_condition(node)
76
+ # on_else_condition(node)
77
+ # on_for(node)
78
+ # on_form(node)
79
+ # on_include(node)
80
+ # on_integer(node)
81
+ # on_layout(node)
82
+ # on_method_literal(node)
83
+ # on_paginate(node)
84
+ # on_range(node)
85
+ # on_render(node)
86
+ # on_schema(node)
87
+ # on_section(node)
88
+ # on_style(node)
89
+ # on_unless(node)
90
+ # on_variable_lookup(node)
91
+ end
92
+ end
93
+ ```
94
+
95
+ ## Resources
96
+
97
+ - [Liquid source][liquidsource]
98
+
99
+ [liquidsource]: https://github.com/Shopify/liquid/tree/master/lib/liquid
@@ -1,4 +1,4 @@
1
- # Check Title (`CheckClassName`)
1
+ # Check Title (`<%= class_name %>`)
2
2
 
3
3
  A brief paragraph explaining why the check exists.
4
4
 
@@ -21,7 +21,7 @@ This check is aimed at eliminating ...
21
21
  The default configuration for this check is the following:
22
22
 
23
23
  ```yaml
24
- CheckClassName:
24
+ <%= class_name %>:
25
25
  enabled: true
26
26
  some_option: 10
27
27
  ```
@@ -36,12 +36,12 @@ If you don't want to ..., then it's safe to disable this rule.
36
36
 
37
37
  ## Version
38
38
 
39
- This check has been introduced in Theme Check X.X.X.
39
+ This check has been introduced in Theme Check THEME_CHECK_VERSION.
40
40
 
41
41
  ## Resources
42
42
 
43
43
  - [Rule Source][codesource]
44
44
  - [Documentation Source][docsource]
45
45
 
46
- [codesource]: /lib/theme_check/checks/check_class_name.rb
47
- [docsource]: /docs/checks/check_class_name.md
46
+ [codesource]: /<%= code_source %>
47
+ [docsource]: /<%= doc_source %>
@@ -18,7 +18,6 @@ module ThemeCheck
18
18
  CATEGORIES = [
19
19
  :liquid,
20
20
  :translation,
21
- :performance,
22
21
  :html,
23
22
  :json,
24
23
  :performance,
@@ -124,6 +123,7 @@ module ThemeCheck
124
123
  def ==(other)
125
124
  other.is_a?(Check) && code_name == other.code_name
126
125
  end
126
+ alias_method :eql?, :==
127
127
 
128
128
  def to_s
129
129
  s = +"#{code_name}:\n"
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module ThemeCheck
3
+ # TODO: inherit from HtmlCheck or JsonCheck if working on a non-Liquid check
4
+ class <%= class_name %> < LiquidCheck
5
+ severity :suggestion
6
+ category :liquid
7
+ doc docs_url(__FILE__)
8
+
9
+ # TODO: def on_<NODE_TYPE>
10
+ end
11
+ end
@@ -46,6 +46,11 @@ module ThemeCheck
46
46
  false
47
47
  end
48
48
 
49
+ def ==(other)
50
+ other.is_a?(JsonFile) && relative_path == other.relative_path
51
+ end
52
+ alias_method :eql?, :==
53
+
49
54
  private
50
55
 
51
56
  def load!
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ require "logger"
2
3
 
3
4
  module ThemeCheck
4
5
  module LanguageServer
@@ -16,6 +17,7 @@ module ThemeCheck
16
17
  def build_diagnostics(offenses, analyzed_files: nil)
17
18
  reported_files = Set.new
18
19
  new_single_file_offenses = {}
20
+ analyzed_files = analyzed_files.map { |path| Pathname.new(path) } if analyzed_files
19
21
 
20
22
  offenses.group_by(&:template).each do |template, template_offenses|
21
23
  next unless template
@@ -124,13 +124,13 @@ module ThemeCheck
124
124
 
125
125
  def ==(other)
126
126
  other.is_a?(Offense) &&
127
- check == other.check &&
127
+ code_name == other.code_name &&
128
128
  message == other.message &&
129
- template == other.template &&
130
- node == other.node &&
131
- markup == other.markup &&
132
- line_number == other.line_number
129
+ location == other.location &&
130
+ start_index == other.start_index &&
131
+ end_index == other.end_index
133
132
  end
133
+ alias_method :eql?, :==
134
134
 
135
135
  def to_s
136
136
  if template
@@ -91,6 +91,7 @@ module ThemeCheck
91
91
  def ==(other)
92
92
  other.is_a?(Template) && relative_path == other.relative_path
93
93
  end
94
+ alias_method :eql?, :==
94
95
 
95
96
  def self.parse(source)
96
97
  Liquid::Template.parse(
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ThemeCheck
3
- VERSION = "0.10.0"
3
+ VERSION = "0.10.1"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: theme-check
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marc-André Cournoyer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-06-08 00:00:00.000000000 Z
11
+ date: 2021-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: liquid
@@ -69,7 +69,11 @@ files:
69
69
  - data/shopify_liquid/tags.yml
70
70
  - data/shopify_translation_keys.yml
71
71
  - dev.yml
72
- - docs/checks/CHECK_DOCS_TEMPLATE.md
72
+ - docs/api/check.md
73
+ - docs/api/html_check.md
74
+ - docs/api/json_check.md
75
+ - docs/api/liquid_check.md
76
+ - docs/checks/TEMPLATE.md.erb
73
77
  - docs/checks/asset_size_css.md
74
78
  - docs/checks/asset_size_javascript.md
75
79
  - docs/checks/asset_url_filters.md
@@ -111,6 +115,7 @@ files:
111
115
  - lib/theme_check/bug.rb
112
116
  - lib/theme_check/check.rb
113
117
  - lib/theme_check/checks.rb
118
+ - lib/theme_check/checks/TEMPLATE.rb.erb
114
119
  - lib/theme_check/checks/asset_size_css.rb
115
120
  - lib/theme_check/checks/asset_size_javascript.rb
116
121
  - lib/theme_check/checks/asset_url_filters.rb