zendesk_apps_support 1.17.0 → 1.17.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/zendesk_apps_support.rb +0 -1
- data/lib/zendesk_apps_support/app_file.rb +5 -5
- data/lib/zendesk_apps_support/app_version.rb +3 -7
- data/lib/zendesk_apps_support/build_translation.rb +1 -4
- data/lib/zendesk_apps_support/engine.rb +0 -2
- data/lib/zendesk_apps_support/i18n.rb +2 -2
- data/lib/zendesk_apps_support/package.rb +32 -33
- data/lib/zendesk_apps_support/sass_functions.rb +1 -3
- data/lib/zendesk_apps_support/stylesheet_compiler.rb +1 -3
- data/lib/zendesk_apps_support/validations/banner.rb +4 -4
- data/lib/zendesk_apps_support/validations/manifest.rb +21 -24
- data/lib/zendesk_apps_support/validations/requirements.rb +6 -8
- data/lib/zendesk_apps_support/validations/source.rb +11 -13
- data/lib/zendesk_apps_support/validations/stylesheets.rb +1 -4
- data/lib/zendesk_apps_support/validations/templates.rb +1 -3
- data/lib/zendesk_apps_support/validations/translations.rb +10 -10
- data/lib/zendesk_apps_support/validations/validation_error.rb +10 -12
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4652177f210c7e96e96dda1dd85b981b2d9017c1
|
4
|
+
data.tar.gz: 707731e9c4eb073339dc46ba1529416b43d63aa0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b31cb09a925f5987c82290c4f4cae89ea09e41ade156db05bd1409d20a4f6e4bb7426ef2cf1710f892579ea5be834b211e863a11a7547d0ba7459518c31c054
|
7
|
+
data.tar.gz: 3b3d587b40cebbcbfba5d704371eb83c8bcd4d3395fe64243ebddf50e3b292d98427ee7fc0b60b91c0d8151ad8d8ee7089cb6b907d6022feb46a39b05075da53
|
data/lib/zendesk_apps_support.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module ZendeskAppsSupport
|
2
|
-
|
3
2
|
class AppFile
|
4
|
-
|
5
3
|
attr_reader :relative_path
|
6
4
|
attr_reader :absolute_path
|
7
5
|
|
@@ -16,7 +14,11 @@ module ZendeskAppsSupport
|
|
16
14
|
end
|
17
15
|
|
18
16
|
def =~(regex)
|
19
|
-
|
17
|
+
relative_path =~ regex
|
18
|
+
end
|
19
|
+
|
20
|
+
def match(regex)
|
21
|
+
self =~ regex
|
20
22
|
end
|
21
23
|
|
22
24
|
alias_method :to_s, :relative_path
|
@@ -38,7 +40,5 @@ module ZendeskAppsSupport
|
|
38
40
|
def respond_to_missing?(sym, include_private = false)
|
39
41
|
@file.send(:respond_to_missing?, sym, include_private) || super
|
40
42
|
end
|
41
|
-
|
42
43
|
end
|
43
|
-
|
44
44
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'multi_json'
|
2
2
|
|
3
3
|
module ZendeskAppsSupport
|
4
|
-
|
5
4
|
# At any point in time, we support up to three versions:
|
6
5
|
# * deprecated -- we will still serve apps targeting the deprecated version,
|
7
6
|
# but newly created or updated apps CANNOT target it
|
@@ -11,13 +10,12 @@ module ZendeskAppsSupport
|
|
11
10
|
# newly created or updates apps MAY target it, but it
|
12
11
|
# may change without notice
|
13
12
|
class AppVersion
|
14
|
-
|
15
13
|
DEPRECATED = '0.4'.freeze
|
16
14
|
CURRENT = '0.5'.freeze
|
17
15
|
FUTURE = '1.0'.freeze
|
18
16
|
|
19
|
-
TO_BE_SERVED = [
|
20
|
-
VALID_FOR_UPDATE = [
|
17
|
+
TO_BE_SERVED = [DEPRECATED, CURRENT, FUTURE].compact.freeze
|
18
|
+
VALID_FOR_UPDATE = [CURRENT, FUTURE].compact.freeze
|
21
19
|
|
22
20
|
def initialize(version)
|
23
21
|
@version = version.to_s
|
@@ -53,16 +51,14 @@ module ZendeskAppsSupport
|
|
53
51
|
@version
|
54
52
|
end
|
55
53
|
|
56
|
-
def to_json(*
|
54
|
+
def to_json(*)
|
57
55
|
MultiJson.encode(@version)
|
58
56
|
end
|
59
57
|
|
60
58
|
def ==(other)
|
61
59
|
@version == other.to_s
|
62
60
|
end
|
63
|
-
|
64
61
|
end
|
65
62
|
|
66
63
|
AppVersion.freeze
|
67
|
-
|
68
64
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module ZendeskAppsSupport
|
2
2
|
module BuildTranslation
|
3
|
-
|
4
3
|
I18N_TITLE_KEY = 'title'
|
5
4
|
I18N_VALUE_KEY = 'value'
|
6
5
|
I18N_KEYS = [I18N_TITLE_KEY, I18N_VALUE_KEY]
|
@@ -8,7 +7,7 @@ module ZendeskAppsSupport
|
|
8
7
|
def to_flattened_namespaced_hash(hash, target_key = nil, prefix = nil)
|
9
8
|
hash.inject({}) do |result, (key, value)|
|
10
9
|
key = [prefix, key].compact.join('.')
|
11
|
-
if value.
|
10
|
+
if value.is_a?(Hash)
|
12
11
|
if target_key && is_translation_hash?(value)
|
13
12
|
result[key] = value[target_key]
|
14
13
|
else
|
@@ -22,7 +21,6 @@ module ZendeskAppsSupport
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def remove_zendesk_keys(scope, translations = {})
|
25
|
-
|
26
24
|
scope.each_key do |key|
|
27
25
|
context = scope[key]
|
28
26
|
|
@@ -48,6 +46,5 @@ module ZendeskAppsSupport
|
|
48
46
|
def is_translation_hash?(hash)
|
49
47
|
hash.keys.sort == I18N_KEYS
|
50
48
|
end
|
51
|
-
|
52
49
|
end
|
53
50
|
end
|
@@ -20,8 +20,8 @@ module ZendeskAppsSupport
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def locale_files
|
23
|
-
Dir[
|
24
|
-
Dir[
|
23
|
+
Dir[File.expand_path('../../../config/locales/*.yml', __FILE__)] -
|
24
|
+
Dir[File.expand_path('../../../config/locales/*.zendesk.yml', __FILE__)]
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -6,9 +6,9 @@ module ZendeskAppsSupport
|
|
6
6
|
class Package
|
7
7
|
include ZendeskAppsSupport::BuildTranslation
|
8
8
|
|
9
|
-
DEFAULT_LAYOUT = Erubis::Eruby.new(
|
9
|
+
DEFAULT_LAYOUT = Erubis::Eruby.new(File.read(File.expand_path('../assets/default_template.html.erb', __FILE__)))
|
10
10
|
DEFAULT_SCSS = File.read(File.expand_path('../assets/default_styles.scss', __FILE__))
|
11
|
-
SRC_TEMPLATE = Erubis::Eruby.new(
|
11
|
+
SRC_TEMPLATE = Erubis::Eruby.new(File.read(File.expand_path('../assets/src.js.erb', __FILE__)))
|
12
12
|
|
13
13
|
attr_reader :lib_root, :root, :warnings
|
14
14
|
attr_accessor :requirements_only
|
@@ -22,7 +22,6 @@ module ZendeskAppsSupport
|
|
22
22
|
|
23
23
|
def validate
|
24
24
|
[].tap do |errors|
|
25
|
-
|
26
25
|
errors << Validations::Manifest.call(self)
|
27
26
|
|
28
27
|
if has_manifest?
|
@@ -48,7 +47,7 @@ module ZendeskAppsSupport
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def app_js
|
51
|
-
read_file(
|
50
|
+
read_file('app.js')
|
52
51
|
end
|
53
52
|
|
54
53
|
def commonjs_modules
|
@@ -78,22 +77,22 @@ module ZendeskAppsSupport
|
|
78
77
|
end
|
79
78
|
|
80
79
|
def manifest_json
|
81
|
-
read_json(
|
80
|
+
read_json('manifest.json')
|
82
81
|
end
|
83
82
|
|
84
83
|
def requirements_json
|
85
|
-
read_json(
|
84
|
+
read_json('requirements.json')
|
86
85
|
end
|
87
86
|
|
88
87
|
def translations
|
89
|
-
read_json(
|
88
|
+
read_json('translations/en.json', false)
|
90
89
|
end
|
91
90
|
|
92
91
|
def app_translations
|
93
92
|
remove_zendesk_keys(translations)
|
94
93
|
end
|
95
94
|
|
96
|
-
def readified_js(app_name, app_id, asset_url_prefix, settings={})
|
95
|
+
def readified_js(app_name, app_id, asset_url_prefix, settings = {})
|
97
96
|
manifest = manifest_json
|
98
97
|
source = app_js
|
99
98
|
name = app_name || manifest[:name] || 'Local App'
|
@@ -105,37 +104,37 @@ module ZendeskAppsSupport
|
|
105
104
|
no_template = manifest[:noTemplate]
|
106
105
|
templates = no_template ? {} : compiled_templates(app_id, asset_url_prefix)
|
107
106
|
|
108
|
-
settings[
|
107
|
+
settings['title'] = name
|
109
108
|
|
110
109
|
app_settings = {
|
111
|
-
:
|
112
|
-
:
|
113
|
-
:
|
114
|
-
}.select { |
|
110
|
+
location: location,
|
111
|
+
noTemplate: no_template,
|
112
|
+
singleInstall: single_install
|
113
|
+
}.select { |_k, v| !v.nil? }
|
115
114
|
|
116
115
|
SRC_TEMPLATE.result(
|
117
|
-
:
|
118
|
-
:
|
119
|
-
:
|
120
|
-
:
|
121
|
-
:
|
122
|
-
:
|
123
|
-
:
|
124
|
-
:
|
125
|
-
:
|
126
|
-
:
|
127
|
-
:
|
128
|
-
:
|
116
|
+
name: name,
|
117
|
+
source: source,
|
118
|
+
app_settings: app_settings,
|
119
|
+
asset_url_prefix: asset_url_prefix,
|
120
|
+
app_class_name: app_class_name,
|
121
|
+
author: author,
|
122
|
+
translations: app_translations,
|
123
|
+
framework_version: framework_version,
|
124
|
+
templates: templates,
|
125
|
+
settings: settings,
|
126
|
+
app_id: app_id,
|
127
|
+
modules: commonjs_modules
|
129
128
|
)
|
130
129
|
end
|
131
130
|
|
132
131
|
def customer_css
|
133
132
|
css_file = file_path('app.css')
|
134
|
-
|
133
|
+
File.exist?(css_file) ? File.read(css_file) : ''
|
135
134
|
end
|
136
135
|
|
137
136
|
def has_js?
|
138
|
-
file_exists?(
|
137
|
+
file_exists?('app.js')
|
139
138
|
end
|
140
139
|
|
141
140
|
def has_lib_js?
|
@@ -143,7 +142,7 @@ module ZendeskAppsSupport
|
|
143
142
|
end
|
144
143
|
|
145
144
|
def has_manifest?
|
146
|
-
file_exists?(
|
145
|
+
file_exists?('manifest.json')
|
147
146
|
end
|
148
147
|
|
149
148
|
def has_location?
|
@@ -151,11 +150,11 @@ module ZendeskAppsSupport
|
|
151
150
|
end
|
152
151
|
|
153
152
|
def has_requirements?
|
154
|
-
file_exists?(
|
153
|
+
file_exists?('requirements.json')
|
155
154
|
end
|
156
155
|
|
157
156
|
def has_banner?
|
158
|
-
file_exists?(
|
157
|
+
file_exists?('assets/banner.png')
|
159
158
|
end
|
160
159
|
|
161
160
|
def file_path(path)
|
@@ -168,7 +167,7 @@ module ZendeskAppsSupport
|
|
168
167
|
compiled_css = ZendeskAppsSupport::StylesheetCompiler.new(DEFAULT_SCSS + customer_css, app_id, asset_url_prefix).compile
|
169
168
|
|
170
169
|
templates = begin
|
171
|
-
Dir["#{root
|
170
|
+
Dir["#{root}/templates/*.hdbs"].inject({}) do |h, file|
|
172
171
|
str = File.read(file)
|
173
172
|
str.chomp!
|
174
173
|
h[File.basename(file, File.extname(file))] = str
|
@@ -185,7 +184,7 @@ module ZendeskAppsSupport
|
|
185
184
|
|
186
185
|
def non_tmp_files
|
187
186
|
files = []
|
188
|
-
Dir[
|
187
|
+
Dir[root.join('**/**')].each do |f|
|
189
188
|
next unless File.file?(f)
|
190
189
|
relative_file_name = f.sub(/#{root}\/?/, '')
|
191
190
|
next if relative_file_name =~ /^tmp\//
|
@@ -205,7 +204,7 @@ module ZendeskAppsSupport
|
|
205
204
|
def read_json(path, symbolize_names = true)
|
206
205
|
file = read_file(path)
|
207
206
|
unless file.nil?
|
208
|
-
JSON.parse(read_file(path), :
|
207
|
+
JSON.parse(read_file(path), symbolize_names: symbolize_names)
|
209
208
|
end
|
210
209
|
end
|
211
210
|
end
|
@@ -1,11 +1,10 @@
|
|
1
1
|
require 'sass'
|
2
2
|
|
3
3
|
module Sass::Script::Functions
|
4
|
-
|
5
4
|
module AppAssetUrl
|
6
5
|
def app_asset_url(name)
|
7
6
|
assert_type name, :String
|
8
|
-
result = %
|
7
|
+
result = %{url("#{app_asset_url_helper(name)}")}
|
9
8
|
Sass::Script::String.new(result)
|
10
9
|
end
|
11
10
|
|
@@ -18,5 +17,4 @@ module Sass::Script::Functions
|
|
18
17
|
end
|
19
18
|
|
20
19
|
include AppAssetUrl
|
21
|
-
|
22
20
|
end
|
@@ -2,13 +2,12 @@ require 'sass'
|
|
2
2
|
|
3
3
|
module ZendeskAppsSupport
|
4
4
|
class StylesheetCompiler
|
5
|
-
|
6
5
|
def initialize(source, app_id, url_prefix)
|
7
6
|
@source, @app_id, @url_prefix = source, app_id, url_prefix
|
8
7
|
end
|
9
8
|
|
10
9
|
def compile
|
11
|
-
Sass::Engine.new(wrapped_source, :
|
10
|
+
Sass::Engine.new(wrapped_source, syntax: :scss, app_asset_url_builder: self).render
|
12
11
|
end
|
13
12
|
|
14
13
|
def app_asset_url(name)
|
@@ -20,6 +19,5 @@ module ZendeskAppsSupport
|
|
20
19
|
def wrapped_source
|
21
20
|
".app-#{@app_id} {#{@source}}"
|
22
21
|
end
|
23
|
-
|
24
22
|
end
|
25
23
|
end
|
@@ -17,11 +17,11 @@ module ZendeskAppsSupport
|
|
17
17
|
end
|
18
18
|
|
19
19
|
unless (image.width == BANNER_WIDTH && image.height == BANNER_HEIGHT) ||
|
20
|
-
(image.width == 2*BANNER_WIDTH && image.height == 2*BANNER_HEIGHT)
|
21
|
-
return [ValidationError.new('banner.invalid_size', :
|
22
|
-
:
|
20
|
+
(image.width == 2 * BANNER_WIDTH && image.height == 2 * BANNER_HEIGHT)
|
21
|
+
return [ValidationError.new('banner.invalid_size', required_banner_width: BANNER_WIDTH,
|
22
|
+
required_banner_height: BANNER_HEIGHT)]
|
23
23
|
end
|
24
|
-
rescue
|
24
|
+
rescue
|
25
25
|
return [ValidationError.new('banner.invalid_format')]
|
26
26
|
end
|
27
27
|
end
|
@@ -3,11 +3,10 @@ require 'multi_json'
|
|
3
3
|
module ZendeskAppsSupport
|
4
4
|
module Validations
|
5
5
|
module Manifest
|
6
|
-
|
7
6
|
REQUIRED_MANIFEST_FIELDS = %w( author defaultLocale ).freeze
|
8
7
|
OAUTH_REQUIRED_FIELDS = %w( client_id client_secret authorize_uri access_token_uri ).freeze
|
9
8
|
LOCATIONS_AVAILABLE = %w( top_bar nav_bar ticket_sidebar new_ticket_sidebar user_sidebar ).freeze
|
10
|
-
TYPES_AVAILABLE = %
|
9
|
+
TYPES_AVAILABLE = %w( text password checkbox url number multiline hidden ).freeze
|
11
10
|
|
12
11
|
class <<self
|
13
12
|
def call(package)
|
@@ -42,7 +41,7 @@ module ZendeskAppsSupport
|
|
42
41
|
errors.compact!
|
43
42
|
end
|
44
43
|
rescue MultiJson::DecodeError => e
|
45
|
-
return [ValidationError.new(:manifest_not_json, :
|
44
|
+
return [ValidationError.new(:manifest_not_json, errors: e)]
|
46
45
|
end
|
47
46
|
|
48
47
|
private
|
@@ -63,22 +62,21 @@ module ZendeskAppsSupport
|
|
63
62
|
end
|
64
63
|
|
65
64
|
if missing.any?
|
66
|
-
ValidationError.new('oauth_keys.missing', :
|
65
|
+
ValidationError.new('oauth_keys.missing', missing_keys: missing.join(', '), count: missing.length)
|
67
66
|
end
|
68
|
-
|
69
67
|
end
|
70
68
|
|
71
69
|
def parameters_error(manifest)
|
72
70
|
return unless manifest['parameters']
|
73
71
|
|
74
|
-
unless manifest['parameters'].
|
72
|
+
unless manifest['parameters'].is_a?(Array)
|
75
73
|
return ValidationError.new(:parameters_not_an_array)
|
76
74
|
end
|
77
75
|
|
78
|
-
para_names = manifest['parameters'].collect{|para| para['name']}
|
79
|
-
duplicate_parameters = para_names.select {|name| para_names.count(name) > 1}.uniq
|
76
|
+
para_names = manifest['parameters'].collect { |para| para['name'] }
|
77
|
+
duplicate_parameters = para_names.select { |name| para_names.count(name) > 1 }.uniq
|
80
78
|
unless duplicate_parameters.empty?
|
81
|
-
return ValidationError.new(:duplicate_parameters, :
|
79
|
+
return ValidationError.new(:duplicate_parameters, duplicate_parameters: duplicate_parameters)
|
82
80
|
end
|
83
81
|
end
|
84
82
|
|
@@ -92,11 +90,11 @@ module ZendeskAppsSupport
|
|
92
90
|
|
93
91
|
def default_locale_error(manifest, package)
|
94
92
|
default_locale = manifest['defaultLocale']
|
95
|
-
|
93
|
+
unless default_locale.nil?
|
96
94
|
if default_locale !~ Translations::VALID_LOCALE
|
97
|
-
ValidationError.new(:invalid_default_locale, :
|
95
|
+
ValidationError.new(:invalid_default_locale, defaultLocale: default_locale)
|
98
96
|
elsif package.translation_files.detect { |file| file.relative_path == "translations/#{default_locale}.json" }.nil?
|
99
|
-
ValidationError.new(:missing_translation_file, :
|
97
|
+
ValidationError.new(:missing_translation_file, defaultLocale: default_locale)
|
100
98
|
end
|
101
99
|
end
|
102
100
|
end
|
@@ -108,7 +106,7 @@ module ZendeskAppsSupport
|
|
108
106
|
def invalid_location_error(manifest)
|
109
107
|
invalid_locations = [*manifest['location']] - LOCATIONS_AVAILABLE
|
110
108
|
unless invalid_locations.empty?
|
111
|
-
ValidationError.new(:invalid_location, :
|
109
|
+
ValidationError.new(:invalid_location, invalid_locations: invalid_locations.join(', '), count: invalid_locations.length)
|
112
110
|
end
|
113
111
|
end
|
114
112
|
|
@@ -117,7 +115,7 @@ module ZendeskAppsSupport
|
|
117
115
|
duplicate_locations = *locations.select { |location| locations.count(location) > 1 }.uniq
|
118
116
|
|
119
117
|
unless duplicate_locations.empty?
|
120
|
-
ValidationError.new(:duplicate_location, :
|
118
|
+
ValidationError.new(:duplicate_location, duplicate_locations: duplicate_locations.join(', '), count: duplicate_locations.length)
|
121
119
|
end
|
122
120
|
end
|
123
121
|
|
@@ -134,12 +132,12 @@ module ZendeskAppsSupport
|
|
134
132
|
end
|
135
133
|
|
136
134
|
unless valid_to_serve.include?(target_version)
|
137
|
-
return ValidationError.new(:invalid_version, :
|
135
|
+
return ValidationError.new(:invalid_version, target_version: target_version, available_versions: valid_to_serve.join(', '))
|
138
136
|
end
|
139
137
|
end
|
140
138
|
|
141
139
|
def name_as_parameter_name_error(manifest)
|
142
|
-
if manifest['parameters'].
|
140
|
+
if manifest['parameters'].is_a?(Array)
|
143
141
|
if manifest['parameters'].any? { |p| p['name'] == 'name' }
|
144
142
|
ValidationError.new(:name_as_parameter_name)
|
145
143
|
end
|
@@ -149,35 +147,34 @@ module ZendeskAppsSupport
|
|
149
147
|
def invalid_hidden_parameter_error(manifest)
|
150
148
|
invalid_params = []
|
151
149
|
|
152
|
-
if manifest.
|
150
|
+
if manifest.key?('parameters')
|
153
151
|
invalid_params = manifest['parameters'].select { |p| p['type'] == 'hidden' && p['required'] }.map { |p| p['name'] }
|
154
152
|
end
|
155
153
|
|
156
154
|
if invalid_params.any?
|
157
|
-
ValidationError.new(:invalid_hidden_parameter, :
|
155
|
+
ValidationError.new(:invalid_hidden_parameter, invalid_params: invalid_params.join(', '), count: invalid_params.length)
|
158
156
|
end
|
159
157
|
end
|
160
158
|
|
161
159
|
def invalid_type_error(manifest)
|
162
|
-
return unless manifest['parameters'].
|
160
|
+
return unless manifest['parameters'].is_a?(Array)
|
163
161
|
|
164
162
|
invalid_types = []
|
165
163
|
|
166
|
-
manifest[
|
167
|
-
parameter_type = parameter.fetch(
|
164
|
+
manifest['parameters'].each do |parameter|
|
165
|
+
parameter_type = parameter.fetch('type', '')
|
168
166
|
|
169
167
|
invalid_types << parameter_type unless TYPES_AVAILABLE.include?(parameter_type)
|
170
168
|
end
|
171
169
|
|
172
170
|
if invalid_types.any?
|
173
|
-
ValidationError.new(:invalid_type_parameter, :
|
171
|
+
ValidationError.new(:invalid_type_parameter, invalid_types: invalid_types.join(', '), count: invalid_types.length)
|
174
172
|
end
|
175
173
|
end
|
176
174
|
|
177
175
|
def missing_keys_validation_error(missing_keys)
|
178
|
-
ValidationError.new('manifest_keys.missing', :
|
176
|
+
ValidationError.new('manifest_keys.missing', missing_keys: missing_keys.join(', '), count: missing_keys.length)
|
179
177
|
end
|
180
|
-
|
181
178
|
end
|
182
179
|
end
|
183
180
|
end
|
@@ -4,7 +4,6 @@ require 'json/stream'
|
|
4
4
|
module ZendeskAppsSupport
|
5
5
|
module Validations
|
6
6
|
module Requirements
|
7
|
-
|
8
7
|
MAX_REQUIREMENTS = 5000
|
9
8
|
|
10
9
|
class <<self
|
@@ -16,7 +15,7 @@ module ZendeskAppsSupport
|
|
16
15
|
requirements_stream = requirements_file.read
|
17
16
|
duplicates = non_unique_type_keys(requirements_stream)
|
18
17
|
unless duplicates.empty?
|
19
|
-
return [ValidationError.new(:duplicate_requirements, :
|
18
|
+
return [ValidationError.new(:duplicate_requirements, duplicate_keys: duplicates.join(', '), count: duplicates.length)]
|
20
19
|
end
|
21
20
|
|
22
21
|
requirements = MultiJson.load(requirements_stream)
|
@@ -28,7 +27,7 @@ module ZendeskAppsSupport
|
|
28
27
|
errors.compact!
|
29
28
|
end
|
30
29
|
rescue MultiJson::DecodeError => e
|
31
|
-
return [ValidationError.new(:requirements_not_json, :
|
30
|
+
return [ValidationError.new(:requirements_not_json, errors: e)]
|
32
31
|
end
|
33
32
|
|
34
33
|
private
|
@@ -38,14 +37,14 @@ module ZendeskAppsSupport
|
|
38
37
|
requirements.values.each do |requirement|
|
39
38
|
requirement.each do |identifier, fields|
|
40
39
|
next if fields.include? 'title'
|
41
|
-
errors << ValidationError.new(:missing_required_fields, :
|
40
|
+
errors << ValidationError.new(:missing_required_fields, field: 'title', identifier: identifier)
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
44
|
unless requirements['user_fields'].nil?
|
46
45
|
requirements['user_fields'].each do |identifier, fields|
|
47
46
|
next if fields.include? 'key'
|
48
|
-
errors << ValidationError.new(:missing_required_fields, :
|
47
|
+
errors << ValidationError.new(:missing_required_fields, field: 'key', identifier: identifier)
|
49
48
|
end
|
50
49
|
end
|
51
50
|
end
|
@@ -54,7 +53,7 @@ module ZendeskAppsSupport
|
|
54
53
|
def excessive_requirements(requirements)
|
55
54
|
requirement_count = requirements.values.map(&:values).flatten.size
|
56
55
|
if requirement_count > MAX_REQUIREMENTS
|
57
|
-
ValidationError.new(:excessive_requirements, :
|
56
|
+
ValidationError.new(:excessive_requirements, max: MAX_REQUIREMENTS, count: requirement_count)
|
58
57
|
end
|
59
58
|
end
|
60
59
|
|
@@ -62,7 +61,7 @@ module ZendeskAppsSupport
|
|
62
61
|
invalid_types = requirements.keys - ZendeskAppsSupport::AppRequirement::TYPES
|
63
62
|
|
64
63
|
unless invalid_types.empty?
|
65
|
-
ValidationError.new(:invalid_requirements_types, :
|
64
|
+
ValidationError.new(:invalid_requirements_types, invalid_types: invalid_types.join(', '), count: invalid_types.length)
|
66
65
|
end
|
67
66
|
end
|
68
67
|
|
@@ -78,7 +77,6 @@ module ZendeskAppsSupport
|
|
78
77
|
|
79
78
|
duplicates
|
80
79
|
end
|
81
|
-
|
82
80
|
end
|
83
81
|
end
|
84
82
|
end
|
@@ -3,21 +3,20 @@ require 'jshintrb'
|
|
3
3
|
module ZendeskAppsSupport
|
4
4
|
module Validations
|
5
5
|
module Source
|
6
|
-
|
7
6
|
LINTER_OPTIONS = {
|
8
7
|
# enforcing options:
|
9
|
-
:
|
10
|
-
:
|
8
|
+
noarg: true,
|
9
|
+
undef: true,
|
11
10
|
|
12
11
|
# relaxing options:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
12
|
+
eqnull: true,
|
13
|
+
laxcomma: true,
|
14
|
+
sub: true,
|
16
15
|
|
17
16
|
# predefined globals:
|
18
|
-
:
|
19
|
-
|
20
|
-
|
17
|
+
predef: %w(_ console services helpers alert window document self
|
18
|
+
JSON Base64 clearInterval clearTimeout setInterval setTimeout
|
19
|
+
require module exports top frames parent moment)
|
21
20
|
}.freeze
|
22
21
|
|
23
22
|
class <<self
|
@@ -26,10 +25,10 @@ module ZendeskAppsSupport
|
|
26
25
|
files = package.lib_files << app
|
27
26
|
|
28
27
|
if package.requirements_only
|
29
|
-
return app ? [
|
28
|
+
return app ? [ValidationError.new(:no_app_js_required)] : []
|
30
29
|
end
|
31
30
|
|
32
|
-
return [
|
31
|
+
return [ValidationError.new(:missing_source)] unless app
|
33
32
|
|
34
33
|
jshint_errors(files).flatten!
|
35
34
|
end
|
@@ -38,7 +37,7 @@ module ZendeskAppsSupport
|
|
38
37
|
|
39
38
|
def jshint_error(file)
|
40
39
|
errors = linter.lint(file.read)
|
41
|
-
[
|
40
|
+
[JSHintValidationError.new(file.relative_path, errors)] if errors.any?
|
42
41
|
end
|
43
42
|
|
44
43
|
def jshint_errors(files)
|
@@ -51,7 +50,6 @@ module ZendeskAppsSupport
|
|
51
50
|
def linter
|
52
51
|
Jshintrb::Lint.new(LINTER_OPTIONS)
|
53
52
|
end
|
54
|
-
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
@@ -3,9 +3,7 @@ require 'zendesk_apps_support/stylesheet_compiler'
|
|
3
3
|
module ZendeskAppsSupport
|
4
4
|
module Validations
|
5
5
|
module Stylesheets
|
6
|
-
|
7
6
|
class << self
|
8
|
-
|
9
7
|
def call(package)
|
10
8
|
if css_error = validate_styles(package.customer_css)
|
11
9
|
[css_error]
|
@@ -21,11 +19,10 @@ module ZendeskAppsSupport
|
|
21
19
|
begin
|
22
20
|
compiler.compile
|
23
21
|
rescue Sass::SyntaxError => e
|
24
|
-
return ValidationError.new(:stylesheet_error, :
|
22
|
+
return ValidationError.new(:stylesheet_error, sass_error: e.message)
|
25
23
|
end
|
26
24
|
nil
|
27
25
|
end
|
28
|
-
|
29
26
|
end
|
30
27
|
end
|
31
28
|
end
|
@@ -1,20 +1,18 @@
|
|
1
1
|
module ZendeskAppsSupport
|
2
2
|
module Validations
|
3
3
|
module Templates
|
4
|
-
|
5
4
|
class <<self
|
6
5
|
def call(package)
|
7
6
|
errors = []
|
8
7
|
package.template_files.each do |template|
|
9
8
|
contents = template.read
|
10
9
|
if contents =~ /<\s*style\b/
|
11
|
-
errors << ValidationError.new(:style_in_template, :
|
10
|
+
errors << ValidationError.new(:style_in_template, template: template.relative_path)
|
12
11
|
end
|
13
12
|
end
|
14
13
|
errors
|
15
14
|
end
|
16
15
|
end
|
17
|
-
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|
@@ -23,35 +23,35 @@ module ZendeskAppsSupport
|
|
23
23
|
|
24
24
|
def locale_error(file, locale)
|
25
25
|
return nil if VALID_LOCALE =~ locale
|
26
|
-
ValidationError.new('translation.invalid_locale', :
|
26
|
+
ValidationError.new('translation.invalid_locale', file: file.relative_path)
|
27
27
|
end
|
28
28
|
|
29
29
|
def json_error(file)
|
30
30
|
json = MultiJson.load(file.read)
|
31
|
-
if json.
|
32
|
-
if json[
|
33
|
-
json[
|
31
|
+
if json.is_a?(Hash)
|
32
|
+
if json['app'] && json['app']['package']
|
33
|
+
json['app'].delete('package')
|
34
34
|
begin
|
35
35
|
validate_translation_format(json)
|
36
36
|
return
|
37
37
|
rescue TranslationFormatError => e
|
38
|
-
ValidationError.new('translation.invalid_format', :
|
38
|
+
ValidationError.new('translation.invalid_format', field: e.message)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
else
|
42
|
-
ValidationError.new('translation.not_json_object', :
|
42
|
+
ValidationError.new('translation.not_json_object', file: file.relative_path)
|
43
43
|
end
|
44
44
|
rescue MultiJson::DecodeError => e
|
45
|
-
ValidationError.new('translation.not_json', :
|
45
|
+
ValidationError.new('translation.not_json', file: file.relative_path, errors: e)
|
46
46
|
end
|
47
47
|
|
48
48
|
def validate_translation_format(json)
|
49
49
|
json.keys.each do |key|
|
50
|
-
|
50
|
+
fail TranslationFormatError.new("'#{key}': '#{json[key]}'") unless json[key].is_a? Hash
|
51
51
|
|
52
52
|
if json[key].keys.sort == BuildTranslation::I18N_KEYS &&
|
53
|
-
|
54
|
-
|
53
|
+
json[key][BuildTranslation::I18N_TITLE_KEY].class == String &&
|
54
|
+
json[key][BuildTranslation::I18N_VALUE_KEY].class == String
|
55
55
|
next
|
56
56
|
else
|
57
57
|
validate_translation_format(json[key])
|
@@ -2,7 +2,6 @@ require 'multi_json'
|
|
2
2
|
|
3
3
|
module ZendeskAppsSupport
|
4
4
|
module Validations
|
5
|
-
|
6
5
|
class ValidationError
|
7
6
|
KEY_PREFIX = 'txt.apps.admin.error.app_build.'.freeze
|
8
7
|
|
@@ -13,20 +12,19 @@ module ZendeskAppsSupport
|
|
13
12
|
end
|
14
13
|
|
15
14
|
class << self
|
16
|
-
|
17
15
|
# Turn a JSON string into a ValidationError.
|
18
16
|
def from_json(json)
|
19
17
|
hash = MultiJson.decode(json)
|
20
|
-
|
18
|
+
fail DeserializationError.new(json) unless hash.is_a?(Hash)
|
21
19
|
from_hash(hash)
|
22
20
|
rescue MultiJson::DecodeError, NameError
|
23
21
|
raise DeserializationError.new(json)
|
24
22
|
end
|
25
23
|
|
26
24
|
def from_hash(hash)
|
27
|
-
|
25
|
+
fail DeserializationError.new(hash) unless hash['class']
|
28
26
|
klass = constantize(hash['class'])
|
29
|
-
|
27
|
+
fail DeserializationError.new(hash) unless klass <= self
|
30
28
|
klass.vivify(hash)
|
31
29
|
end
|
32
30
|
|
@@ -38,7 +36,7 @@ module ZendeskAppsSupport
|
|
38
36
|
private
|
39
37
|
|
40
38
|
def constantize(klass)
|
41
|
-
klass.to_s.split('::').inject(Object) { |klass, part| klass
|
39
|
+
klass.to_s.split('::').inject(Object) { |klass, part| klass.const_get(part) }
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
@@ -52,11 +50,11 @@ module ZendeskAppsSupport
|
|
52
50
|
ZendeskAppsSupport::I18n.t("#{KEY_PREFIX}#{key}", data)
|
53
51
|
end
|
54
52
|
|
55
|
-
def to_json(*
|
53
|
+
def to_json(*)
|
56
54
|
MultiJson.encode(as_json)
|
57
55
|
end
|
58
56
|
|
59
|
-
def as_json(*
|
57
|
+
def as_json(*)
|
60
58
|
{
|
61
59
|
'class' => self.class.to_s,
|
62
60
|
'key' => key,
|
@@ -85,13 +83,13 @@ module ZendeskAppsSupport
|
|
85
83
|
errors = jshint_errors.compact.map { |err| "\n L#{err['line']}: #{err['reason']}" }.join('')
|
86
84
|
@filename = filename, @jshint_errors = jshint_errors
|
87
85
|
super(:jshint, {
|
88
|
-
:
|
89
|
-
:
|
90
|
-
:
|
86
|
+
file: filename,
|
87
|
+
errors: errors,
|
88
|
+
count: jshint_errors.length
|
91
89
|
})
|
92
90
|
end
|
93
91
|
|
94
|
-
def as_json(*
|
92
|
+
def as_json(*)
|
95
93
|
{
|
96
94
|
'class' => self.class.to_s,
|
97
95
|
'filename' => filename,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zendesk_apps_support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.17.
|
4
|
+
version: 1.17.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James A. Rosen
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-02-
|
14
|
+
date: 2015-02-16 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: i18n
|
@@ -131,14 +131,14 @@ dependencies:
|
|
131
131
|
requirements:
|
132
132
|
- - "~>"
|
133
133
|
- !ruby/object:Gem::Version
|
134
|
-
version:
|
134
|
+
version: 3.1.0
|
135
135
|
type: :development
|
136
136
|
prerelease: false
|
137
137
|
version_requirements: !ruby/object:Gem::Requirement
|
138
138
|
requirements:
|
139
139
|
- - "~>"
|
140
140
|
- !ruby/object:Gem::Version
|
141
|
-
version:
|
141
|
+
version: 3.1.0
|
142
142
|
- !ruby/object:Gem::Dependency
|
143
143
|
name: bump
|
144
144
|
requirement: !ruby/object:Gem::Requirement
|