theme-check 0.1.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 (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: []