theme-check 0.5.0 → 0.6.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -3
- data/CHANGELOG.md +11 -0
- data/Gemfile +5 -3
- data/README.md +2 -0
- data/config/default.yml +8 -1
- data/data/shopify_translation_keys.yml +850 -0
- data/docs/checks/asset_size_css.md +52 -0
- data/docs/checks/img_width_and_height.md +79 -0
- data/docs/checks/parser_blocking_javascript.md +3 -3
- data/lib/theme_check/checks/asset_size_css.rb +89 -0
- data/lib/theme_check/checks/asset_size_javascript.rb +1 -7
- data/lib/theme_check/checks/img_width_and_height.rb +74 -0
- data/lib/theme_check/checks/parser_blocking_javascript.rb +5 -13
- data/lib/theme_check/checks/translation_key_exists.rb +16 -1
- data/lib/theme_check/cli.rb +19 -8
- data/lib/theme_check/config.rb +3 -0
- data/lib/theme_check/in_memory_storage.rb +11 -3
- data/lib/theme_check/language_server.rb +2 -0
- data/lib/theme_check/language_server/completion_engine.rb +1 -1
- data/lib/theme_check/language_server/completion_provider.rb +4 -0
- data/lib/theme_check/language_server/completion_providers/filter_completion_provider.rb +5 -1
- data/lib/theme_check/language_server/completion_providers/render_snippet_completion_provider.rb +43 -0
- data/lib/theme_check/language_server/constants.rb +10 -0
- data/lib/theme_check/language_server/document_link_engine.rb +47 -0
- data/lib/theme_check/language_server/handler.rb +33 -2
- data/lib/theme_check/language_server/server.rb +3 -2
- data/lib/theme_check/liquid_check.rb +11 -0
- data/lib/theme_check/remote_asset_file.rb +1 -1
- data/lib/theme_check/shopify_liquid/deprecated_filter.rb +4 -0
- data/lib/theme_check/version.rb +1 -1
- metadata +10 -2
data/lib/theme_check/config.rb
CHANGED
@@ -10,6 +10,8 @@ module ThemeCheck
|
|
10
10
|
attr_accessor :only_categories, :exclude_categories, :auto_correct
|
11
11
|
|
12
12
|
class << self
|
13
|
+
attr_reader :last_loaded_config
|
14
|
+
|
13
15
|
def from_path(path)
|
14
16
|
if (filename = find(path))
|
15
17
|
new(root: filename.dirname, configuration: load_file(filename))
|
@@ -36,6 +38,7 @@ module ThemeCheck
|
|
36
38
|
end
|
37
39
|
|
38
40
|
def load_file(absolute_path)
|
41
|
+
@last_loaded_config = absolute_path
|
39
42
|
YAML.load_file(absolute_path)
|
40
43
|
end
|
41
44
|
|
@@ -6,20 +6,28 @@
|
|
6
6
|
# as a big hash already, leave it like that and save yourself some IO.
|
7
7
|
module ThemeCheck
|
8
8
|
class InMemoryStorage < Storage
|
9
|
-
def initialize(files = {})
|
9
|
+
def initialize(files = {}, root = nil)
|
10
10
|
@files = files
|
11
|
+
@root = root
|
11
12
|
end
|
12
13
|
|
13
14
|
def path(name)
|
15
|
+
return File.join(@root, name) unless @root.nil?
|
16
|
+
name
|
17
|
+
end
|
18
|
+
|
19
|
+
def relative_path(name)
|
20
|
+
path = Pathname.new(name)
|
21
|
+
return path.relative_path_from(@root).to_s unless path.relative? || @root.nil?
|
14
22
|
name
|
15
23
|
end
|
16
24
|
|
17
25
|
def read(name)
|
18
|
-
@files[name]
|
26
|
+
@files[relative_path(name)]
|
19
27
|
end
|
20
28
|
|
21
29
|
def write(name, content)
|
22
|
-
@files[name] = content
|
30
|
+
@files[relative_path(name)] = content
|
23
31
|
end
|
24
32
|
|
25
33
|
def files
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require_relative "language_server/protocol"
|
3
|
+
require_relative "language_server/constants"
|
3
4
|
require_relative "language_server/handler"
|
4
5
|
require_relative "language_server/server"
|
5
6
|
require_relative "language_server/tokens"
|
@@ -7,6 +8,7 @@ require_relative "language_server/position_helper"
|
|
7
8
|
require_relative "language_server/completion_helper"
|
8
9
|
require_relative "language_server/completion_provider"
|
9
10
|
require_relative "language_server/completion_engine"
|
11
|
+
require_relative "language_server/document_link_engine"
|
10
12
|
|
11
13
|
Dir[__dir__ + "/language_server/completion_providers/*.rb"].each do |file|
|
12
14
|
require file
|
@@ -7,7 +7,7 @@ module ThemeCheck
|
|
7
7
|
|
8
8
|
def completions(content, cursor)
|
9
9
|
return [] unless can_complete?(content, cursor)
|
10
|
-
|
10
|
+
available_labels
|
11
11
|
.select { |w| w.starts_with?(partial(content, cursor)) }
|
12
12
|
.map { |filter| filter_to_completion(filter) }
|
13
13
|
end
|
@@ -21,6 +21,10 @@ module ThemeCheck
|
|
21
21
|
|
22
22
|
private
|
23
23
|
|
24
|
+
def available_labels
|
25
|
+
@labels ||= ShopifyLiquid::Filter.labels - ShopifyLiquid::DeprecatedFilter.labels
|
26
|
+
end
|
27
|
+
|
24
28
|
def cursor_on_filter?(content, cursor)
|
25
29
|
return false unless content.match?(NAMED_FILTER)
|
26
30
|
matches(content, NAMED_FILTER).any? do |match|
|
data/lib/theme_check/language_server/completion_providers/render_snippet_completion_provider.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ThemeCheck
|
4
|
+
module LanguageServer
|
5
|
+
class RenderSnippetCompletionProvider < CompletionProvider
|
6
|
+
def completions(content, cursor)
|
7
|
+
return [] unless cursor_on_quoted_argument?(content, cursor)
|
8
|
+
partial = snippet(content) || ''
|
9
|
+
snippets
|
10
|
+
.select { |x| x.starts_with?(partial) }
|
11
|
+
.map { |x| snippet_to_completion(x) }
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def cursor_on_quoted_argument?(content, cursor)
|
17
|
+
match = content.match(PARTIAL_RENDER)
|
18
|
+
return false if match.nil?
|
19
|
+
match.begin(:partial) <= cursor && cursor <= match.end(:partial)
|
20
|
+
end
|
21
|
+
|
22
|
+
def snippet(content)
|
23
|
+
match = content.match(PARTIAL_RENDER)
|
24
|
+
return if match.nil?
|
25
|
+
match[:partial]
|
26
|
+
end
|
27
|
+
|
28
|
+
def snippets
|
29
|
+
@storage
|
30
|
+
.files
|
31
|
+
.select { |x| x.include?('snippets/') }
|
32
|
+
end
|
33
|
+
|
34
|
+
def snippet_to_completion(file)
|
35
|
+
{
|
36
|
+
label: File.basename(file, '.liquid'),
|
37
|
+
kind: CompletionItemKinds::SNIPPET,
|
38
|
+
detail: file,
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ThemeCheck
|
4
|
+
module LanguageServer
|
5
|
+
class DocumentLinkEngine
|
6
|
+
include PositionHelper
|
7
|
+
include RegexHelpers
|
8
|
+
|
9
|
+
def initialize(storage)
|
10
|
+
@storage = storage
|
11
|
+
end
|
12
|
+
|
13
|
+
def document_links(uri)
|
14
|
+
buffer = @storage.read(uri)
|
15
|
+
matches(buffer, PARTIAL_RENDER).map do |match|
|
16
|
+
start_line, start_character = from_index_to_line_column(
|
17
|
+
buffer,
|
18
|
+
match.begin(:partial),
|
19
|
+
)
|
20
|
+
|
21
|
+
end_line, end_character = from_index_to_line_column(
|
22
|
+
buffer,
|
23
|
+
match.end(:partial)
|
24
|
+
)
|
25
|
+
|
26
|
+
{
|
27
|
+
target: link(match[:partial]),
|
28
|
+
range: {
|
29
|
+
start: {
|
30
|
+
line: start_line,
|
31
|
+
character: start_character,
|
32
|
+
},
|
33
|
+
end: {
|
34
|
+
line: end_line,
|
35
|
+
character: end_character,
|
36
|
+
},
|
37
|
+
},
|
38
|
+
}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def link(partial)
|
43
|
+
'file://' + @storage.path('snippets/' + partial + '.liquid')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -8,6 +8,7 @@ module ThemeCheck
|
|
8
8
|
triggerCharacters: ['.', '{{ ', '{% '],
|
9
9
|
context: true,
|
10
10
|
},
|
11
|
+
documentLinkProvider: true,
|
11
12
|
textDocumentSync: {
|
12
13
|
openClose: true,
|
13
14
|
change: TextDocumentSyncKind::FULL,
|
@@ -19,12 +20,13 @@ module ThemeCheck
|
|
19
20
|
def initialize(server)
|
20
21
|
@server = server
|
21
22
|
@previously_reported_files = Set.new
|
22
|
-
@storage = InMemoryStorage.new
|
23
|
-
@completion_engine = CompletionEngine.new(@storage)
|
24
23
|
end
|
25
24
|
|
26
25
|
def on_initialize(id, params)
|
27
26
|
@root_path = params["rootPath"]
|
27
|
+
@storage = in_memory_storage(@root_path)
|
28
|
+
@completion_engine = CompletionEngine.new(@storage)
|
29
|
+
@document_link_engine = DocumentLinkEngine.new(@storage)
|
28
30
|
# https://microsoft.github.io/language-server-protocol/specifications/specification-current/#responseMessage
|
29
31
|
send_response(
|
30
32
|
id: id,
|
@@ -59,6 +61,14 @@ module ThemeCheck
|
|
59
61
|
analyze_and_send_offenses(text_document_uri(params))
|
60
62
|
end
|
61
63
|
|
64
|
+
def on_text_document_document_link(id, params)
|
65
|
+
uri = text_document_uri(params)
|
66
|
+
send_response(
|
67
|
+
id: id,
|
68
|
+
result: document_links(uri)
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
62
72
|
def on_text_document_completion(id, params)
|
63
73
|
uri = text_document_uri(params)
|
64
74
|
line = params.dig('position', 'line')
|
@@ -71,6 +81,23 @@ module ThemeCheck
|
|
71
81
|
|
72
82
|
private
|
73
83
|
|
84
|
+
def in_memory_storage(root)
|
85
|
+
config = ThemeCheck::Config.from_path(root)
|
86
|
+
|
87
|
+
# Make a real FS to get the files from the snippets folder
|
88
|
+
fs = ThemeCheck::FileSystemStorage.new(
|
89
|
+
config.root,
|
90
|
+
ignored_patterns: config.ignored_patterns
|
91
|
+
)
|
92
|
+
|
93
|
+
# Turn that into a hash of empty buffers
|
94
|
+
files = fs.files
|
95
|
+
.map { |fn| [fn, ""] }
|
96
|
+
.to_h
|
97
|
+
|
98
|
+
InMemoryStorage.new(files, root)
|
99
|
+
end
|
100
|
+
|
74
101
|
def text_document_uri(params)
|
75
102
|
params.dig('textDocument', 'uri').sub('file://', '')
|
76
103
|
end
|
@@ -108,6 +135,10 @@ module ThemeCheck
|
|
108
135
|
@completion_engine.completions(uri, line, col)
|
109
136
|
end
|
110
137
|
|
138
|
+
def document_links(uri)
|
139
|
+
@document_link_engine.document_links(uri)
|
140
|
+
end
|
141
|
+
|
111
142
|
def send_diagnostics(offenses)
|
112
143
|
reported_files = Set.new
|
113
144
|
|
@@ -6,6 +6,7 @@ require 'active_support/core_ext/string/inflections'
|
|
6
6
|
module ThemeCheck
|
7
7
|
module LanguageServer
|
8
8
|
class DoneStreaming < StandardError; end
|
9
|
+
|
9
10
|
class IncompatibleStream < StandardError; end
|
10
11
|
|
11
12
|
class Server
|
@@ -15,7 +16,7 @@ module ThemeCheck
|
|
15
16
|
def initialize(
|
16
17
|
in_stream: STDIN,
|
17
18
|
out_stream: STDOUT,
|
18
|
-
err_stream:
|
19
|
+
err_stream: STDERR,
|
19
20
|
should_raise_errors: false
|
20
21
|
)
|
21
22
|
validate!([in_stream, out_stream, err_stream])
|
@@ -50,7 +51,7 @@ module ThemeCheck
|
|
50
51
|
|
51
52
|
def send_response(response)
|
52
53
|
response_body = JSON.dump(response)
|
53
|
-
log(
|
54
|
+
log(JSON.pretty_generate(response)) if $DEBUG
|
54
55
|
|
55
56
|
@out.write("Content-Length: #{response_body.size}\r\n")
|
56
57
|
@out.write("\r\n")
|
@@ -6,6 +6,17 @@ module ThemeCheck
|
|
6
6
|
extend ChecksTracking
|
7
7
|
include ParsingHelpers
|
8
8
|
|
9
|
+
TAG = /#{Liquid::TagStart}.*?#{Liquid::TagEnd}/om
|
10
|
+
VARIABLE = /#{Liquid::VariableStart}.*?#{Liquid::VariableEnd}/om
|
11
|
+
START_OR_END_QUOTE = /(^['"])|(['"]$)/
|
12
|
+
QUOTED_LIQUID_ATTRIBUTE = %r{
|
13
|
+
'(?:#{TAG}|#{VARIABLE}|[^'])*'| # any combination of tag/variable or non straight quote inside straight quotes
|
14
|
+
"(?:#{TAG}|#{VARIABLE}|[^"])*" # any combination of tag/variable or non double quotes inside double quotes
|
15
|
+
}omix
|
16
|
+
ATTR = /[a-z0-9-]+/i
|
17
|
+
HTML_ATTRIBUTE = /#{ATTR}(?:=#{QUOTED_LIQUID_ATTRIBUTE})?/omix
|
18
|
+
HTML_ATTRIBUTES = /(?:#{HTML_ATTRIBUTE}|\s)*/omix
|
19
|
+
|
9
20
|
def add_offense(message, node: nil, template: node&.template, markup: nil, line_number: nil, &block)
|
10
21
|
offenses << Offense.new(check: self, message: message, template: template, node: node, markup: markup, line_number: line_number, correction: block)
|
11
22
|
end
|
data/lib/theme_check/version.rb
CHANGED
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.
|
4
|
+
version: 0.6.0
|
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-03-
|
11
|
+
date: 2021-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: liquid
|
@@ -81,12 +81,15 @@ files:
|
|
81
81
|
- data/shopify_liquid/objects.yml
|
82
82
|
- data/shopify_liquid/plus_objects.yml
|
83
83
|
- data/shopify_liquid/tags.yml
|
84
|
+
- data/shopify_translation_keys.yml
|
84
85
|
- dev.yml
|
85
86
|
- docs/checks/CHECK_DOCS_TEMPLATE.md
|
87
|
+
- docs/checks/asset_size_css.md
|
86
88
|
- docs/checks/asset_size_javascript.md
|
87
89
|
- docs/checks/convert_include_to_render.md
|
88
90
|
- docs/checks/default_locale.md
|
89
91
|
- docs/checks/deprecated_filter.md
|
92
|
+
- docs/checks/img_width_and_height.md
|
90
93
|
- docs/checks/liquid_tag.md
|
91
94
|
- docs/checks/matching_schema_translations.md
|
92
95
|
- docs/checks/matching_translations.md
|
@@ -116,10 +119,12 @@ files:
|
|
116
119
|
- lib/theme_check/asset_file.rb
|
117
120
|
- lib/theme_check/check.rb
|
118
121
|
- lib/theme_check/checks.rb
|
122
|
+
- lib/theme_check/checks/asset_size_css.rb
|
119
123
|
- lib/theme_check/checks/asset_size_javascript.rb
|
120
124
|
- lib/theme_check/checks/convert_include_to_render.rb
|
121
125
|
- lib/theme_check/checks/default_locale.rb
|
122
126
|
- lib/theme_check/checks/deprecated_filter.rb
|
127
|
+
- lib/theme_check/checks/img_width_and_height.rb
|
123
128
|
- lib/theme_check/checks/liquid_tag.rb
|
124
129
|
- lib/theme_check/checks/matching_schema_translations.rb
|
125
130
|
- lib/theme_check/checks/matching_translations.rb
|
@@ -157,7 +162,10 @@ files:
|
|
157
162
|
- lib/theme_check/language_server/completion_provider.rb
|
158
163
|
- lib/theme_check/language_server/completion_providers/filter_completion_provider.rb
|
159
164
|
- lib/theme_check/language_server/completion_providers/object_completion_provider.rb
|
165
|
+
- lib/theme_check/language_server/completion_providers/render_snippet_completion_provider.rb
|
160
166
|
- lib/theme_check/language_server/completion_providers/tag_completion_provider.rb
|
167
|
+
- lib/theme_check/language_server/constants.rb
|
168
|
+
- lib/theme_check/language_server/document_link_engine.rb
|
161
169
|
- lib/theme_check/language_server/handler.rb
|
162
170
|
- lib/theme_check/language_server/position_helper.rb
|
163
171
|
- lib/theme_check/language_server/protocol.rb
|