platformos-check 0.4.9 → 0.4.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +18 -18
- data/config/default.yml +9 -0
- data/data/platformos_liquid/documentation/filters.json +1 -1
- data/data/platformos_liquid/documentation/latest.json +1 -1
- data/data/platformos_liquid/documentation/tags.json +1 -1
- data/docs/checks/translation_files_match.md +70 -0
- data/docs/checks/translation_key_exists.md +44 -0
- data/docs/platformos-check.jpg +0 -0
- data/lib/platformos_check/app.rb +13 -0
- data/lib/platformos_check/app_file.rb +22 -3
- data/lib/platformos_check/checks/missing_template.rb +19 -26
- data/lib/platformos_check/checks/translation_files_match.rb +83 -0
- data/lib/platformos_check/checks/translation_key_exists.rb +48 -0
- data/lib/platformos_check/checks/undefined_object.rb +1 -1
- data/lib/platformos_check/ext/hash.rb +19 -0
- data/lib/platformos_check/graphql_file.rb +10 -6
- data/lib/platformos_check/language_server/constants.rb +18 -2
- data/lib/platformos_check/language_server/document_link_provider.rb +67 -10
- data/lib/platformos_check/language_server/document_link_providers/localize_document_link_provider.rb +38 -0
- data/lib/platformos_check/language_server/document_link_providers/theme_render_document_link_provider.rb +2 -1
- data/lib/platformos_check/language_server/document_link_providers/translation_document_link_provider.rb +36 -0
- data/lib/platformos_check/translation_file.rb +40 -0
- data/lib/platformos_check/version.rb +1 -1
- data/lib/platformos_check/yaml_file.rb +7 -2
- data/lib/platformos_check.rb +1 -0
- metadata +11 -4
- data/docs/preview.png +0 -0
@@ -34,7 +34,6 @@ module PlatformosCheck
|
|
34
34
|
severity :suggestion
|
35
35
|
category :liquid
|
36
36
|
doc docs_url(__FILE__)
|
37
|
-
single_file false
|
38
37
|
|
39
38
|
def initialize(ignore_missing: [])
|
40
39
|
@ignore_missing = ignore_missing
|
@@ -44,30 +43,37 @@ module PlatformosCheck
|
|
44
43
|
partial = node.value.template_name_expr
|
45
44
|
return unless partial.is_a?(String)
|
46
45
|
|
47
|
-
|
46
|
+
add_missing_template_offense(partial, file_type: PartialFile, node:)
|
48
47
|
end
|
49
48
|
|
50
49
|
def on_render(node)
|
51
50
|
partial = node.value.template_name_expr
|
52
51
|
return unless partial.is_a?(String)
|
53
52
|
|
54
|
-
|
53
|
+
add_missing_template_offense(partial, file_type: PartialFile, node:)
|
54
|
+
end
|
55
|
+
|
56
|
+
def on_background(node)
|
57
|
+
partial = node.value.partial_name
|
58
|
+
return unless partial.is_a?(String)
|
59
|
+
|
60
|
+
add_missing_template_offense(partial, file_type: PartialFile, node:)
|
55
61
|
end
|
56
62
|
|
57
63
|
def on_function(node)
|
58
64
|
partial = node.value.from
|
59
65
|
return unless partial.is_a?(String)
|
60
66
|
|
61
|
-
|
67
|
+
add_missing_template_offense(partial, file_type: PartialFile, node:)
|
62
68
|
end
|
63
69
|
|
64
70
|
def on_graphql(node)
|
65
71
|
return if node.value.inline_query
|
66
72
|
|
67
|
-
|
68
|
-
return unless
|
73
|
+
path = node.value.partial_name
|
74
|
+
return unless path.is_a?(String)
|
69
75
|
|
70
|
-
|
76
|
+
add_missing_template_offense(path, file_type: GraphqlFile, node:)
|
71
77
|
end
|
72
78
|
|
73
79
|
private
|
@@ -80,28 +86,15 @@ module PlatformosCheck
|
|
80
86
|
@all_ignored_patterns ||= @ignore_missing + ignored_patterns
|
81
87
|
end
|
82
88
|
|
83
|
-
def
|
84
|
-
return if ignore?(path)
|
89
|
+
def add_missing_template_offense(path, file_type:, node:)
|
90
|
+
return if ignore?(path)
|
85
91
|
|
86
|
-
|
87
|
-
# corrector.create_file(@platformos_app.storage, MissingFileCorrection.new(path:, directory: 'views/partials', extension: '.liquid').full_relative_path, "")
|
88
|
-
# end
|
89
|
-
end
|
90
|
-
|
91
|
-
def add_missing_function_offense(path, node:)
|
92
|
-
return if ignore?(path) || platformos_app.grouped_files[PartialFile][path]
|
93
|
-
|
94
|
-
add_offense("'#{path}' is not found", node:) # do |corrector|
|
95
|
-
# corrector.create_file(@platformos_app.storage, MissingFileCorrection.new(path:, directory: 'lib', extension: '.liquid').full_relative_path, "")
|
96
|
-
# end
|
97
|
-
end
|
92
|
+
file = platformos_app.grouped_files[file_type][path]
|
98
93
|
|
99
|
-
|
100
|
-
return
|
94
|
+
return add_offense("'#{path}' is missing", node:) if file.nil?
|
95
|
+
return add_offense("'#{path}' is blank", node:) if file.source.strip == ''
|
101
96
|
|
102
|
-
|
103
|
-
# corrector.create_file(@platformos_app.storage, MissingFileCorrection.new(path:, directory: 'graphql', extension: '.graphql').full_relative_path, "")
|
104
|
-
# end
|
97
|
+
nil
|
105
98
|
end
|
106
99
|
end
|
107
100
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
class TranslationFilesMatch < YamlCheck
|
5
|
+
severity :error
|
6
|
+
category :translation
|
7
|
+
doc docs_url(__FILE__)
|
8
|
+
|
9
|
+
PLURALIZATION_KEYS = Set.new(%w[zero one two few many other])
|
10
|
+
|
11
|
+
def on_file(file)
|
12
|
+
return unless file.translation?
|
13
|
+
return if file.parse_error
|
14
|
+
return add_offense_wrong_language_in_file(file) if file.language != file.language_from_path
|
15
|
+
return check_if_file_exists_for_all_other_languages(file) if file.language == @platformos_app.default_language
|
16
|
+
|
17
|
+
default_language_file = @platformos_app.grouped_files[PlatformosCheck::TranslationFile][file.name.sub(file.language, @platformos_app.default_language)]
|
18
|
+
|
19
|
+
return add_offense_missing_file(file) if default_language_file.nil?
|
20
|
+
|
21
|
+
add_offense_different_structure(file, default_language_file) unless same_structure?(default_language_file.content[@platformos_app.default_language], file.content[file.language])
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def add_offense_wrong_language_in_file(file)
|
27
|
+
add_offense("Mismatch detected - file inside #{file.language_from_path} directory defines translations for `#{file.language}`", app_file: file) do |_corrector|
|
28
|
+
file.update_contents(file.content[file.language_from_path] = file.content.delete(file.content[file.language]))
|
29
|
+
file.write
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_offense_missing_file(file)
|
34
|
+
add_offense("Mismatch detected - missing `#{file.relative_path.to_s.sub(file.language, @platformos_app.default_language)}` to define translations the default language", app_file: file)
|
35
|
+
end
|
36
|
+
|
37
|
+
def check_if_file_exists_for_all_other_languages(file)
|
38
|
+
@platformos_app.translations_hash.each_key do |lang|
|
39
|
+
next if lang == @platformos_app.default_language
|
40
|
+
|
41
|
+
language_file = @platformos_app.grouped_files[PlatformosCheck::TranslationFile][file.name.sub(file.language, lang)]
|
42
|
+
add_offense_missing_translation_file(file, lang) if language_file.nil?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_offense_missing_translation_file(file, lang)
|
47
|
+
missing_file_path = file.relative_path.to_s.sub(file.language, lang)
|
48
|
+
add_offense("Mismatch detected - missing `#{missing_file_path}` file to define translations for `#{lang}`", app_file: file) do |corrector|
|
49
|
+
missing_file_content = file.content.clone
|
50
|
+
missing_file_content[lang] = missing_file_content.delete(file.language)
|
51
|
+
corrector.create_file(@platformos_app.storage, missing_file_path, YAML.dump(missing_file_content))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def same_structure?(hash1, hash2)
|
56
|
+
if !hash1.is_a?(Hash) && !hash2.is_a?(Hash)
|
57
|
+
true
|
58
|
+
elsif (hash1.is_a?(Hash) && !hash2.is_a?(Hash)) || (!hash1.is_a?(Hash) && hash2.is_a?(Hash))
|
59
|
+
false
|
60
|
+
elsif pluralization?(hash1) && pluralization?(hash2)
|
61
|
+
true
|
62
|
+
elsif hash1.keys.map(&:to_s).sort != hash2.keys.map(&:to_s).sort
|
63
|
+
false
|
64
|
+
else
|
65
|
+
hash1.keys.all? { |key| same_structure?(hash1[key], hash2[key]) }
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_offense_different_structure(file, default_language_file)
|
70
|
+
add_offense("Mismatch detected - structure differs from the default language file #{default_language_file.relative_path}", app_file: file) do |_corrector|
|
71
|
+
file.content[file.language].transform_values! { |v| v.nil? ? {} : v }
|
72
|
+
file.content[file.language] = default_language_file.content[default_language_file.language].deep_merge(file.content[file.language])
|
73
|
+
file.write
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def pluralization?(hash)
|
78
|
+
hash.all? do |key, value|
|
79
|
+
PLURALIZATION_KEYS.include?(key) && !value.is_a?(Hash)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
# Recommends using {% liquid ... %} if 5 or more consecutive {% ... %} are found.
|
5
|
+
class TranslationKeyExists < LiquidCheck
|
6
|
+
severity :error
|
7
|
+
categories :translation, :liquid
|
8
|
+
doc docs_url(__FILE__)
|
9
|
+
|
10
|
+
def on_variable(node)
|
11
|
+
return unless node.value.name.is_a?(String)
|
12
|
+
return unless node.filters.size == 1
|
13
|
+
|
14
|
+
translation_filter = node.filters.detect { |f| TranslationFile::TRANSLATION_FILTERS.include?(f[0]) }
|
15
|
+
return unless translation_filter
|
16
|
+
return unless translation_filter
|
17
|
+
|
18
|
+
filter_attributes = translation_filter[2] || {}
|
19
|
+
|
20
|
+
return unless filter_attributes['default'].nil?
|
21
|
+
return if !filter_attributes['scope'].nil? && !filter_attributes['scope'].is_a?(String)
|
22
|
+
|
23
|
+
lang = filter_attributes['language'].is_a?(String) ? filter_attributes['language'] : @platformos_app.default_language
|
24
|
+
translation_components = node.value.name.split('.')
|
25
|
+
|
26
|
+
translation_components = filter_attributes['scope'].split('.') + translation_components if filter_attributes['scope']
|
27
|
+
|
28
|
+
return add_translation_offense(node:, lang:) if @platformos_app.translations_hash.empty?
|
29
|
+
|
30
|
+
hash = @platformos_app.translations_hash[lang] || {}
|
31
|
+
index = 0
|
32
|
+
while translation_components[index]
|
33
|
+
hash = hash[translation_components[index]]
|
34
|
+
if hash.nil?
|
35
|
+
add_translation_offense(node:, lang:)
|
36
|
+
break
|
37
|
+
end
|
38
|
+
index += 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
protected
|
43
|
+
|
44
|
+
def add_translation_offense(node:, lang:)
|
45
|
+
add_offense("Translation `#{lang}.#{node.value.name}` does not exists", node:)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
def deep_merge!(other_hash, &block)
|
5
|
+
merge!(other_hash) do |key, this_val, other_val|
|
6
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
7
|
+
this_val.deep_merge(other_val, &block)
|
8
|
+
elsif block
|
9
|
+
yield(key, this_val, other_val)
|
10
|
+
else
|
11
|
+
other_val
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def deep_merge(other_hash, &)
|
17
|
+
dup.deep_merge!(other_hash, &)
|
18
|
+
end
|
19
|
+
end
|
@@ -50,15 +50,15 @@ module PlatformosCheck
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def parse
|
53
|
-
@parse ||= GraphQL.parse(source)
|
53
|
+
@parse ||= source && source.strip != '' ? GraphQL.parse(source) : nil
|
54
54
|
end
|
55
55
|
|
56
56
|
def warnings
|
57
|
-
parse
|
57
|
+
parse&.warnings || {}
|
58
58
|
end
|
59
59
|
|
60
60
|
def root
|
61
|
-
parse
|
61
|
+
parse&.root || {}
|
62
62
|
end
|
63
63
|
|
64
64
|
def self.parse(_source)
|
@@ -80,11 +80,15 @@ module PlatformosCheck
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def selections
|
83
|
-
definition
|
83
|
+
definition&.selections
|
84
84
|
end
|
85
85
|
|
86
86
|
def fragments
|
87
|
-
@fragments ||= parse
|
87
|
+
@fragments ||= parse&.definitions&.select { |d| d.is_a?(GraphQL::Language::Nodes::FragmentDefinition) } || []
|
88
|
+
end
|
89
|
+
|
90
|
+
def graphql?
|
91
|
+
true
|
88
92
|
end
|
89
93
|
|
90
94
|
private
|
@@ -94,7 +98,7 @@ module PlatformosCheck
|
|
94
98
|
end
|
95
99
|
|
96
100
|
def definition
|
97
|
-
@definition ||= parse
|
101
|
+
@definition ||= parse&.definitions&.detect { |d| d.is_a?(GraphQL::Language::Nodes::OperationDefinition) }
|
98
102
|
end
|
99
103
|
|
100
104
|
def bounded(lower, x, upper)
|
@@ -32,13 +32,29 @@ module PlatformosCheck
|
|
32
32
|
PARTIAL_GRAPHQL = partial_tag_with_result('graphql')
|
33
33
|
PARTIAL_BACKGROUND = partial_tag_with_result('background')
|
34
34
|
|
35
|
+
TAGS_FOR_FILTERS = 'echo|print|log|hash_assign|assign'
|
36
|
+
TRANSLATION_FILTERS_NAMES = 'translate|t_escape|translate_escape|t[^\\w]'
|
37
|
+
OPTIONAL_SCOPE_ARGUMENT = %((:?([\\w:'"\\s]*)\\s*(scope:\\s*['"](?<scope>[^'"]*)['"]))?)
|
38
|
+
|
39
|
+
LOCALIZE_FILTERS_NAMES = ''
|
40
|
+
|
35
41
|
ASSET_INCLUDE = /
|
36
42
|
\{\{-?\s*'(?<partial>[^']*)'\s*\|\s*asset_url|
|
37
43
|
\{\{-?\s*"(?<partial>[^"]*)"\s*\|\s*asset_url|
|
38
44
|
|
39
45
|
# in liquid tags the whole line is white space until the asset partial
|
40
|
-
^\s*(
|
41
|
-
^\s*(
|
46
|
+
^\s*(?:#{TAGS_FOR_FILTERS}[^=]*=)\s*'(?<partial>[^']*)'\s*\|\s*asset_url|
|
47
|
+
^\s*(?:#{TAGS_FOR_FILTERS}[^=]*=)\s*"(?<partial>[^"]*)"\s*\|\s*asset_url
|
48
|
+
/mix
|
49
|
+
|
50
|
+
TRANSLATION_FILTER = /
|
51
|
+
'(?<key>[^']*)'\s*\|\s*(#{TRANSLATION_FILTERS_NAMES})#{OPTIONAL_SCOPE_ARGUMENT}|
|
52
|
+
"(?<key>[^"]*)"\s*\|\s*(#{TRANSLATION_FILTERS_NAMES})#{OPTIONAL_SCOPE_ARGUMENT}
|
53
|
+
/mix
|
54
|
+
|
55
|
+
LOCALIZE_FILTER = /
|
56
|
+
[\s\w'"-:.]+\|\s*(localize|l):\s*'(?<key>[^']*)'|
|
57
|
+
[\s\w'"-:.]+\|\s*(localize|l):\s*"(?<key>[^"]*)"
|
42
58
|
/mix
|
43
59
|
end
|
44
60
|
end
|
@@ -7,6 +7,16 @@ module PlatformosCheck
|
|
7
7
|
include PositionHelper
|
8
8
|
include URIHelper
|
9
9
|
|
10
|
+
class DefaultTranslationFile
|
11
|
+
def initialize(default_language)
|
12
|
+
@default_language = default_language
|
13
|
+
end
|
14
|
+
|
15
|
+
def relative_path
|
16
|
+
Pathname.new(@default_language, "#{@default_language}.yml")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
10
20
|
class << self
|
11
21
|
attr_accessor :partial_regexp, :app_file_type, :default_dir, :default_extension
|
12
22
|
|
@@ -41,18 +51,12 @@ module PlatformosCheck
|
|
41
51
|
|
42
52
|
def document_links(buffer, platformos_app)
|
43
53
|
matches(buffer, partial_regexp).map do |match|
|
44
|
-
start_row, start_column =
|
45
|
-
buffer,
|
46
|
-
match.begin(:partial)
|
47
|
-
)
|
54
|
+
start_row, start_column = start_coordinates(buffer, match)
|
48
55
|
|
49
|
-
end_row, end_column =
|
50
|
-
buffer,
|
51
|
-
match.end(:partial)
|
52
|
-
)
|
56
|
+
end_row, end_column = end_coordinates(buffer, match)
|
53
57
|
|
54
58
|
{
|
55
|
-
target: file_link(match
|
59
|
+
target: file_link(match, platformos_app),
|
56
60
|
range: {
|
57
61
|
start: {
|
58
62
|
line: start_row,
|
@@ -67,13 +71,66 @@ module PlatformosCheck
|
|
67
71
|
end
|
68
72
|
end
|
69
73
|
|
70
|
-
def
|
74
|
+
def start_coordinates(buffer, match)
|
75
|
+
from_index_to_row_column(
|
76
|
+
buffer,
|
77
|
+
match.begin(:partial)
|
78
|
+
)
|
79
|
+
end
|
80
|
+
|
81
|
+
def end_coordinates(buffer, match)
|
82
|
+
from_index_to_row_column(
|
83
|
+
buffer,
|
84
|
+
match.end(:partial)
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
def file_link(match, platformos_app)
|
89
|
+
partial = match[:partial]
|
71
90
|
relative_path = platformos_app.send(app_file_type).detect { |f| f.name == partial }&.relative_path
|
72
91
|
relative_path ||= default_relative_path(partial)
|
73
92
|
|
74
93
|
file_uri(@storage.path(relative_path))
|
75
94
|
end
|
76
95
|
|
96
|
+
def translation_file_link(match, platformos_app)
|
97
|
+
@current_best_fit = platformos_app.translations.first || DefaultTranslationFile.new(platformos_app.default_language)
|
98
|
+
@current_best_fit_level = 0
|
99
|
+
array_of_translation_components = translation_components_for_match(match)
|
100
|
+
platformos_app.translations.each do |translation_file|
|
101
|
+
array_of_translation_components.each do |translation_components|
|
102
|
+
exact_match_level = translation_components.size
|
103
|
+
component_result = translation_file.content[platformos_app.default_language]
|
104
|
+
next if component_result.nil?
|
105
|
+
|
106
|
+
i = 0
|
107
|
+
while i < exact_match_level
|
108
|
+
component_result = yaml(component_result, translation_components[i])
|
109
|
+
|
110
|
+
break if component_result.nil?
|
111
|
+
|
112
|
+
i += 1
|
113
|
+
if i > @current_best_fit_level
|
114
|
+
@current_best_fit = translation_file
|
115
|
+
@current_best_fit_level = i
|
116
|
+
end
|
117
|
+
|
118
|
+
break unless component_result.is_a?(Hash)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
file_uri(@storage.path(@current_best_fit&.relative_path))
|
124
|
+
end
|
125
|
+
|
126
|
+
def translation_components_for_match(match)
|
127
|
+
raise NotImplementedError
|
128
|
+
end
|
129
|
+
|
130
|
+
def yaml(component_result, component)
|
131
|
+
component_result[component]
|
132
|
+
end
|
133
|
+
|
77
134
|
def default_relative_path(partial)
|
78
135
|
return Pathname.new("app/#{default_dir}/#{partial}#{default_extension}") unless partial.start_with?('modules/')
|
79
136
|
|
data/lib/platformos_check/language_server/document_link_providers/localize_document_link_provider.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
module LanguageServer
|
5
|
+
class LocalizeDocumentLinkProvider < DocumentLinkProvider
|
6
|
+
@partial_regexp = LOCALIZE_FILTER
|
7
|
+
@app_file_type = :translations
|
8
|
+
@default_dir = 'translations'
|
9
|
+
@default_extension = '.yml'
|
10
|
+
|
11
|
+
def file_link(match, platformos_app)
|
12
|
+
translation_file_link(match, platformos_app)
|
13
|
+
end
|
14
|
+
|
15
|
+
def translation_components_for_match(match)
|
16
|
+
key = match[:key].split('.')
|
17
|
+
[
|
18
|
+
%w[time formats] + key,
|
19
|
+
%w[date formats] + key
|
20
|
+
]
|
21
|
+
end
|
22
|
+
|
23
|
+
def start_coordinates(buffer, match)
|
24
|
+
from_index_to_row_column(
|
25
|
+
buffer,
|
26
|
+
match.begin(:key)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
def end_coordinates(buffer, match)
|
31
|
+
from_index_to_row_column(
|
32
|
+
buffer,
|
33
|
+
match.end(:key)
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -8,7 +8,8 @@ module PlatformosCheck
|
|
8
8
|
@default_dir = 'views/partials'
|
9
9
|
@default_extension = '.liquid'
|
10
10
|
|
11
|
-
def file_link(
|
11
|
+
def file_link(match, platformos_app)
|
12
|
+
partial = match[:partial]
|
12
13
|
relative_path = nil
|
13
14
|
path_prefixes(platformos_app).each do |prefix|
|
14
15
|
prefix ||= ''
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PlatformosCheck
|
4
|
+
module LanguageServer
|
5
|
+
class TranslationDocumentLinkProvider < DocumentLinkProvider
|
6
|
+
@partial_regexp = TRANSLATION_FILTER
|
7
|
+
@app_file_type = :translations
|
8
|
+
@default_dir = 'translations'
|
9
|
+
@default_extension = '.yml'
|
10
|
+
|
11
|
+
def file_link(match, platformos_app)
|
12
|
+
translation_file_link(match, platformos_app)
|
13
|
+
end
|
14
|
+
|
15
|
+
def translation_components_for_match(match)
|
16
|
+
translation_components = match[:key].split('.')
|
17
|
+
translation_components = match[:scope].split('.') + translation_components if match[:scope]
|
18
|
+
[translation_components]
|
19
|
+
end
|
20
|
+
|
21
|
+
def start_coordinates(buffer, match)
|
22
|
+
from_index_to_row_column(
|
23
|
+
buffer,
|
24
|
+
match.begin(:key)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def end_coordinates(buffer, match)
|
29
|
+
from_index_to_row_column(
|
30
|
+
buffer,
|
31
|
+
match.end(:key)
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -2,5 +2,45 @@
|
|
2
2
|
|
3
3
|
module PlatformosCheck
|
4
4
|
class TranslationFile < YamlFile
|
5
|
+
DIR_PREFIX = %r{\A/?((marketplace_builder|app)/(translations)/|modules/((\w|-)*)/(private|public)/(translations)/)}
|
6
|
+
TRANSLATION_FILTERS = Set.new(%w[t t_escape translate translate_escape]).freeze
|
7
|
+
attr_reader :language
|
8
|
+
|
9
|
+
def load!
|
10
|
+
before_load
|
11
|
+
super
|
12
|
+
after_load
|
13
|
+
end
|
14
|
+
|
15
|
+
def before_load
|
16
|
+
@storage.platformos_app.instance_variable_set(:@translations_hash, nil) unless @loaded
|
17
|
+
end
|
18
|
+
|
19
|
+
def after_load
|
20
|
+
@language = @content&.keys&.first
|
21
|
+
return if module_name.nil?
|
22
|
+
|
23
|
+
@content[@language].transform_keys! { |key| key.start_with?(module_prefix) ? key : "#{module_prefix}#{key}" }
|
24
|
+
end
|
25
|
+
|
26
|
+
def language_from_path
|
27
|
+
@language_from_path ||= name.sub(module_prefix, '').split(File::SEPARATOR).first
|
28
|
+
end
|
29
|
+
|
30
|
+
def update_contents(new_content = {})
|
31
|
+
before_load
|
32
|
+
super(new_content)
|
33
|
+
@loaded = true
|
34
|
+
|
35
|
+
after_load
|
36
|
+
end
|
37
|
+
|
38
|
+
def dir_prefix
|
39
|
+
DIR_PREFIX
|
40
|
+
end
|
41
|
+
|
42
|
+
def translation?
|
43
|
+
true
|
44
|
+
end
|
5
45
|
end
|
6
46
|
end
|
@@ -28,14 +28,19 @@ module PlatformosCheck
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def write
|
31
|
+
pretty = content_to_string
|
32
|
+
@storage.write(@relative_path, pretty)
|
33
|
+
@source = pretty
|
34
|
+
end
|
35
|
+
|
36
|
+
def content_to_string
|
31
37
|
pretty = YAML.dump(@content)
|
32
38
|
return unless source.rstrip != pretty.rstrip
|
33
39
|
|
34
40
|
# Most editors add a trailing \n at the end of files. Here we
|
35
41
|
# try to maintain the convention.
|
36
42
|
eof = source.end_with?("\n") ? "\n" : ""
|
37
|
-
|
38
|
-
@source = pretty
|
43
|
+
pretty.gsub("\n", @eol) + eof
|
39
44
|
end
|
40
45
|
|
41
46
|
def yaml?
|
data/lib/platformos_check.rb
CHANGED
@@ -5,6 +5,7 @@ require "liquid"
|
|
5
5
|
require_relative "platformos_check/version"
|
6
6
|
require_relative "platformos_check/bug"
|
7
7
|
require_relative "platformos_check/exceptions"
|
8
|
+
require_relative "platformos_check/ext/hash"
|
8
9
|
require_relative "platformos_check/json_helper"
|
9
10
|
require_relative "platformos_check/app_file_rewriter"
|
10
11
|
require_relative "platformos_check/app_file"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: platformos-check
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Bliszczyk
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-
|
13
|
+
date: 2024-03-11 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: graphql
|
@@ -134,6 +134,8 @@ files:
|
|
134
134
|
- docs/checks/space_inside_braces.md
|
135
135
|
- docs/checks/syntax_error.md
|
136
136
|
- docs/checks/template_length.md
|
137
|
+
- docs/checks/translation_files_match.md
|
138
|
+
- docs/checks/translation_key_exists.md
|
137
139
|
- docs/checks/undefined_object.md
|
138
140
|
- docs/checks/unknown_filter.md
|
139
141
|
- docs/checks/unreachable_code.md
|
@@ -148,7 +150,7 @@ files:
|
|
148
150
|
- docs/language_server/code-action-problem.png
|
149
151
|
- docs/language_server/code-action-quickfix.png
|
150
152
|
- docs/language_server/how_to_correct_code_with_code_actions_and_execute_command.md
|
151
|
-
- docs/
|
153
|
+
- docs/platformos-check.jpg
|
152
154
|
- exe/platformos-check
|
153
155
|
- exe/platformos-check-language-server
|
154
156
|
- lib/platformos_check.rb
|
@@ -181,6 +183,8 @@ files:
|
|
181
183
|
- lib/platformos_check/checks/space_inside_braces.rb
|
182
184
|
- lib/platformos_check/checks/syntax_error.rb
|
183
185
|
- lib/platformos_check/checks/template_length.rb
|
186
|
+
- lib/platformos_check/checks/translation_files_match.rb
|
187
|
+
- lib/platformos_check/checks/translation_key_exists.rb
|
184
188
|
- lib/platformos_check/checks/undefined_object.rb
|
185
189
|
- lib/platformos_check/checks/unknown_filter.rb
|
186
190
|
- lib/platformos_check/checks/unreachable_code.rb
|
@@ -196,6 +200,7 @@ files:
|
|
196
200
|
- lib/platformos_check/disabled_checks.rb
|
197
201
|
- lib/platformos_check/email_file.rb
|
198
202
|
- lib/platformos_check/exceptions.rb
|
203
|
+
- lib/platformos_check/ext/hash.rb
|
199
204
|
- lib/platformos_check/file_system_storage.rb
|
200
205
|
- lib/platformos_check/form_file.rb
|
201
206
|
- lib/platformos_check/graphql_file.rb
|
@@ -244,8 +249,10 @@ files:
|
|
244
249
|
- lib/platformos_check/language_server/document_link_providers/graphql_document_link_provider.rb
|
245
250
|
- lib/platformos_check/language_server/document_link_providers/include_document_link_provider.rb
|
246
251
|
- lib/platformos_check/language_server/document_link_providers/include_form_document_link_provider.rb
|
252
|
+
- lib/platformos_check/language_server/document_link_providers/localize_document_link_provider.rb
|
247
253
|
- lib/platformos_check/language_server/document_link_providers/render_document_link_provider.rb
|
248
254
|
- lib/platformos_check/language_server/document_link_providers/theme_render_document_link_provider.rb
|
255
|
+
- lib/platformos_check/language_server/document_link_providers/translation_document_link_provider.rb
|
249
256
|
- lib/platformos_check/language_server/execute_command_engine.rb
|
250
257
|
- lib/platformos_check/language_server/execute_command_provider.rb
|
251
258
|
- lib/platformos_check/language_server/execute_command_providers/correction_execute_command_provider.rb
|
@@ -366,7 +373,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
366
373
|
- !ruby/object:Gem::Version
|
367
374
|
version: '0'
|
368
375
|
requirements: []
|
369
|
-
rubygems_version: 3.
|
376
|
+
rubygems_version: 3.5.6
|
370
377
|
signing_key:
|
371
378
|
specification_version: 4
|
372
379
|
summary: A platformOS App Linter
|
data/docs/preview.png
DELETED
Binary file
|