theme-check 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.github/probots.yml +3 -0
  3. data/.github/workflows/theme-check.yml +28 -0
  4. data/.gitignore +13 -0
  5. data/.rubocop.yml +18 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/CONTRIBUTING.md +132 -0
  8. data/Gemfile +26 -0
  9. data/Guardfile +7 -0
  10. data/LICENSE.md +8 -0
  11. data/README.md +71 -0
  12. data/Rakefile +14 -0
  13. data/bin/liquid-server +4 -0
  14. data/config/default.yml +63 -0
  15. data/data/shopify_liquid/filters.yml +174 -0
  16. data/data/shopify_liquid/objects.yml +81 -0
  17. data/dev.yml +23 -0
  18. data/docs/preview.png +0 -0
  19. data/exe/theme-check +6 -0
  20. data/exe/theme-check-language-server +12 -0
  21. data/lib/theme_check.rb +25 -0
  22. data/lib/theme_check/analyzer.rb +43 -0
  23. data/lib/theme_check/check.rb +92 -0
  24. data/lib/theme_check/checks.rb +12 -0
  25. data/lib/theme_check/checks/convert_include_to_render.rb +13 -0
  26. data/lib/theme_check/checks/default_locale.rb +12 -0
  27. data/lib/theme_check/checks/liquid_tag.rb +48 -0
  28. data/lib/theme_check/checks/matching_schema_translations.rb +73 -0
  29. data/lib/theme_check/checks/matching_translations.rb +29 -0
  30. data/lib/theme_check/checks/missing_required_template_files.rb +29 -0
  31. data/lib/theme_check/checks/missing_template.rb +25 -0
  32. data/lib/theme_check/checks/nested_snippet.rb +46 -0
  33. data/lib/theme_check/checks/required_directories.rb +24 -0
  34. data/lib/theme_check/checks/required_layout_theme_object.rb +40 -0
  35. data/lib/theme_check/checks/space_inside_braces.rb +58 -0
  36. data/lib/theme_check/checks/syntax_error.rb +29 -0
  37. data/lib/theme_check/checks/template_length.rb +18 -0
  38. data/lib/theme_check/checks/translation_key_exists.rb +35 -0
  39. data/lib/theme_check/checks/undefined_object.rb +86 -0
  40. data/lib/theme_check/checks/unknown_filter.rb +25 -0
  41. data/lib/theme_check/checks/unused_assign.rb +54 -0
  42. data/lib/theme_check/checks/unused_snippet.rb +34 -0
  43. data/lib/theme_check/checks/valid_html_translation.rb +43 -0
  44. data/lib/theme_check/checks/valid_json.rb +14 -0
  45. data/lib/theme_check/checks/valid_schema.rb +13 -0
  46. data/lib/theme_check/checks_tracking.rb +8 -0
  47. data/lib/theme_check/cli.rb +78 -0
  48. data/lib/theme_check/config.rb +108 -0
  49. data/lib/theme_check/json_check.rb +11 -0
  50. data/lib/theme_check/json_file.rb +47 -0
  51. data/lib/theme_check/json_helpers.rb +9 -0
  52. data/lib/theme_check/language_server.rb +11 -0
  53. data/lib/theme_check/language_server/handler.rb +117 -0
  54. data/lib/theme_check/language_server/server.rb +140 -0
  55. data/lib/theme_check/liquid_check.rb +13 -0
  56. data/lib/theme_check/locale_diff.rb +69 -0
  57. data/lib/theme_check/node.rb +117 -0
  58. data/lib/theme_check/offense.rb +104 -0
  59. data/lib/theme_check/parsing_helpers.rb +17 -0
  60. data/lib/theme_check/printer.rb +74 -0
  61. data/lib/theme_check/shopify_liquid.rb +3 -0
  62. data/lib/theme_check/shopify_liquid/filter.rb +18 -0
  63. data/lib/theme_check/shopify_liquid/object.rb +16 -0
  64. data/lib/theme_check/tags.rb +146 -0
  65. data/lib/theme_check/template.rb +73 -0
  66. data/lib/theme_check/theme.rb +60 -0
  67. data/lib/theme_check/version.rb +4 -0
  68. data/lib/theme_check/visitor.rb +37 -0
  69. data/theme-check.gemspec +28 -0
  70. metadata +156 -0
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ require "pathname"
3
+
4
+ module ThemeCheck
5
+ class Theme
6
+ DEFAULT_LOCALE_REGEXP = %r{^locales/(.*)\.default$}
7
+ attr_reader :root
8
+
9
+ def initialize(root)
10
+ @root = Pathname.new(root)
11
+ end
12
+
13
+ def liquid
14
+ @liquid ||= @root.glob("**/*.liquid").map { |path| Template.new(path, @root) }
15
+ end
16
+
17
+ def json
18
+ @json ||= @root.glob("**/*.json").map { |path| JsonFile.new(path, @root) }
19
+ end
20
+
21
+ def default_locale_json
22
+ return @default_locale_json if defined?(@default_locale_json)
23
+ @default_locale_json = json.find do |json_file|
24
+ json_file.name.match?(DEFAULT_LOCALE_REGEXP)
25
+ end
26
+ end
27
+
28
+ def default_locale
29
+ if default_locale_json
30
+ default_locale_json.name[DEFAULT_LOCALE_REGEXP, 1]
31
+ else
32
+ "en"
33
+ end
34
+ end
35
+
36
+ def all
37
+ @all ||= json + liquid
38
+ end
39
+
40
+ def [](name)
41
+ all.find { |t| t.name == name }
42
+ end
43
+
44
+ def templates
45
+ liquid.select(&:template?)
46
+ end
47
+
48
+ def sections
49
+ liquid.select(&:section?)
50
+ end
51
+
52
+ def snippets
53
+ liquid.select(&:snippet?)
54
+ end
55
+
56
+ def directories
57
+ @directories ||= @root.glob('*').select { |f| File.directory?(f) }.map { |f| f.relative_path_from(@root) }
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+ module ThemeCheck
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ module ThemeCheck
3
+ class Visitor
4
+ def initialize(checks)
5
+ @checks = checks
6
+ end
7
+
8
+ def visit_template(template)
9
+ visit(Node.new(template.root, nil, template))
10
+ rescue Liquid::Error => exception
11
+ exception.template_name = template.name
12
+ call_checks(:on_error, exception)
13
+ end
14
+
15
+ def visit(node)
16
+ call_checks(:on_node, node)
17
+ call_checks(:on_tag, node) if node.tag?
18
+ call_checks(:"on_#{node.type_name}", node)
19
+ node.children.each { |child| visit(child) }
20
+ unless node.literal?
21
+ call_checks(:"after_#{node.type_name}", node)
22
+ call_checks(:after_tag, node) if node.tag?
23
+ call_checks(:after_node, node)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def visit_children(node)
30
+ node.children.each { |child| visit(child) }
31
+ end
32
+
33
+ def call_checks(method, *args)
34
+ @checks.call(method, *args)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "theme_check/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "theme-check"
8
+ spec.version = ThemeCheck::VERSION
9
+ spec.authors = ["Marc-André Cournoyer"]
10
+ spec.email = ["marcandre.cournoyer@shopify.com"]
11
+
12
+ spec.summary = "A Shopify Theme Linter"
13
+ spec.homepage = "https://github.com/Shopify/theme-check"
14
+ spec.license = "MIT"
15
+
16
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
+
18
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
+ %x{git ls-files -z}.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
+ end
21
+ spec.bindir = "exe"
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_dependency('liquid', '>= 5')
26
+ spec.add_dependency('activesupport')
27
+ spec.add_dependency('nokogumbo')
28
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: theme-check
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Marc-André Cournoyer
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-01-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: liquid
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogumbo
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - marcandre.cournoyer@shopify.com
58
+ executables:
59
+ - theme-check
60
+ - theme-check-language-server
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".github/probots.yml"
65
+ - ".github/workflows/theme-check.yml"
66
+ - ".gitignore"
67
+ - ".rubocop.yml"
68
+ - CODE_OF_CONDUCT.md
69
+ - CONTRIBUTING.md
70
+ - Gemfile
71
+ - Guardfile
72
+ - LICENSE.md
73
+ - README.md
74
+ - Rakefile
75
+ - bin/liquid-server
76
+ - config/default.yml
77
+ - data/shopify_liquid/filters.yml
78
+ - data/shopify_liquid/objects.yml
79
+ - dev.yml
80
+ - docs/preview.png
81
+ - exe/theme-check
82
+ - exe/theme-check-language-server
83
+ - lib/theme_check.rb
84
+ - lib/theme_check/analyzer.rb
85
+ - lib/theme_check/check.rb
86
+ - lib/theme_check/checks.rb
87
+ - lib/theme_check/checks/convert_include_to_render.rb
88
+ - lib/theme_check/checks/default_locale.rb
89
+ - lib/theme_check/checks/liquid_tag.rb
90
+ - lib/theme_check/checks/matching_schema_translations.rb
91
+ - lib/theme_check/checks/matching_translations.rb
92
+ - lib/theme_check/checks/missing_required_template_files.rb
93
+ - lib/theme_check/checks/missing_template.rb
94
+ - lib/theme_check/checks/nested_snippet.rb
95
+ - lib/theme_check/checks/required_directories.rb
96
+ - lib/theme_check/checks/required_layout_theme_object.rb
97
+ - lib/theme_check/checks/space_inside_braces.rb
98
+ - lib/theme_check/checks/syntax_error.rb
99
+ - lib/theme_check/checks/template_length.rb
100
+ - lib/theme_check/checks/translation_key_exists.rb
101
+ - lib/theme_check/checks/undefined_object.rb
102
+ - lib/theme_check/checks/unknown_filter.rb
103
+ - lib/theme_check/checks/unused_assign.rb
104
+ - lib/theme_check/checks/unused_snippet.rb
105
+ - lib/theme_check/checks/valid_html_translation.rb
106
+ - lib/theme_check/checks/valid_json.rb
107
+ - lib/theme_check/checks/valid_schema.rb
108
+ - lib/theme_check/checks_tracking.rb
109
+ - lib/theme_check/cli.rb
110
+ - lib/theme_check/config.rb
111
+ - lib/theme_check/json_check.rb
112
+ - lib/theme_check/json_file.rb
113
+ - lib/theme_check/json_helpers.rb
114
+ - lib/theme_check/language_server.rb
115
+ - lib/theme_check/language_server/handler.rb
116
+ - lib/theme_check/language_server/server.rb
117
+ - lib/theme_check/liquid_check.rb
118
+ - lib/theme_check/locale_diff.rb
119
+ - lib/theme_check/node.rb
120
+ - lib/theme_check/offense.rb
121
+ - lib/theme_check/parsing_helpers.rb
122
+ - lib/theme_check/printer.rb
123
+ - lib/theme_check/shopify_liquid.rb
124
+ - lib/theme_check/shopify_liquid/filter.rb
125
+ - lib/theme_check/shopify_liquid/object.rb
126
+ - lib/theme_check/tags.rb
127
+ - lib/theme_check/template.rb
128
+ - lib/theme_check/theme.rb
129
+ - lib/theme_check/version.rb
130
+ - lib/theme_check/visitor.rb
131
+ - theme-check.gemspec
132
+ homepage: https://github.com/Shopify/theme-check
133
+ licenses:
134
+ - MIT
135
+ metadata:
136
+ allowed_push_host: https://rubygems.org
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubygems_version: 3.1.2
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: A Shopify Theme Linter
156
+ test_files: []