zendesk_apps_support 4.29.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +176 -0
  3. data/README.md +39 -0
  4. data/config/locales/en.yml +163 -0
  5. data/config/locales/translations/zendesk_apps_support.yml +405 -0
  6. data/lib/zendesk_apps_support.rb +42 -0
  7. data/lib/zendesk_apps_support/app_file.rb +44 -0
  8. data/lib/zendesk_apps_support/app_requirement.rb +11 -0
  9. data/lib/zendesk_apps_support/app_version.rb +78 -0
  10. data/lib/zendesk_apps_support/assets/default_app_logo.svg +10 -0
  11. data/lib/zendesk_apps_support/assets/default_styles.scss +3 -0
  12. data/lib/zendesk_apps_support/assets/default_template.html.erb +10 -0
  13. data/lib/zendesk_apps_support/assets/installed.js.erb +21 -0
  14. data/lib/zendesk_apps_support/assets/src.js.erb +37 -0
  15. data/lib/zendesk_apps_support/build_translation.rb +51 -0
  16. data/lib/zendesk_apps_support/engine.rb +11 -0
  17. data/lib/zendesk_apps_support/finders.rb +36 -0
  18. data/lib/zendesk_apps_support/i18n.rb +31 -0
  19. data/lib/zendesk_apps_support/installation.rb +22 -0
  20. data/lib/zendesk_apps_support/installed.rb +27 -0
  21. data/lib/zendesk_apps_support/location.rb +71 -0
  22. data/lib/zendesk_apps_support/manifest.rb +197 -0
  23. data/lib/zendesk_apps_support/manifest/location_options.rb +35 -0
  24. data/lib/zendesk_apps_support/manifest/no_override_hash.rb +50 -0
  25. data/lib/zendesk_apps_support/manifest/parameter.rb +23 -0
  26. data/lib/zendesk_apps_support/package.rb +402 -0
  27. data/lib/zendesk_apps_support/product.rb +31 -0
  28. data/lib/zendesk_apps_support/sass_functions.rb +43 -0
  29. data/lib/zendesk_apps_support/stylesheet_compiler.rb +38 -0
  30. data/lib/zendesk_apps_support/validations/banner.rb +35 -0
  31. data/lib/zendesk_apps_support/validations/manifest.rb +412 -0
  32. data/lib/zendesk_apps_support/validations/marketplace.rb +31 -0
  33. data/lib/zendesk_apps_support/validations/mime.rb +41 -0
  34. data/lib/zendesk_apps_support/validations/requests.rb +47 -0
  35. data/lib/zendesk_apps_support/validations/requirements.rb +154 -0
  36. data/lib/zendesk_apps_support/validations/secrets.rb +77 -0
  37. data/lib/zendesk_apps_support/validations/secure_settings.rb +37 -0
  38. data/lib/zendesk_apps_support/validations/source.rb +25 -0
  39. data/lib/zendesk_apps_support/validations/stylesheets.rb +28 -0
  40. data/lib/zendesk_apps_support/validations/svg.rb +81 -0
  41. data/lib/zendesk_apps_support/validations/templates.rb +20 -0
  42. data/lib/zendesk_apps_support/validations/translations.rb +160 -0
  43. data/lib/zendesk_apps_support/validations/validation_error.rb +77 -0
  44. metadata +327 -0
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'loofah'
4
+
5
+ module ZendeskAppsSupport
6
+ module Validations
7
+ module Svg
8
+ PLACEHOLDER_SVG_MARKUP = File.read(File.expand_path('../../assets/default_app_logo.svg', __FILE__))
9
+
10
+ # whitelist elements and attributes used in Zendesk Garden assets
11
+ Loofah::HTML5::WhiteList::ALLOWED_ELEMENTS_WITH_LIBXML2.add 'symbol'
12
+ Loofah::HTML5::WhiteList::ACCEPTABLE_CSS_PROPERTIES.add 'position'
13
+
14
+ # CRUFT: ignore a (very specific) style attribute which Loofah would otherwise scrub.
15
+ # This attribute is deprecated (https://www.w3.org/TR/filter-effects/#AccessBackgroundImage)
16
+ # but is included in many of the test apps used in fixtures for tests in ZAM, ZAT etc.
17
+ Loofah::HTML5::WhiteList::ACCEPTABLE_CSS_PROPERTIES.add 'enable-background'
18
+
19
+ @strip_declaration = Loofah::Scrubber.new do |node|
20
+ node.remove if node.name == 'xml' && node.children.empty?
21
+ end
22
+
23
+ # Loofah's default scrubber strips spaces between CSS attributes. Passing the input markup through this scrubber
24
+ # first ensures that this stripped whitespace in the output doesn't register as a diff.
25
+ @strip_spaces_between_css_attrs = Loofah::Scrubber.new do |node|
26
+ match_pattern = Regexp.new(/\;\s+/)
27
+ if node.name == 'svg' && node['style']
28
+ node['style'] = node['style'].gsub(match_pattern, ';')
29
+ end
30
+ end
31
+
32
+ @empty_malformed_markup = Loofah::Scrubber.new do |node|
33
+ node.next.remove while node.name == 'svg' && node.next
34
+ end
35
+
36
+ class << self
37
+ def contains_embedded_bitmap?(markup)
38
+ Nokogiri::XML(markup).css('//image').any?
39
+ end
40
+
41
+ def rewrite_svg(svg, new_markup, package, errors)
42
+ warning_string = if contains_embedded_bitmap?(svg.read)
43
+ 'txt.apps.admin.warning.app_build.bitmap_in_svg'
44
+ else
45
+ 'txt.apps.admin.warning.app_build.sanitised_svg'
46
+ end
47
+
48
+ package.warnings << I18n.t(warning_string, svg: svg.relative_path)
49
+ compressed_new_markup = new_markup.tr("\n", '').squeeze(' ').gsub(/\>\s+\</, '><')
50
+ IO.write(svg.absolute_path, compressed_new_markup)
51
+ rescue
52
+ errors << ValidationError.new(:dirty_svg, svg: svg.relative_path)
53
+ end
54
+
55
+ def call(package)
56
+ errors = []
57
+
58
+ package.svg_files.each do |svg|
59
+ if contains_embedded_bitmap?(svg.read)
60
+ rewrite_svg(svg, PLACEHOLDER_SVG_MARKUP, package, errors)
61
+ else
62
+ markup = Loofah.xml_fragment(svg.read)
63
+ .scrub!(@strip_declaration)
64
+ .scrub!(@strip_spaces_between_css_attrs)
65
+ .to_xml.strip
66
+
67
+ clean_markup = Loofah.xml_fragment(markup)
68
+ .scrub!(:prune)
69
+ .scrub!(@empty_malformed_markup)
70
+ .to_xml
71
+
72
+ next if clean_markup == markup
73
+ rewrite_svg(svg, clean_markup, package, errors)
74
+ end
75
+ end
76
+ errors
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ZendeskAppsSupport
4
+ module Validations
5
+ module Templates
6
+ class <<self
7
+ def call(package)
8
+ errors = []
9
+ package.template_files.each do |template|
10
+ contents = template.read
11
+ if contents =~ /<\s*style\b/
12
+ errors << ValidationError.new(:style_in_template, template: template.relative_path)
13
+ end
14
+ end
15
+ errors
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module ZendeskAppsSupport
6
+ module Validations
7
+ module Translations
8
+ TRANSLATIONS_PATH = %r{^translations/(.*)\.json$}
9
+ VALID_LOCALE = /^[a-z]{2}(-\w{2,3})?$/
10
+
11
+ class TranslationFormatError < StandardError
12
+ end
13
+
14
+ class << self
15
+ def call(package, opts = {})
16
+ package.files.each_with_object([]) do |file, errors|
17
+ path_match = TRANSLATIONS_PATH.match(file.relative_path)
18
+ next unless path_match
19
+ errors << locale_error(file, path_match[1]) << json_error(file) << format_error(file)
20
+ next unless errors.compact.empty?
21
+ if file.relative_path == 'translations/en.json'
22
+ # rubocop:disable Metrics/LineLength
23
+ errors.push(*validate_marketplace_content(file, package, opts.fetch(:skip_marketplace_translations, false)))
24
+ end
25
+ end.compact
26
+ end
27
+
28
+ private
29
+
30
+ def locale_error(file, locale)
31
+ return nil if VALID_LOCALE =~ locale
32
+ ValidationError.new('translation.invalid_locale', file: file.relative_path)
33
+ end
34
+
35
+ def format_error(file)
36
+ with_valid_json(file) do |json|
37
+ if json['app'] && json['app']['parameters']
38
+ parameters_node = json['app']['parameters']
39
+ parameters_node.keys.map do |param|
40
+ unless parameters_node[param].is_a?(Hash) && parameters_node[param].keys.include?('label')
41
+ return ValidationError.new('translation.missing_required_key_on_leaf',
42
+ file: file.relative_path, missing_key: 'label', leaf: param)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ nil
48
+ end
49
+
50
+ def json_error(file)
51
+ with_valid_json(file) do |json|
52
+ if json['app'] && json['app']['package']
53
+ json['app'].delete('package')
54
+ begin
55
+ validate_translation_format(json)
56
+ return
57
+ rescue TranslationFormatError => e
58
+ ValidationError.new('translation.invalid_format', field: e.message)
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ def with_valid_json(file)
65
+ json = JSON.parse(file.read)
66
+ if json.is_a?(Hash)
67
+ yield json
68
+ else
69
+ ValidationError.new('translation.not_json_object', file: file.relative_path)
70
+ end
71
+ rescue JSON::ParserError => e
72
+ ValidationError.new('translation.not_json', file: file.relative_path, errors: e)
73
+ end
74
+
75
+ def validate_marketplace_content(file, package, skip_marketplace_translations)
76
+ errors = []
77
+ json = JSON.parse(file.read)
78
+ product_names = Product::PRODUCTS_AVAILABLE.map(&:name)
79
+ present_product_keys = json['app'].is_a?(Hash) ? json['app'].keys & product_names : []
80
+ skip_marketplace_strings = package.manifest.private? || skip_marketplace_translations
81
+
82
+ if present_product_keys.empty?
83
+ errors << validate_top_level_required_keys(json, file.relative_path, skip_marketplace_strings)
84
+ else
85
+ errors << validate_products_match_manifest_products(present_product_keys, package, file.relative_path)
86
+ errors << validate_products_have_required_keys(
87
+ json,
88
+ present_product_keys,
89
+ file.relative_path,
90
+ skip_marketplace_strings
91
+ )
92
+ end
93
+ errors.compact
94
+ end
95
+
96
+ def validate_top_level_required_keys(json, file_path, skip_marketplace_strings)
97
+ keys = json['app'].is_a?(Hash) ? json['app'].keys : []
98
+ missing_keys = get_missing_keys(keys, skip_marketplace_strings)
99
+ return if missing_keys.empty?
100
+ ValidationError.new(
101
+ 'translation.missing_required_key',
102
+ file: file_path,
103
+ missing_key: missing_keys.join(', ')
104
+ )
105
+ end
106
+
107
+ def validate_products_have_required_keys(json, products, file_path, skip_marketplace_strings)
108
+ products.each do |product|
109
+ missing_keys = get_missing_keys(json['app'][product].keys, skip_marketplace_strings)
110
+ next if missing_keys.empty?
111
+ return ValidationError.new(
112
+ 'translation.missing_required_key_for_product',
113
+ file: file_path,
114
+ product: product.capitalize,
115
+ missing_key: missing_keys.join(', ')
116
+ )
117
+ end
118
+ nil
119
+ end
120
+
121
+ def validate_products_match_manifest_products(products, package, file_path)
122
+ manifest_products = package.manifest.products.map(&:name)
123
+ return if (products - manifest_products).empty?
124
+ ValidationError.new(
125
+ 'translation.products_do_not_match_manifest_products',
126
+ file: file_path,
127
+ translation_products: products.map(&:capitalize).join(', '),
128
+ manifest_products: manifest_products.map(&:capitalize).join(', ')
129
+ )
130
+ end
131
+
132
+ def validate_translation_format(json)
133
+ json.keys.each do |key|
134
+ raise TranslationFormatError, "'#{key}': '#{json[key]}'" unless json[key].is_a? Hash
135
+
136
+ if json[key].keys.sort == BuildTranslation::I18N_KEYS &&
137
+ json[key][BuildTranslation::I18N_TITLE_KEY].class == String &&
138
+ json[key][BuildTranslation::I18N_VALUE_KEY].class == String
139
+ next
140
+ else
141
+ validate_translation_format(json[key])
142
+ end
143
+ end
144
+ end
145
+
146
+ def get_missing_keys(keys, skip_marketplace_strings)
147
+ public_app_keys = %w[name short_description installation_instructions long_description]
148
+ mandatory_keys = skip_marketplace_strings ? ['name'] : public_app_keys
149
+ # since we support description as well as short_description for backwards compatibility,
150
+ # validate keys as if description == short_description
151
+ keys_to_validate = keys.map do |key|
152
+ key == 'description' ? 'short_description' : key
153
+ end
154
+
155
+ mandatory_keys - keys_to_validate
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module ZendeskAppsSupport
6
+ module Validations
7
+ class ValidationError < StandardError
8
+ KEY_PREFIX = 'txt.apps.admin.error.app_build.'
9
+
10
+ class DeserializationError < StandardError
11
+ def initialize(serialized)
12
+ super "Cannot deserialize ValidationError from #{serialized}"
13
+ end
14
+ end
15
+
16
+ class << self
17
+ # Turn a JSON string into a ValidationError.
18
+ def from_json(json)
19
+ hash = JSON.parse(json)
20
+ raise DeserializationError, json unless hash.is_a?(Hash)
21
+ from_hash(hash)
22
+ rescue JSON::ParserError, NameError
23
+ raise DeserializationError, json
24
+ end
25
+
26
+ def from_hash(hash)
27
+ raise DeserializationError, hash unless hash['class']
28
+ klass = constantize(hash['class'])
29
+ raise DeserializationError, hash unless klass <= self
30
+ klass.vivify(hash)
31
+ end
32
+
33
+ # Turn a Hash into a ValidationError. Used within from_json.
34
+ def vivify(hash)
35
+ new(hash['key'], hash['data'])
36
+ end
37
+
38
+ private
39
+
40
+ def constantize(klass)
41
+ klass.to_s.split('::').inject(Object) { |superclass, part| superclass.const_get(part) }
42
+ end
43
+ end
44
+
45
+ attr_reader :key, :data
46
+
47
+ def initialize(key, data = nil)
48
+ @key = key
49
+ @data = symbolize_keys(data || {})
50
+ end
51
+
52
+ def to_s
53
+ ZendeskAppsSupport::I18n.t("#{KEY_PREFIX}#{key}", data)
54
+ end
55
+
56
+ def to_json(*)
57
+ JSON.generate(as_json)
58
+ end
59
+
60
+ def as_json(*)
61
+ {
62
+ 'class' => self.class.to_s,
63
+ 'key' => key,
64
+ 'data' => data
65
+ }
66
+ end
67
+
68
+ private
69
+
70
+ def symbolize_keys(hash)
71
+ hash.each_with_object({}) do |(key, value), result|
72
+ result[key.to_sym] = value
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
metadata ADDED
@@ -0,0 +1,327 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zendesk_apps_support
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.29.4
5
+ platform: ruby
6
+ authors:
7
+ - James A. Rosen
8
+ - Likun Liu
9
+ - Sean Caffery
10
+ - Daniel Ribeiro
11
+ autorequire:
12
+ bindir: bin
13
+ cert_chain: []
14
+ date: 2020-07-22 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: i18n
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sassc
32
+ requirement: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: 1.11.2
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: 1.11.2
44
+ - !ruby/object:Gem::Dependency
45
+ name: sass
46
+ requirement: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ - !ruby/object:Gem::Dependency
59
+ name: json
60
+ requirement: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ - !ruby/object:Gem::Dependency
73
+ name: image_size
74
+ requirement: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ - !ruby/object:Gem::Dependency
87
+ name: erubis
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ type: :runtime
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ - !ruby/object:Gem::Dependency
101
+ name: loofah
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - "~>"
105
+ - !ruby/object:Gem::Version
106
+ version: 2.2.3
107
+ type: :runtime
108
+ prerelease: false
109
+ version_requirements: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - "~>"
112
+ - !ruby/object:Gem::Version
113
+ version: 2.2.3
114
+ - !ruby/object:Gem::Dependency
115
+ name: nokogiri
116
+ requirement: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - "~>"
119
+ - !ruby/object:Gem::Version
120
+ version: 1.8.5
121
+ type: :runtime
122
+ prerelease: false
123
+ version_requirements: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - "~>"
126
+ - !ruby/object:Gem::Version
127
+ version: 1.8.5
128
+ - !ruby/object:Gem::Dependency
129
+ name: rb-inotify
130
+ requirement: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - '='
133
+ - !ruby/object:Gem::Version
134
+ version: 0.9.10
135
+ type: :runtime
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - '='
140
+ - !ruby/object:Gem::Version
141
+ version: 0.9.10
142
+ - !ruby/object:Gem::Dependency
143
+ name: mimemagic
144
+ requirement: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - "~>"
147
+ - !ruby/object:Gem::Version
148
+ version: 0.3.3
149
+ type: :runtime
150
+ prerelease: false
151
+ version_requirements: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - "~>"
154
+ - !ruby/object:Gem::Version
155
+ version: 0.3.3
156
+ - !ruby/object:Gem::Dependency
157
+ name: ipaddress_2
158
+ requirement: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - "~>"
161
+ - !ruby/object:Gem::Version
162
+ version: 0.13.0
163
+ type: :runtime
164
+ prerelease: false
165
+ version_requirements: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - "~>"
168
+ - !ruby/object:Gem::Version
169
+ version: 0.13.0
170
+ - !ruby/object:Gem::Dependency
171
+ name: rspec
172
+ requirement: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - "~>"
175
+ - !ruby/object:Gem::Version
176
+ version: 3.4.0
177
+ type: :development
178
+ prerelease: false
179
+ version_requirements: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - "~>"
182
+ - !ruby/object:Gem::Version
183
+ version: 3.4.0
184
+ - !ruby/object:Gem::Dependency
185
+ name: bump
186
+ requirement: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - "~>"
189
+ - !ruby/object:Gem::Version
190
+ version: 0.5.1
191
+ type: :development
192
+ prerelease: false
193
+ version_requirements: !ruby/object:Gem::Requirement
194
+ requirements:
195
+ - - "~>"
196
+ - !ruby/object:Gem::Version
197
+ version: 0.5.1
198
+ - !ruby/object:Gem::Dependency
199
+ name: faker
200
+ requirement: !ruby/object:Gem::Requirement
201
+ requirements:
202
+ - - "~>"
203
+ - !ruby/object:Gem::Version
204
+ version: 1.6.6
205
+ type: :development
206
+ prerelease: false
207
+ version_requirements: !ruby/object:Gem::Requirement
208
+ requirements:
209
+ - - "~>"
210
+ - !ruby/object:Gem::Version
211
+ version: 1.6.6
212
+ - !ruby/object:Gem::Dependency
213
+ name: rubocop
214
+ requirement: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - "~>"
217
+ - !ruby/object:Gem::Version
218
+ version: 0.49.0
219
+ type: :development
220
+ prerelease: false
221
+ version_requirements: !ruby/object:Gem::Requirement
222
+ requirements:
223
+ - - "~>"
224
+ - !ruby/object:Gem::Version
225
+ version: 0.49.0
226
+ - !ruby/object:Gem::Dependency
227
+ name: byebug
228
+ requirement: !ruby/object:Gem::Requirement
229
+ requirements:
230
+ - - "~>"
231
+ - !ruby/object:Gem::Version
232
+ version: 9.0.6
233
+ type: :development
234
+ prerelease: false
235
+ version_requirements: !ruby/object:Gem::Requirement
236
+ requirements:
237
+ - - "~>"
238
+ - !ruby/object:Gem::Version
239
+ version: 9.0.6
240
+ - !ruby/object:Gem::Dependency
241
+ name: bundler
242
+ requirement: !ruby/object:Gem::Requirement
243
+ requirements:
244
+ - - '='
245
+ - !ruby/object:Gem::Version
246
+ version: 1.17.3
247
+ type: :development
248
+ prerelease: false
249
+ version_requirements: !ruby/object:Gem::Requirement
250
+ requirements:
251
+ - - '='
252
+ - !ruby/object:Gem::Version
253
+ version: 1.17.3
254
+ description: Support to help you develop Zendesk Apps.
255
+ email:
256
+ - dev@zendesk.com
257
+ executables: []
258
+ extensions: []
259
+ extra_rdoc_files: []
260
+ files:
261
+ - LICENSE
262
+ - README.md
263
+ - config/locales/en.yml
264
+ - config/locales/translations/zendesk_apps_support.yml
265
+ - lib/zendesk_apps_support.rb
266
+ - lib/zendesk_apps_support/app_file.rb
267
+ - lib/zendesk_apps_support/app_requirement.rb
268
+ - lib/zendesk_apps_support/app_version.rb
269
+ - lib/zendesk_apps_support/assets/default_app_logo.svg
270
+ - lib/zendesk_apps_support/assets/default_styles.scss
271
+ - lib/zendesk_apps_support/assets/default_template.html.erb
272
+ - lib/zendesk_apps_support/assets/installed.js.erb
273
+ - lib/zendesk_apps_support/assets/src.js.erb
274
+ - lib/zendesk_apps_support/build_translation.rb
275
+ - lib/zendesk_apps_support/engine.rb
276
+ - lib/zendesk_apps_support/finders.rb
277
+ - lib/zendesk_apps_support/i18n.rb
278
+ - lib/zendesk_apps_support/installation.rb
279
+ - lib/zendesk_apps_support/installed.rb
280
+ - lib/zendesk_apps_support/location.rb
281
+ - lib/zendesk_apps_support/manifest.rb
282
+ - lib/zendesk_apps_support/manifest/location_options.rb
283
+ - lib/zendesk_apps_support/manifest/no_override_hash.rb
284
+ - lib/zendesk_apps_support/manifest/parameter.rb
285
+ - lib/zendesk_apps_support/package.rb
286
+ - lib/zendesk_apps_support/product.rb
287
+ - lib/zendesk_apps_support/sass_functions.rb
288
+ - lib/zendesk_apps_support/stylesheet_compiler.rb
289
+ - lib/zendesk_apps_support/validations/banner.rb
290
+ - lib/zendesk_apps_support/validations/manifest.rb
291
+ - lib/zendesk_apps_support/validations/marketplace.rb
292
+ - lib/zendesk_apps_support/validations/mime.rb
293
+ - lib/zendesk_apps_support/validations/requests.rb
294
+ - lib/zendesk_apps_support/validations/requirements.rb
295
+ - lib/zendesk_apps_support/validations/secrets.rb
296
+ - lib/zendesk_apps_support/validations/secure_settings.rb
297
+ - lib/zendesk_apps_support/validations/source.rb
298
+ - lib/zendesk_apps_support/validations/stylesheets.rb
299
+ - lib/zendesk_apps_support/validations/svg.rb
300
+ - lib/zendesk_apps_support/validations/templates.rb
301
+ - lib/zendesk_apps_support/validations/translations.rb
302
+ - lib/zendesk_apps_support/validations/validation_error.rb
303
+ homepage: http://github.com/zendesk/zendesk_apps_support
304
+ licenses:
305
+ - Apache License Version 2.0
306
+ metadata: {}
307
+ post_install_message:
308
+ rdoc_options: []
309
+ require_paths:
310
+ - lib
311
+ required_ruby_version: !ruby/object:Gem::Requirement
312
+ requirements:
313
+ - - ">="
314
+ - !ruby/object:Gem::Version
315
+ version: '2.0'
316
+ required_rubygems_version: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - ">="
319
+ - !ruby/object:Gem::Version
320
+ version: 1.3.6
321
+ requirements: []
322
+ rubyforge_project:
323
+ rubygems_version: 2.7.10
324
+ signing_key:
325
+ specification_version: 4
326
+ summary: Support to help you develop Zendesk Apps.
327
+ test_files: []