theme-check 0.4.0 → 0.7.2
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/.github/workflows/theme-check.yml +10 -3
- data/.rubocop.yml +12 -3
- data/CHANGELOG.md +40 -0
- data/CONTRIBUTING.md +5 -2
- data/Gemfile +5 -3
- data/LICENSE.md +2 -0
- data/README.md +12 -2
- data/RELEASING.md +10 -3
- data/Rakefile +6 -0
- data/config/default.yml +16 -0
- data/data/shopify_liquid/tags.yml +1 -0
- data/data/shopify_translation_keys.yml +850 -0
- data/docs/checks/CHECK_DOCS_TEMPLATE.md +47 -0
- data/docs/checks/asset_size_css.md +52 -0
- data/docs/checks/asset_size_javascript.md +79 -0
- data/docs/checks/convert_include_to_render.md +48 -0
- data/docs/checks/default_locale.md +46 -0
- data/docs/checks/deprecated_filter.md +46 -0
- data/docs/checks/img_width_and_height.md +79 -0
- data/docs/checks/liquid_tag.md +65 -0
- data/docs/checks/matching_schema_translations.md +93 -0
- data/docs/checks/matching_translations.md +72 -0
- data/docs/checks/missing_enable_comment.md +50 -0
- data/docs/checks/missing_required_template_files.md +26 -0
- data/docs/checks/missing_template.md +40 -0
- data/docs/checks/nested_snippet.md +69 -0
- data/docs/checks/parser_blocking_javascript.md +97 -0
- data/docs/checks/remote_asset.md +82 -0
- data/docs/checks/required_directories.md +25 -0
- data/docs/checks/required_layout_theme_object.md +28 -0
- data/docs/checks/space_inside_braces.md +63 -0
- data/docs/checks/syntax_error.md +49 -0
- data/docs/checks/template_length.md +50 -0
- data/docs/checks/translation_key_exists.md +63 -0
- data/docs/checks/undefined_object.md +53 -0
- data/docs/checks/unknown_filter.md +45 -0
- data/docs/checks/unused_assign.md +47 -0
- data/docs/checks/unused_snippet.md +32 -0
- data/docs/checks/valid_html_translation.md +53 -0
- data/docs/checks/valid_json.md +60 -0
- data/docs/checks/valid_schema.md +50 -0
- data/lib/theme_check.rb +4 -0
- data/lib/theme_check/asset_file.rb +34 -0
- data/lib/theme_check/check.rb +20 -10
- data/lib/theme_check/checks/asset_size_css.rb +89 -0
- data/lib/theme_check/checks/asset_size_javascript.rb +68 -0
- data/lib/theme_check/checks/convert_include_to_render.rb +1 -1
- data/lib/theme_check/checks/default_locale.rb +1 -0
- data/lib/theme_check/checks/deprecated_filter.rb +1 -1
- data/lib/theme_check/checks/img_width_and_height.rb +74 -0
- data/lib/theme_check/checks/liquid_tag.rb +3 -3
- data/lib/theme_check/checks/matching_schema_translations.rb +1 -0
- data/lib/theme_check/checks/matching_translations.rb +2 -1
- data/lib/theme_check/checks/missing_enable_comment.rb +1 -0
- data/lib/theme_check/checks/missing_required_template_files.rb +1 -2
- data/lib/theme_check/checks/missing_template.rb +1 -0
- data/lib/theme_check/checks/nested_snippet.rb +1 -0
- data/lib/theme_check/checks/parser_blocking_javascript.rb +8 -15
- data/lib/theme_check/checks/remote_asset.rb +99 -0
- data/lib/theme_check/checks/required_directories.rb +1 -1
- data/lib/theme_check/checks/required_layout_theme_object.rb +1 -1
- data/lib/theme_check/checks/space_inside_braces.rb +1 -0
- data/lib/theme_check/checks/syntax_error.rb +1 -0
- data/lib/theme_check/checks/template_length.rb +1 -0
- data/lib/theme_check/checks/translation_key_exists.rb +14 -1
- data/lib/theme_check/checks/undefined_object.rb +11 -5
- data/lib/theme_check/checks/unknown_filter.rb +1 -0
- data/lib/theme_check/checks/unused_assign.rb +1 -0
- data/lib/theme_check/checks/unused_snippet.rb +1 -0
- data/lib/theme_check/checks/valid_html_translation.rb +2 -1
- data/lib/theme_check/checks/valid_json.rb +1 -0
- data/lib/theme_check/checks/valid_schema.rb +1 -0
- data/lib/theme_check/cli.rb +29 -9
- data/lib/theme_check/config.rb +5 -2
- data/lib/theme_check/disabled_checks.rb +2 -2
- data/lib/theme_check/in_memory_storage.rb +13 -8
- data/lib/theme_check/language_server.rb +2 -0
- data/lib/theme_check/language_server/completion_engine.rb +3 -3
- data/lib/theme_check/language_server/completion_helper.rb +0 -10
- data/lib/theme_check/language_server/completion_provider.rb +5 -0
- data/lib/theme_check/language_server/completion_providers/filter_completion_provider.rb +6 -2
- data/lib/theme_check/language_server/completion_providers/object_completion_provider.rb +1 -1
- data/lib/theme_check/language_server/completion_providers/render_snippet_completion_provider.rb +43 -0
- data/lib/theme_check/language_server/completion_providers/tag_completion_provider.rb +2 -2
- data/lib/theme_check/language_server/constants.rb +10 -0
- data/lib/theme_check/language_server/document_link_engine.rb +48 -0
- data/lib/theme_check/language_server/handler.rb +67 -20
- data/lib/theme_check/language_server/server.rb +9 -4
- data/lib/theme_check/liquid_check.rb +11 -0
- data/lib/theme_check/node.rb +1 -2
- data/lib/theme_check/offense.rb +3 -1
- data/lib/theme_check/packager.rb +1 -1
- data/lib/theme_check/regex_helpers.rb +15 -0
- data/lib/theme_check/releaser.rb +39 -0
- data/lib/theme_check/remote_asset_file.rb +44 -0
- data/lib/theme_check/shopify_liquid/deprecated_filter.rb +10 -8
- data/lib/theme_check/shopify_liquid/filter.rb +3 -5
- data/lib/theme_check/shopify_liquid/object.rb +2 -6
- data/lib/theme_check/shopify_liquid/tag.rb +1 -3
- data/lib/theme_check/storage.rb +3 -3
- data/lib/theme_check/string_helpers.rb +47 -0
- data/lib/theme_check/tags.rb +1 -2
- data/lib/theme_check/theme.rb +7 -1
- data/lib/theme_check/version.rb +1 -1
- data/packaging/homebrew/theme_check.base.rb +1 -1
- data/theme-check.gemspec +1 -2
- metadata +46 -18
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module ThemeCheck
|
|
3
|
+
module SystemTranslations
|
|
4
|
+
extend self
|
|
5
|
+
|
|
6
|
+
def translations
|
|
7
|
+
@translations ||= YAML.load(File.read("#{__dir__}/../../../data/shopify_translation_keys.yml")).to_set
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def include?(key)
|
|
11
|
+
translations.include?(key)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
3
15
|
class TranslationKeyExists < LiquidCheck
|
|
4
16
|
severity :error
|
|
5
17
|
category :translation
|
|
18
|
+
doc docs_url(__FILE__)
|
|
6
19
|
|
|
7
20
|
def on_variable(node)
|
|
8
21
|
return unless @theme.default_locale_json&.content&.is_a?(Hash)
|
|
@@ -11,7 +24,7 @@ module ThemeCheck
|
|
|
11
24
|
return unless (key_node = node.children.first)
|
|
12
25
|
return unless key_node.value.is_a?(String)
|
|
13
26
|
|
|
14
|
-
unless key_exists?(key_node.value)
|
|
27
|
+
unless key_exists?(key_node.value) || SystemTranslations.include?(key_node.value)
|
|
15
28
|
add_offense(
|
|
16
29
|
"'#{key_node.value}' does not have a matching entry in '#{@theme.default_locale_json.relative_path}'",
|
|
17
30
|
node: node,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
module ThemeCheck
|
|
3
3
|
class UndefinedObject < LiquidCheck
|
|
4
4
|
category :liquid
|
|
5
|
-
doc
|
|
5
|
+
doc docs_url(__FILE__)
|
|
6
6
|
severity :error
|
|
7
7
|
|
|
8
8
|
class TemplateInfo
|
|
@@ -21,7 +21,13 @@ module ThemeCheck
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def add_variable_lookup(name:, node:)
|
|
24
|
-
|
|
24
|
+
parent = node
|
|
25
|
+
line_number = nil
|
|
26
|
+
loop do
|
|
27
|
+
line_number = parent.line_number
|
|
28
|
+
parent = parent.parent
|
|
29
|
+
break unless line_number.nil? && parent
|
|
30
|
+
end
|
|
25
31
|
key = [name, line_number]
|
|
26
32
|
@all_variable_lookups[key] = node
|
|
27
33
|
end
|
|
@@ -129,7 +135,7 @@ module ThemeCheck
|
|
|
129
135
|
|
|
130
136
|
def each_template
|
|
131
137
|
@files.each do |(name, info)|
|
|
132
|
-
next if name.
|
|
138
|
+
next if name.start_with?('snippets/')
|
|
133
139
|
yield [name, info]
|
|
134
140
|
end
|
|
135
141
|
end
|
|
@@ -154,7 +160,7 @@ module ThemeCheck
|
|
|
154
160
|
all_variables = info.all_variables
|
|
155
161
|
|
|
156
162
|
info.each_variable_lookup(!!render_node) do |(key, node)|
|
|
157
|
-
name,
|
|
163
|
+
name, line_number = key
|
|
158
164
|
next if all_variables.include?(name)
|
|
159
165
|
next if all_global_objects.include?(name)
|
|
160
166
|
|
|
@@ -164,7 +170,7 @@ module ThemeCheck
|
|
|
164
170
|
if render_node
|
|
165
171
|
add_offense("Missing argument `#{name}`", node: render_node)
|
|
166
172
|
else
|
|
167
|
-
add_offense("Undefined object `#{name}`", node: node)
|
|
173
|
+
add_offense("Undefined object `#{name}`", node: node, line_number: line_number)
|
|
168
174
|
end
|
|
169
175
|
end
|
|
170
176
|
end
|
|
@@ -5,9 +5,10 @@ require 'nokogumbo'
|
|
|
5
5
|
module ThemeCheck
|
|
6
6
|
class ValidHTMLTranslation < JsonCheck
|
|
7
7
|
severity :suggestion
|
|
8
|
+
doc docs_url(__FILE__)
|
|
8
9
|
|
|
9
10
|
def on_file(file)
|
|
10
|
-
return unless file.name.
|
|
11
|
+
return unless file.name.start_with?("locales/")
|
|
11
12
|
return unless file.content.is_a?(Hash)
|
|
12
13
|
|
|
13
14
|
visit_nested(file.content)
|
data/lib/theme_check/cli.rb
CHANGED
|
@@ -6,14 +6,18 @@ module ThemeCheck
|
|
|
6
6
|
USAGE = <<~END
|
|
7
7
|
Usage: theme-check [options] /path/to/your/theme
|
|
8
8
|
|
|
9
|
-
Options:
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-a,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
Basic Options:
|
|
10
|
+
-C, --config <path> Use the config provided, overriding .theme-check.yml if present
|
|
11
|
+
-c, --category <category> Only run this category of checks
|
|
12
|
+
-x, --exclude-category <category> Exclude this category of checks
|
|
13
|
+
-a, --auto-correct Automatically fix offenses
|
|
14
|
+
|
|
15
|
+
Miscellaneous:
|
|
16
|
+
--init Generate a .theme-check.yml file
|
|
17
|
+
--print-config Output active config to STDOUT
|
|
18
|
+
-h, --help Show this. Hi!
|
|
19
|
+
-l, --list List enabled checks
|
|
20
|
+
-v, --version Print Theme Check version
|
|
17
21
|
|
|
18
22
|
Description:
|
|
19
23
|
Theme Check helps you follow Shopify Themes & Liquid best practices by analyzing the
|
|
@@ -29,6 +33,7 @@ module ThemeCheck
|
|
|
29
33
|
only_categories = []
|
|
30
34
|
exclude_categories = []
|
|
31
35
|
auto_correct = false
|
|
36
|
+
config_path = nil
|
|
32
37
|
|
|
33
38
|
args = argv.dup
|
|
34
39
|
while (arg = args.shift)
|
|
@@ -37,6 +42,8 @@ module ThemeCheck
|
|
|
37
42
|
raise Abort, USAGE
|
|
38
43
|
when "--version", "-v"
|
|
39
44
|
command = :version
|
|
45
|
+
when "--config", "-C"
|
|
46
|
+
config_path = Pathname.new(args.shift)
|
|
40
47
|
when "--category", "-c"
|
|
41
48
|
only_categories << args.shift.to_sym
|
|
42
49
|
when "--exclude-category", "-x"
|
|
@@ -47,13 +54,22 @@ module ThemeCheck
|
|
|
47
54
|
auto_correct = true
|
|
48
55
|
when "--init"
|
|
49
56
|
command = :init
|
|
57
|
+
when "--print"
|
|
58
|
+
command = :print
|
|
50
59
|
else
|
|
51
60
|
@path = arg
|
|
52
61
|
end
|
|
53
62
|
end
|
|
54
63
|
|
|
55
64
|
unless [:version, :init].include?(command)
|
|
56
|
-
@config =
|
|
65
|
+
@config = if config_path
|
|
66
|
+
ThemeCheck::Config.new(
|
|
67
|
+
root: @path,
|
|
68
|
+
configuration: ThemeCheck::Config.load_file(config_path)
|
|
69
|
+
)
|
|
70
|
+
else
|
|
71
|
+
ThemeCheck::Config.from_path(@path)
|
|
72
|
+
end
|
|
57
73
|
@config.only_categories = only_categories
|
|
58
74
|
@config.exclude_categories = exclude_categories
|
|
59
75
|
@config.auto_correct = auto_correct
|
|
@@ -91,6 +107,10 @@ module ThemeCheck
|
|
|
91
107
|
end
|
|
92
108
|
end
|
|
93
109
|
|
|
110
|
+
def print
|
|
111
|
+
puts YAML.dump(@config.to_h)
|
|
112
|
+
end
|
|
113
|
+
|
|
94
114
|
def check
|
|
95
115
|
puts "Checking #{@config.root} ..."
|
|
96
116
|
storage = ThemeCheck::FileSystemStorage.new(@config.root, ignored_patterns: @config.ignored_patterns)
|
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
|
|
|
@@ -83,8 +86,8 @@ module ThemeCheck
|
|
|
83
86
|
|
|
84
87
|
check_class = ThemeCheck.const_get(check_name)
|
|
85
88
|
|
|
86
|
-
next if exclude_categories.include?(
|
|
87
|
-
next if only_categories.any? &&
|
|
89
|
+
next if check_class.categories.any? { |category| exclude_categories.include?(category) }
|
|
90
|
+
next if only_categories.any? && check_class.categories.none? { |category| only_categories.include?(category) }
|
|
88
91
|
|
|
89
92
|
options_for_check = options.transform_keys(&:to_sym)
|
|
90
93
|
options_for_check.delete(:enabled)
|
|
@@ -61,11 +61,11 @@ module ThemeCheck
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
def start_disabling?(text)
|
|
64
|
-
text.strip.
|
|
64
|
+
text.strip.start_with?(DISABLE_START)
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def stop_disabling?(text)
|
|
68
|
-
text.strip.
|
|
68
|
+
text.strip.start_with?(DISABLE_END)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
# Return a list of checks from a theme-check-disable comment
|
|
@@ -6,24 +6,25 @@
|
|
|
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 = "/dev/null")
|
|
10
10
|
@files = files
|
|
11
|
+
@root = Pathname.new(root)
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
def path(
|
|
14
|
-
|
|
14
|
+
def path(relative_path)
|
|
15
|
+
@root.join(relative_path)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
|
-
def read(
|
|
18
|
-
@files[
|
|
18
|
+
def read(relative_path)
|
|
19
|
+
@files[relative_path]
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def write(
|
|
22
|
-
@files[
|
|
22
|
+
def write(relative_path, content)
|
|
23
|
+
@files[relative_path] = content
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
def files
|
|
26
|
-
@
|
|
27
|
+
@files.keys
|
|
27
28
|
end
|
|
28
29
|
|
|
29
30
|
def directories
|
|
@@ -33,5 +34,9 @@ module ThemeCheck
|
|
|
33
34
|
.map(&:to_s)
|
|
34
35
|
.uniq
|
|
35
36
|
end
|
|
37
|
+
|
|
38
|
+
def relative_path(absolute_path)
|
|
39
|
+
Pathname.new(absolute_path).relative_path_from(@root).to_s
|
|
40
|
+
end
|
|
36
41
|
end
|
|
37
42
|
end
|
|
@@ -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,11 +7,11 @@ module ThemeCheck
|
|
|
7
7
|
|
|
8
8
|
def initialize(storage)
|
|
9
9
|
@storage = storage
|
|
10
|
-
@providers = CompletionProvider.all.map(
|
|
10
|
+
@providers = CompletionProvider.all.map { |x| x.new(storage) }
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def completions(
|
|
14
|
-
buffer = @storage.read(
|
|
13
|
+
def completions(relative_path, line, col)
|
|
14
|
+
buffer = @storage.read(relative_path)
|
|
15
15
|
cursor = from_line_column_to_index(buffer, line, col)
|
|
16
16
|
token = find_token(buffer, cursor)
|
|
17
17
|
return [] if token.nil?
|
|
@@ -20,16 +20,6 @@ module ThemeCheck
|
|
|
20
20
|
def first_word(content)
|
|
21
21
|
return content.match(WORD)[0] if content.match?(WORD)
|
|
22
22
|
end
|
|
23
|
-
|
|
24
|
-
def matches(s, re)
|
|
25
|
-
start_at = 0
|
|
26
|
-
matches = []
|
|
27
|
-
while (m = s.match(re, start_at))
|
|
28
|
-
matches.push(m)
|
|
29
|
-
start_at = m.end(0)
|
|
30
|
-
end
|
|
31
|
-
matches
|
|
32
|
-
end
|
|
33
23
|
end
|
|
34
24
|
end
|
|
35
25
|
end
|
|
@@ -4,6 +4,7 @@ module ThemeCheck
|
|
|
4
4
|
module LanguageServer
|
|
5
5
|
class CompletionProvider
|
|
6
6
|
include CompletionHelper
|
|
7
|
+
include RegexHelpers
|
|
7
8
|
|
|
8
9
|
class << self
|
|
9
10
|
def all
|
|
@@ -15,6 +16,10 @@ module ThemeCheck
|
|
|
15
16
|
end
|
|
16
17
|
end
|
|
17
18
|
|
|
19
|
+
def initialize(storage = InMemoryStorage.new)
|
|
20
|
+
@storage = storage
|
|
21
|
+
end
|
|
22
|
+
|
|
18
23
|
def completions(content, cursor)
|
|
19
24
|
raise NotImplementedError
|
|
20
25
|
end
|
|
@@ -7,8 +7,8 @@ module ThemeCheck
|
|
|
7
7
|
|
|
8
8
|
def completions(content, cursor)
|
|
9
9
|
return [] unless can_complete?(content, cursor)
|
|
10
|
-
|
|
11
|
-
.select { |w| w.
|
|
10
|
+
available_labels
|
|
11
|
+
.select { |w| w.start_with?(partial(content, cursor)) }
|
|
12
12
|
.map { |filter| filter_to_completion(filter) }
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -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|
|
|
@@ -7,7 +7,7 @@ module ThemeCheck
|
|
|
7
7
|
return [] unless can_complete?(content, cursor)
|
|
8
8
|
partial = first_word(content) || ''
|
|
9
9
|
ShopifyLiquid::Object.labels
|
|
10
|
-
.select { |w| w.
|
|
10
|
+
.select { |w| w.start_with?(partial) }
|
|
11
11
|
.map { |object| object_to_completion(object) }
|
|
12
12
|
end
|
|
13
13
|
|
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.start_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
|