theme-check 1.8.0 → 1.9.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/.gitignore +1 -0
- data/CHANGELOG.md +21 -0
- data/README.md +10 -0
- data/RELEASING.md +13 -0
- data/config/default.yml +5 -0
- data/data/shopify_liquid/deprecated_filters.yml +4 -0
- data/data/shopify_liquid/filters.yml +2 -1
- data/docs/checks/schema_json_format.md +76 -0
- data/docs/language_server/code-action-command-palette.png +0 -0
- data/docs/language_server/code-action-flow.png +0 -0
- data/docs/language_server/code-action-keyboard.png +0 -0
- data/docs/language_server/code-action-light-bulb.png +0 -0
- data/docs/language_server/code-action-problem.png +0 -0
- data/docs/language_server/code-action-quickfix.png +0 -0
- data/docs/language_server/how_to_correct_code_with_code_actions_and_execute_command.md +197 -0
- data/lib/theme_check/checks/asset_size_app_block_css.rb +2 -3
- data/lib/theme_check/checks/asset_size_app_block_javascript.rb +2 -3
- data/lib/theme_check/checks/asset_url_filters.rb +2 -0
- data/lib/theme_check/checks/default_locale.rb +1 -1
- data/lib/theme_check/checks/deprecated_filter.rb +79 -4
- data/lib/theme_check/checks/deprecated_global_app_block_type.rb +2 -3
- data/lib/theme_check/checks/matching_schema_translations.rb +4 -6
- data/lib/theme_check/checks/matching_translations.rb +1 -0
- data/lib/theme_check/checks/missing_required_template_files.rb +3 -3
- data/lib/theme_check/checks/missing_template.rb +1 -1
- data/lib/theme_check/checks/pagination_size.rb +2 -3
- data/lib/theme_check/checks/remote_asset.rb +5 -0
- data/lib/theme_check/checks/required_directories.rb +1 -1
- data/lib/theme_check/checks/schema_json_format.rb +29 -0
- data/lib/theme_check/checks/space_inside_braces.rb +132 -87
- data/lib/theme_check/checks/translation_key_exists.rb +33 -13
- data/lib/theme_check/checks/unused_snippet.rb +1 -1
- data/lib/theme_check/checks/valid_html_translation.rb +1 -1
- data/lib/theme_check/checks/valid_schema.rb +2 -2
- data/lib/theme_check/corrector.rb +28 -54
- data/lib/theme_check/file_system_storage.rb +4 -3
- data/lib/theme_check/html_node.rb +99 -6
- data/lib/theme_check/html_visitor.rb +1 -32
- data/lib/theme_check/in_memory_storage.rb +9 -0
- data/lib/theme_check/json_helpers.rb +14 -0
- data/lib/theme_check/language_server/bridge.rb +1 -1
- data/lib/theme_check/language_server/client_capabilities.rb +27 -0
- data/lib/theme_check/language_server/code_action_engine.rb +32 -0
- data/lib/theme_check/language_server/code_action_provider.rb +42 -0
- data/lib/theme_check/language_server/code_action_providers/quickfix_code_action_provider.rb +83 -0
- data/lib/theme_check/language_server/code_action_providers/source_fix_all_code_action_provider.rb +40 -0
- data/lib/theme_check/language_server/configuration.rb +69 -0
- data/lib/theme_check/language_server/diagnostic.rb +124 -0
- data/lib/theme_check/language_server/diagnostics_engine.rb +15 -60
- data/lib/theme_check/language_server/diagnostics_manager.rb +136 -0
- data/lib/theme_check/language_server/document_change_corrector.rb +267 -0
- data/lib/theme_check/language_server/document_link_provider.rb +6 -6
- data/lib/theme_check/language_server/execute_command_engine.rb +19 -0
- data/lib/theme_check/language_server/execute_command_provider.rb +30 -0
- data/lib/theme_check/language_server/execute_command_providers/correction_execute_command_provider.rb +48 -0
- data/lib/theme_check/language_server/execute_command_providers/run_checks_execute_command_provider.rb +22 -0
- data/lib/theme_check/language_server/handler.rb +79 -28
- data/lib/theme_check/language_server/io_messenger.rb +9 -1
- data/lib/theme_check/language_server/server.rb +8 -7
- data/lib/theme_check/language_server/uri_helper.rb +1 -0
- data/lib/theme_check/language_server/versioned_in_memory_storage.rb +69 -0
- data/lib/theme_check/language_server.rb +23 -5
- data/lib/theme_check/liquid_node.rb +249 -39
- data/lib/theme_check/locale_diff.rb +16 -4
- data/lib/theme_check/node.rb +16 -0
- data/lib/theme_check/offense.rb +27 -23
- data/lib/theme_check/regex_helpers.rb +1 -1
- data/lib/theme_check/schema_helper.rb +70 -0
- data/lib/theme_check/storage.rb +4 -0
- data/lib/theme_check/theme.rb +1 -1
- data/lib/theme_check/theme_file.rb +8 -1
- data/lib/theme_check/theme_file_rewriter.rb +18 -9
- data/lib/theme_check/version.rb +1 -1
- data/lib/theme_check.rb +7 -2
- metadata +26 -3
- data/lib/theme_check/language_server/diagnostics_tracker.rb +0 -66
@@ -22,6 +22,7 @@ module ThemeCheck
|
|
22
22
|
return if resource_url =~ ABSOLUTE_PATH
|
23
23
|
return if resource_url =~ RELATIVE_PATH
|
24
24
|
return if url_hosted_by_shopify?(resource_url)
|
25
|
+
return if url_is_setting_variable?(resource_url)
|
25
26
|
|
26
27
|
# Ignore non-stylesheet link tags
|
27
28
|
rel = node.attributes["rel"]
|
@@ -39,5 +40,9 @@ module ThemeCheck
|
|
39
40
|
url.start_with?(Liquid::VariableStart) &&
|
40
41
|
AssetUrlFilters::ASSET_URL_FILTERS.any? { |filter| url.include?(filter) }
|
41
42
|
end
|
43
|
+
|
44
|
+
def url_is_setting_variable?(url)
|
45
|
+
url.start_with?(Liquid::VariableStart) && url =~ /settings\./
|
46
|
+
end
|
42
47
|
end
|
43
48
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ThemeCheck
|
3
|
+
class SchemaJsonFormat < LiquidCheck
|
4
|
+
severity :style
|
5
|
+
category :liquid
|
6
|
+
doc docs_url(__FILE__)
|
7
|
+
|
8
|
+
def initialize(start_level: 0, indent: ' ')
|
9
|
+
@pretty_json_opts = {
|
10
|
+
indent: indent,
|
11
|
+
start_level: start_level,
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def on_schema(node)
|
16
|
+
schema = node.inner_json
|
17
|
+
return if schema.nil?
|
18
|
+
pretty_schema = pretty_json(schema, **@pretty_json_opts)
|
19
|
+
if pretty_schema != node.inner_markup
|
20
|
+
add_offense(
|
21
|
+
"JSON formatting could be improved",
|
22
|
+
node: node,
|
23
|
+
) do |corrector|
|
24
|
+
corrector.replace_inner_json(node, schema, **@pretty_json_opts)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -6,115 +6,160 @@ module ThemeCheck
|
|
6
6
|
category :liquid
|
7
7
|
doc docs_url(__FILE__)
|
8
8
|
|
9
|
-
def initialize
|
10
|
-
@ignore = false
|
11
|
-
end
|
12
|
-
|
13
9
|
def on_node(node)
|
14
10
|
return unless node.markup
|
15
|
-
return if
|
11
|
+
return if node.literal?
|
12
|
+
return if node.assigned_or_echoed_variable?
|
16
13
|
|
17
14
|
outside_of_strings(node.markup) do |chunk, chunk_start|
|
18
|
-
chunk.scan(/([,:|]|==|<>|<=|>=|<|>|!=)( +)/) do |_match|
|
19
|
-
|
20
|
-
"Too many spaces after '#{Regexp.last_match(1)}'",
|
21
|
-
node: node,
|
22
|
-
markup: Regexp.last_match(2),
|
23
|
-
node_markup_offset: chunk_start + Regexp.last_match.begin(2)
|
24
|
-
)
|
15
|
+
chunk.scan(/(?<token>[,:|]|==|<>|<=|>=|<|>|!=)(?<offense> +)/) do |_match|
|
16
|
+
add_too_many_spaces_after_offense(Regexp.last_match, node, chunk_start)
|
25
17
|
end
|
26
|
-
chunk.scan(/([,:|]|==|<>|<=|>=|<\b|>\b|!=)(\S|\z)/) do |_match|
|
27
|
-
|
28
|
-
"Space missing after '#{Regexp.last_match(1)}'",
|
29
|
-
node: node,
|
30
|
-
markup: Regexp.last_match(1),
|
31
|
-
node_markup_offset: chunk_start + Regexp.last_match.begin(0),
|
32
|
-
)
|
18
|
+
chunk.scan(/(?<offense>(?<token>[,:|]|==|<>|<=|>=|<\b|>\b|!=)(\S|\z))/) do |_match|
|
19
|
+
add_space_missing_after_offense(Regexp.last_match, node, chunk_start)
|
33
20
|
end
|
34
|
-
chunk.scan(/(
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
markup: Regexp.last_match(1),
|
39
|
-
node_markup_offset: chunk_start + Regexp.last_match.begin(1)
|
40
|
-
)
|
21
|
+
chunk.scan(/(?<offense>\s{2,})(?<token>\||==|<>|<=|>=|<|>|!=)+/) do |_match|
|
22
|
+
unless Regexp.last_match(:offense).include?("\n")
|
23
|
+
add_too_many_spaces_before_offense(Regexp.last_match, node, chunk_start)
|
24
|
+
end
|
41
25
|
end
|
42
|
-
chunk.scan(/(\A|\S)(?<
|
43
|
-
|
44
|
-
"Space missing before '#{Regexp.last_match(1)}'",
|
45
|
-
node: node,
|
46
|
-
markup: Regexp.last_match(:match),
|
47
|
-
node_markup_offset: chunk_start + Regexp.last_match.begin(:match)
|
48
|
-
)
|
26
|
+
chunk.scan(/(\A|\S)(?<offense>(?<token>\||==|<>|<=|>=|<|\b>|!=))/) do |_match|
|
27
|
+
add_space_missing_before_offense(Regexp.last_match, node, chunk_start)
|
49
28
|
end
|
50
29
|
end
|
51
30
|
end
|
52
31
|
|
32
|
+
BlockMarkup = Struct.new(:markup, :node_markup_offset)
|
33
|
+
|
53
34
|
def on_tag(node)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
35
|
+
return if node.inside_liquid_tag?
|
36
|
+
|
37
|
+
# Both the start and end tags
|
38
|
+
blocks = [
|
39
|
+
BlockMarkup.new(node.block_start_markup, node.block_start_start_index - node.start_index),
|
40
|
+
BlockMarkup.new(node.block_end_markup, node.block_end_start_index - node.start_index),
|
41
|
+
]
|
42
|
+
|
43
|
+
blocks.each do |block|
|
44
|
+
# Looking at spaces after the start token
|
45
|
+
if block.markup =~ /^(?<token>{%-?)(?<offense>[^ \n\t-])/
|
46
|
+
add_space_missing_after_offense(Regexp.last_match, node, block.node_markup_offset)
|
47
|
+
end
|
48
|
+
|
49
|
+
if block.markup =~ /^(?<token>{%-?)(?<offense> {2,})\S/
|
50
|
+
add_too_many_spaces_after_offense(Regexp.last_match, node, block.node_markup_offset)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Looking at spaces before the end token
|
54
|
+
if block.markup =~ /(?<offense>[^ \n\t-])(?<token>-?%})$/
|
55
|
+
add_space_missing_before_offense(Regexp.last_match, node, block.node_markup_offset)
|
69
56
|
end
|
57
|
+
|
58
|
+
if block.markup =~ /\S(?<offense> {2,})(?<token>-?%})$/
|
59
|
+
add_too_many_spaces_before_offense(Regexp.last_match, node, block.node_markup_offset)
|
60
|
+
end
|
61
|
+
|
62
|
+
next
|
70
63
|
end
|
71
|
-
@ignore = true
|
72
64
|
end
|
73
65
|
|
74
|
-
def
|
75
|
-
|
66
|
+
def on_variable(node)
|
67
|
+
return if node.markup.empty?
|
68
|
+
return if node.assigned_or_echoed_variable?
|
69
|
+
|
70
|
+
block_start_offset = node.block_start_start_index - node.start_index
|
71
|
+
|
72
|
+
# Looking at spaces after the start token
|
73
|
+
if node.block_start_markup =~ /^(?<token>{{-?)(?<offense>[^ \n\t-])/
|
74
|
+
add_space_missing_after_offense(Regexp.last_match, node, block_start_offset)
|
75
|
+
end
|
76
|
+
|
77
|
+
if node.block_start_markup =~ /^(?<token>{{-?)(?<offense> {2,})\S/
|
78
|
+
add_too_many_spaces_after_offense(Regexp.last_match, node, block_start_offset)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Looking at spaces before the end token
|
82
|
+
if node.block_start_markup =~ /(?<offense>[^ \n\t-])(?<token>-?}})$/
|
83
|
+
add_space_missing_before_offense(Regexp.last_match, node, block_start_offset)
|
84
|
+
end
|
85
|
+
|
86
|
+
if node.block_start_markup =~ /\S(?<offense> {2,})(?<token>-?}})$/
|
87
|
+
add_too_many_spaces_before_offense(Regexp.last_match, node, block_start_offset)
|
88
|
+
end
|
76
89
|
end
|
77
90
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
91
|
+
def add_space_missing_after_offense(match, node, source_offset)
|
92
|
+
add_offense_for_match(
|
93
|
+
"Space missing after '#{match[:token]}'",
|
94
|
+
match,
|
95
|
+
node,
|
96
|
+
source_offset
|
97
|
+
) do |corrector|
|
98
|
+
corrector.insert_after(
|
99
|
+
node,
|
100
|
+
' ',
|
101
|
+
(node.start_index + source_offset + match.begin(:token))...
|
102
|
+
(node.start_index + source_offset + match.end(:token))
|
103
|
+
)
|
88
104
|
end
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_too_many_spaces_after_offense(match, node, source_offset)
|
108
|
+
add_offense_for_match(
|
109
|
+
"Too many spaces after '#{match[:token]}'",
|
110
|
+
match,
|
111
|
+
node,
|
112
|
+
source_offset
|
113
|
+
) do |corrector|
|
114
|
+
corrector.replace(
|
115
|
+
node,
|
116
|
+
' ',
|
117
|
+
(node.start_index + source_offset + match.begin(:offense))...
|
118
|
+
(node.start_index + source_offset + match.end(:offense))
|
119
|
+
)
|
98
120
|
end
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
121
|
+
end
|
122
|
+
|
123
|
+
def add_space_missing_before_offense(match, node, source_offset)
|
124
|
+
add_offense_for_match(
|
125
|
+
"Space missing before '#{match[:token]}'",
|
126
|
+
match,
|
127
|
+
node,
|
128
|
+
source_offset
|
129
|
+
) do |corrector|
|
130
|
+
corrector.insert_before(
|
131
|
+
node,
|
132
|
+
' ',
|
133
|
+
(node.start_index + source_offset + match.begin(:token))...
|
134
|
+
(node.start_index + source_offset + match.end(:token))
|
135
|
+
)
|
107
136
|
end
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
137
|
+
end
|
138
|
+
|
139
|
+
def add_too_many_spaces_before_offense(match, node, source_offset)
|
140
|
+
add_offense_for_match(
|
141
|
+
"Too many spaces before '#{match[:token]}'",
|
142
|
+
match,
|
143
|
+
node,
|
144
|
+
source_offset
|
145
|
+
) do |corrector|
|
146
|
+
corrector.replace(
|
147
|
+
node,
|
148
|
+
' ',
|
149
|
+
(node.start_index + source_offset + match.begin(:offense))...
|
150
|
+
(node.start_index + source_offset + match.end(:offense))
|
151
|
+
)
|
117
152
|
end
|
118
153
|
end
|
154
|
+
|
155
|
+
def add_offense_for_match(message, match, node, source_offset, &block)
|
156
|
+
add_offense(
|
157
|
+
message,
|
158
|
+
node: node,
|
159
|
+
markup: match[:offense],
|
160
|
+
node_markup_offset: source_offset + match.begin(:offense),
|
161
|
+
&block
|
162
|
+
)
|
163
|
+
end
|
119
164
|
end
|
120
165
|
end
|
@@ -5,28 +5,48 @@ module ThemeCheck
|
|
5
5
|
category :translation
|
6
6
|
doc docs_url(__FILE__)
|
7
7
|
|
8
|
+
def initialize
|
9
|
+
@schema_locales = {}
|
10
|
+
@nodes = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def on_document(node)
|
14
|
+
@nodes[node.theme_file.name] = []
|
15
|
+
end
|
16
|
+
|
8
17
|
def on_variable(node)
|
9
18
|
return unless @theme.default_locale_json&.content&.is_a?(Hash)
|
10
|
-
|
11
19
|
return unless node.value.filters.any? { |name, _| name == "t" || name == "translate" }
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
|
21
|
+
@nodes[node.theme_file.name] << node
|
22
|
+
end
|
23
|
+
|
24
|
+
def on_schema(node)
|
25
|
+
if (schema_locales = node.inner_json&.dig("locales", @theme.default_locale))
|
26
|
+
@schema_locales = schema_locales
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_end
|
31
|
+
@nodes.each_pair do |_file_name, file_nodes|
|
32
|
+
file_nodes.each do |node|
|
33
|
+
next unless (key_node = node.children.first)
|
34
|
+
next unless key_node.value.is_a?(String)
|
35
|
+
next if key_exists?(key_node.value, @theme.default_locale_json.content) || key_exists?(key_node.value, @schema_locales) || ShopifyLiquid::SystemTranslations.include?(key_node.value)
|
36
|
+
add_offense(
|
37
|
+
@schema_locales.empty? ? "'#{key_node.value}' does not have a matching entry in '#{@theme.default_locale_json.relative_path}'" : "'#{key_node.value}' does not have a matching entry in '#{@theme.default_locale_json.relative_path}' or '#{node.theme_file.relative_path}'",
|
38
|
+
node: node,
|
39
|
+
markup: key_node.value
|
40
|
+
) do |corrector|
|
41
|
+
corrector.add_translation(@theme.default_locale_json, key_node.value.split("."), "TODO")
|
42
|
+
end
|
22
43
|
end
|
23
44
|
end
|
24
45
|
end
|
25
46
|
|
26
47
|
private
|
27
48
|
|
28
|
-
def key_exists?(key)
|
29
|
-
pointer = @theme.default_locale_json.content
|
49
|
+
def key_exists?(key, pointer)
|
30
50
|
key.split(".").each do |token|
|
31
51
|
return false unless pointer.key?(token)
|
32
52
|
pointer = pointer[token]
|
@@ -25,7 +25,7 @@ module ThemeCheck
|
|
25
25
|
def on_end
|
26
26
|
missing_snippets.each do |theme_file|
|
27
27
|
add_offense("This snippet is not used", theme_file: theme_file) do |corrector|
|
28
|
-
corrector.remove_file(@theme, theme_file.relative_path.to_s)
|
28
|
+
corrector.remove_file(@theme.storage, theme_file.relative_path.to_s)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -19,7 +19,7 @@ module ThemeCheck
|
|
19
19
|
|
20
20
|
def html_key?(keys)
|
21
21
|
pluralized_key = keys[-2] if keys.length > 1
|
22
|
-
keys[-1].end_with?('_html') || pluralized_key
|
22
|
+
keys[-1].end_with?('_html') || pluralized_key&.end_with?('_html')
|
23
23
|
end
|
24
24
|
|
25
25
|
def parse_and_add_offense(key, value)
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module ThemeCheck
|
3
3
|
class ValidSchema < LiquidCheck
|
4
|
-
severity :
|
4
|
+
severity :error
|
5
5
|
category :json
|
6
6
|
doc docs_url(__FILE__)
|
7
7
|
|
8
8
|
def on_schema(node)
|
9
|
-
JSON.parse(node.
|
9
|
+
JSON.parse(node.inner_markup)
|
10
10
|
rescue JSON::ParserError => e
|
11
11
|
add_offense(format_json_parse_error(e), node: node)
|
12
12
|
end
|
@@ -2,89 +2,63 @@
|
|
2
2
|
|
3
3
|
module ThemeCheck
|
4
4
|
class Corrector
|
5
|
+
include JsonHelpers
|
6
|
+
|
5
7
|
def initialize(theme_file:)
|
6
8
|
@theme_file = theme_file
|
7
9
|
end
|
8
10
|
|
9
|
-
def insert_after(node, content)
|
10
|
-
@theme_file.rewriter.insert_after(node, content)
|
11
|
+
def insert_after(node, content, character_range = nil)
|
12
|
+
@theme_file.rewriter.insert_after(node, content, character_range)
|
11
13
|
end
|
12
14
|
|
13
|
-
def insert_before(node, content)
|
14
|
-
@theme_file.rewriter.insert_before(node, content)
|
15
|
+
def insert_before(node, content, character_range = nil)
|
16
|
+
@theme_file.rewriter.insert_before(node, content, character_range)
|
15
17
|
end
|
16
18
|
|
17
19
|
def remove(node)
|
18
20
|
@theme_file.rewriter.remove(node)
|
19
21
|
end
|
20
22
|
|
21
|
-
def replace(node, content)
|
22
|
-
@theme_file.rewriter.replace(node, content)
|
23
|
+
def replace(node, content, character_range = nil)
|
24
|
+
@theme_file.rewriter.replace(node, content, character_range)
|
23
25
|
node.markup = content
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
27
|
-
|
28
|
-
@theme_file.rewriter.replace_body(node, content)
|
29
|
-
end
|
30
|
-
|
31
|
-
def wrap(node, insert_before, insert_after)
|
32
|
-
@theme_file.rewriter.wrap(node, insert_before, insert_after)
|
33
|
-
end
|
34
|
-
|
35
|
-
def create(theme, relative_path, content)
|
36
|
-
theme.storage.write(relative_path, content)
|
28
|
+
def replace_inner_markup(node, content)
|
29
|
+
@theme_file.rewriter.replace_inner_markup(node, content)
|
37
30
|
end
|
38
31
|
|
39
|
-
def
|
40
|
-
|
41
|
-
theme.default_locale_json = JsonFile.new("locales/#{theme.default_locale}.default.json", theme.storage)
|
32
|
+
def replace_inner_json(node, json, **pretty_json_opts)
|
33
|
+
replace_inner_markup(node, pretty_json(json, **pretty_json_opts))
|
42
34
|
end
|
43
35
|
|
44
|
-
def
|
45
|
-
|
36
|
+
def wrap(node, insert_before, insert_after)
|
37
|
+
@theme_file.rewriter.wrap(node, insert_before, insert_after)
|
46
38
|
end
|
47
39
|
|
48
|
-
def
|
49
|
-
|
40
|
+
def create_file(storage, relative_path, content)
|
41
|
+
storage.write(relative_path, content)
|
50
42
|
end
|
51
43
|
|
52
|
-
def
|
53
|
-
|
54
|
-
add_key(hash, key, value)
|
55
|
-
file.update_contents(hash)
|
44
|
+
def remove_file(storage, relative_path)
|
45
|
+
storage.remove(relative_path)
|
56
46
|
end
|
57
47
|
|
58
|
-
def
|
59
|
-
|
60
|
-
return pointer.delete(token) if token == key.last
|
61
|
-
pointer[token]
|
62
|
-
end
|
48
|
+
def mkdir(storage, relative_path)
|
49
|
+
storage.mkdir(relative_path)
|
63
50
|
end
|
64
51
|
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
pointer[token]
|
70
|
-
end
|
52
|
+
def add_translation(json_file, path, value)
|
53
|
+
hash = json_file.content
|
54
|
+
SchemaHelper.set(hash, path, value)
|
55
|
+
json_file.update_contents(hash)
|
71
56
|
end
|
72
57
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
when Array
|
78
|
-
pointer.each do |item|
|
79
|
-
schema_corrector(item, key.drop(1), value)
|
80
|
-
end
|
81
|
-
|
82
|
-
when Hash
|
83
|
-
return pointer[token] = value if token == key.last
|
84
|
-
pointer[token] = {} unless pointer.key?(token) || pointer.key?("id")
|
85
|
-
pointer[token].nil? && pointer["id"] == token ? pointer : pointer[token]
|
86
|
-
end
|
87
|
-
end
|
58
|
+
def remove_translation(json_file, path)
|
59
|
+
hash = json_file.content
|
60
|
+
SchemaHelper.delete(hash, path)
|
61
|
+
json_file.update_contents(hash)
|
88
62
|
end
|
89
63
|
end
|
90
64
|
end
|
@@ -36,13 +36,14 @@ module ThemeCheck
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def mkdir(relative_path)
|
39
|
-
|
40
|
-
|
41
|
-
file(relative_path).mkpath
|
39
|
+
return if file_exists?(relative_path)
|
40
|
+
reset_memoizers
|
41
|
+
file(relative_path).mkpath
|
42
42
|
end
|
43
43
|
|
44
44
|
def files
|
45
45
|
@file_array ||= glob("**/*")
|
46
|
+
.reject { |path| File.directory?(path) }
|
46
47
|
.map { |path| path.relative_path_from(@root).to_s }
|
47
48
|
end
|
48
49
|
|