dxw-zendesk_apps_support 4.29.5

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 +353 -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,353 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dxw-zendesk_apps_support
3
+ version: !ruby/object:Gem::Version
4
+ version: 4.29.5
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: 2021-02-03 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: '0'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
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: 2.0.2
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: 2.0.2
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
+ - - "<"
108
+ - !ruby/object:Gem::Version
109
+ version: 2.10.0
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 2.2.3
117
+ - - "<"
118
+ - !ruby/object:Gem::Version
119
+ version: 2.10.0
120
+ - !ruby/object:Gem::Dependency
121
+ name: nokogiri
122
+ requirement: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: 1.8.5
127
+ - - "<"
128
+ - !ruby/object:Gem::Version
129
+ version: 1.12.0
130
+ type: :runtime
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: 1.8.5
137
+ - - "<"
138
+ - !ruby/object:Gem::Version
139
+ version: 1.12.0
140
+ - !ruby/object:Gem::Dependency
141
+ name: rb-inotify
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - '='
145
+ - !ruby/object:Gem::Version
146
+ version: 0.9.10
147
+ type: :runtime
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - '='
152
+ - !ruby/object:Gem::Version
153
+ version: 0.9.10
154
+ - !ruby/object:Gem::Dependency
155
+ name: mimemagic
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - "~>"
159
+ - !ruby/object:Gem::Version
160
+ version: 0.3.3
161
+ type: :runtime
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: 0.3.3
168
+ - !ruby/object:Gem::Dependency
169
+ name: ipaddress_2
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - "~>"
173
+ - !ruby/object:Gem::Version
174
+ version: 0.13.0
175
+ type: :runtime
176
+ prerelease: false
177
+ version_requirements: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - "~>"
180
+ - !ruby/object:Gem::Version
181
+ version: 0.13.0
182
+ - !ruby/object:Gem::Dependency
183
+ name: rake
184
+ requirement: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - "~>"
187
+ - !ruby/object:Gem::Version
188
+ version: 13.0.0
189
+ type: :development
190
+ prerelease: false
191
+ version_requirements: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - "~>"
194
+ - !ruby/object:Gem::Version
195
+ version: 13.0.0
196
+ - !ruby/object:Gem::Dependency
197
+ name: rspec
198
+ requirement: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - "~>"
201
+ - !ruby/object:Gem::Version
202
+ version: 3.4.0
203
+ type: :development
204
+ prerelease: false
205
+ version_requirements: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - "~>"
208
+ - !ruby/object:Gem::Version
209
+ version: 3.4.0
210
+ - !ruby/object:Gem::Dependency
211
+ name: bump
212
+ requirement: !ruby/object:Gem::Requirement
213
+ requirements:
214
+ - - "~>"
215
+ - !ruby/object:Gem::Version
216
+ version: 0.5.1
217
+ type: :development
218
+ prerelease: false
219
+ version_requirements: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - "~>"
222
+ - !ruby/object:Gem::Version
223
+ version: 0.5.1
224
+ - !ruby/object:Gem::Dependency
225
+ name: faker
226
+ requirement: !ruby/object:Gem::Requirement
227
+ requirements:
228
+ - - "~>"
229
+ - !ruby/object:Gem::Version
230
+ version: 1.6.6
231
+ type: :development
232
+ prerelease: false
233
+ version_requirements: !ruby/object:Gem::Requirement
234
+ requirements:
235
+ - - "~>"
236
+ - !ruby/object:Gem::Version
237
+ version: 1.6.6
238
+ - !ruby/object:Gem::Dependency
239
+ name: rubocop
240
+ requirement: !ruby/object:Gem::Requirement
241
+ requirements:
242
+ - - "~>"
243
+ - !ruby/object:Gem::Version
244
+ version: 0.52.0
245
+ type: :development
246
+ prerelease: false
247
+ version_requirements: !ruby/object:Gem::Requirement
248
+ requirements:
249
+ - - "~>"
250
+ - !ruby/object:Gem::Version
251
+ version: 0.52.0
252
+ - !ruby/object:Gem::Dependency
253
+ name: byebug
254
+ requirement: !ruby/object:Gem::Requirement
255
+ requirements:
256
+ - - "~>"
257
+ - !ruby/object:Gem::Version
258
+ version: 9.0.6
259
+ type: :development
260
+ prerelease: false
261
+ version_requirements: !ruby/object:Gem::Requirement
262
+ requirements:
263
+ - - "~>"
264
+ - !ruby/object:Gem::Version
265
+ version: 9.0.6
266
+ - !ruby/object:Gem::Dependency
267
+ name: bundler
268
+ requirement: !ruby/object:Gem::Requirement
269
+ requirements:
270
+ - - '='
271
+ - !ruby/object:Gem::Version
272
+ version: 1.17.3
273
+ type: :development
274
+ prerelease: false
275
+ version_requirements: !ruby/object:Gem::Requirement
276
+ requirements:
277
+ - - '='
278
+ - !ruby/object:Gem::Version
279
+ version: 1.17.3
280
+ description: Support to help you develop Zendesk Apps.
281
+ email:
282
+ - dev@zendesk.com
283
+ executables: []
284
+ extensions: []
285
+ extra_rdoc_files: []
286
+ files:
287
+ - LICENSE
288
+ - README.md
289
+ - config/locales/en.yml
290
+ - config/locales/translations/zendesk_apps_support.yml
291
+ - lib/zendesk_apps_support.rb
292
+ - lib/zendesk_apps_support/app_file.rb
293
+ - lib/zendesk_apps_support/app_requirement.rb
294
+ - lib/zendesk_apps_support/app_version.rb
295
+ - lib/zendesk_apps_support/assets/default_app_logo.svg
296
+ - lib/zendesk_apps_support/assets/default_styles.scss
297
+ - lib/zendesk_apps_support/assets/default_template.html.erb
298
+ - lib/zendesk_apps_support/assets/installed.js.erb
299
+ - lib/zendesk_apps_support/assets/src.js.erb
300
+ - lib/zendesk_apps_support/build_translation.rb
301
+ - lib/zendesk_apps_support/engine.rb
302
+ - lib/zendesk_apps_support/finders.rb
303
+ - lib/zendesk_apps_support/i18n.rb
304
+ - lib/zendesk_apps_support/installation.rb
305
+ - lib/zendesk_apps_support/installed.rb
306
+ - lib/zendesk_apps_support/location.rb
307
+ - lib/zendesk_apps_support/manifest.rb
308
+ - lib/zendesk_apps_support/manifest/location_options.rb
309
+ - lib/zendesk_apps_support/manifest/no_override_hash.rb
310
+ - lib/zendesk_apps_support/manifest/parameter.rb
311
+ - lib/zendesk_apps_support/package.rb
312
+ - lib/zendesk_apps_support/product.rb
313
+ - lib/zendesk_apps_support/sass_functions.rb
314
+ - lib/zendesk_apps_support/stylesheet_compiler.rb
315
+ - lib/zendesk_apps_support/validations/banner.rb
316
+ - lib/zendesk_apps_support/validations/manifest.rb
317
+ - lib/zendesk_apps_support/validations/marketplace.rb
318
+ - lib/zendesk_apps_support/validations/mime.rb
319
+ - lib/zendesk_apps_support/validations/requests.rb
320
+ - lib/zendesk_apps_support/validations/requirements.rb
321
+ - lib/zendesk_apps_support/validations/secrets.rb
322
+ - lib/zendesk_apps_support/validations/secure_settings.rb
323
+ - lib/zendesk_apps_support/validations/source.rb
324
+ - lib/zendesk_apps_support/validations/stylesheets.rb
325
+ - lib/zendesk_apps_support/validations/svg.rb
326
+ - lib/zendesk_apps_support/validations/templates.rb
327
+ - lib/zendesk_apps_support/validations/translations.rb
328
+ - lib/zendesk_apps_support/validations/validation_error.rb
329
+ homepage: http://github.com/zendesk/zendesk_apps_support
330
+ licenses:
331
+ - Apache License Version 2.0
332
+ metadata: {}
333
+ post_install_message:
334
+ rdoc_options: []
335
+ require_paths:
336
+ - lib
337
+ required_ruby_version: !ruby/object:Gem::Requirement
338
+ requirements:
339
+ - - ">="
340
+ - !ruby/object:Gem::Version
341
+ version: '2.0'
342
+ required_rubygems_version: !ruby/object:Gem::Requirement
343
+ requirements:
344
+ - - ">="
345
+ - !ruby/object:Gem::Version
346
+ version: 1.3.6
347
+ requirements: []
348
+ rubyforge_project:
349
+ rubygems_version: 2.7.6.2
350
+ signing_key:
351
+ specification_version: 4
352
+ summary: Support to help you develop Zendesk Apps.
353
+ test_files: []