class ZendeskAppsSupport::Package

Constants

DEFAULT_LAYOUT
DEFAULT_SCSS
LEGACY_URI_STUB
REQUIREMENTS_FILENAME
SRC_TEMPLATE

Attributes

lib_root[R]
root[R]
warnings[R]

Public Class Methods

new(dir, is_cached = true) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 20
def initialize(dir, is_cached = true)
  @root     = Pathname.new(File.expand_path(dir))
  @lib_root = Pathname.new(File.join(root, 'lib'))

  @is_cached = is_cached # disabled by ZAT for development
  @warnings = []
end

Public Instance Methods

app_css() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 203
def app_css
  css_file = path_to('app.css')
  scss_file = path_to('app.scss')
  File.exist?(scss_file) ? File.read(scss_file) : ( File.exist?(css_file) ? File.read(css_file) : '' )
end
assets() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 64
def assets
  @assets ||= Dir.chdir(root) do
    Dir['assets/**/*'].select { |f| File.file?(f) }
  end
end
compile_js(options) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 109
def compile_js(options)
  begin
    app_id = options.fetch(:app_id)
    asset_url_prefix = options.fetch(:assets_dir)
    name = options.fetch(:app_name)
  rescue KeyError => e
    raise ArgumentError, e.message
  end

  locale = options.fetch(:locale, 'en')

  source = iframe_only? ? nil : app_js
  version = manifest_json['version']
  app_class_name = "app-#{app_id}"
  author = manifest_json['author']
  framework_version = manifest_json['frameworkVersion']
  single_install = manifest_json['singleInstall'] || false
  templates = is_no_template ? {} : compiled_templates(app_id, asset_url_prefix)

  app_settings = {
    location: locations,
    noTemplate: no_template_locations,
    singleInstall: single_install
  }.select { |_k, v| !v.nil? }

  SRC_TEMPLATE.result(
    name: name,
    version: version,
    is_es2015: !!manifest_json['es2015'],
    source: source,
    app_settings: app_settings,
    asset_url_prefix: asset_url_prefix,
    app_class_name: app_class_name,
    author: author,
    translations: translations_for(locale),
    framework_version: framework_version,
    templates: templates,
    modules: commonjs_modules,
    iframe_only: iframe_only?
  )
end
compiled_templates(app_id, asset_url_prefix) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 176
def compiled_templates(app_id, asset_url_prefix)
  compiled_css = ZendeskAppsSupport::StylesheetCompiler.new(DEFAULT_SCSS + app_css, app_id, asset_url_prefix).compile

  layout = templates['layout'] || DEFAULT_LAYOUT.result

  templates.tap do |templates|
    templates['layout'] = "<style>\n#{compiled_css}</style>\n#{layout}"
  end
end
files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 82
def files
  files = []
  Dir[root.join('**/**')].each do |f|
    next unless File.file?(f)
    relative_file_name = f.sub(/#{root}\/?/, '')
    next if relative_file_name =~ /^tmp\//
    files << AppFile.new(self, relative_file_name)
  end
  files
end
has_file?(path) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 199
def has_file?(path)
  File.exist?(path_to(path))
end
has_location?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 195
def has_location?
  manifest_json['location']
end
iframe_only?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 223
def iframe_only?
  !legacy_non_iframe_app?
end
is_no_template() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 160
def is_no_template
  if manifest_json['noTemplate'].is_a?(Array)
    false
  else
    !!manifest_json['noTemplate']
  end
end
js_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 93
def js_files
  @js_files ||= files.select { |f| f.to_s == 'app.js' || ( f.to_s.start_with?('lib/') && f.to_s.end_with?('.js') ) }
end
lib_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 97
def lib_files
  @lib_files ||= js_files.select { |f| f =~ /^lib\// }
end
locales() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 78
def locales
  translations.keys
end
locations() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 209
def locations
  locations = manifest_json['location']
  case locations
  when Hash
    locations
  when Array
    { 'zendesk' => Hash[locations.map { |location| [ location, LEGACY_URI_STUB ] }] }
  when String
    { 'zendesk' => { locations => LEGACY_URI_STUB } }
  else # NilClass
    { 'zendesk' => {} }
  end
end
manifest_json() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 151
def manifest_json
  @manifest ||= read_json('manifest.json')
end
market_translations!(locale) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 186
def market_translations!(locale)
  result = translations[locale].fetch('app', {})
  result.delete('name')
  result.delete('description')
  result.delete('long_description')
  result.delete('installation_instructions')
  result
end
no_template_locations() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 168
def no_template_locations
  if manifest_json['noTemplate'].is_a?(Array)
    manifest_json['noTemplate']
  else
    !!manifest_json['noTemplate']
  end
end
path_to(file) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 70
def path_to(file)
  File.join(root, file)
end
requirements_json() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 155
def requirements_json
  return nil unless has_requirements?
  @requirements ||= read_json('requirements.json')
end
requirements_path() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 74
def requirements_path
  path_to(REQUIREMENTS_FILENAME)
end
template_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 101
def template_files
  files.select { |f| f =~ /^templates\/.*\.hdbs$/ }
end
translation_files() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 105
def translation_files
  files.select { |f| f =~ /^translations\// }
end
validate(marketplace: true) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 28
def validate(marketplace: true)
  [].tap do |errors|
    errors << Validations::Marketplace.call(self) if marketplace

    errors << Validations::Manifest.call(self)

    if has_manifest?
      errors << Validations::Source.call(self)
      errors << Validations::Translations.call(self)

      unless manifest_json['requirementsOnly']
        errors << Validations::Templates.call(self)
        errors << Validations::Stylesheets.call(self)
      end

      if has_requirements?
        errors << Validations::Requirements.call(self)
      end
    end

    if has_banner?
      errors << Validations::Banner.call(self)
    end

    errors.flatten!.compact!
  end
end
validate!(marketplace: true) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 56
def validate!(marketplace: true)
  errors = validate(marketplace: marketplace)
  if errors.any?
    raise errors.first
  end
  true
end

Private Instance Methods

app_js() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 297
def app_js
  transpile(read_file('app.js'))
end
commonjs_modules() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 305
def commonjs_modules
  return {} unless has_lib_js?

  lib_files.each_with_object({}) do |file, modules|
    raise Validations::ValidationError.new('reserved_filename') if file.relative_path == 'lib/_root.js'
    name          = file.relative_path.gsub(/^lib\//, '')
    content       = file.read
    modules[name] = transpile(content)
  end
end
deep_merge_hash(h, another_h) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 316
def deep_merge_hash(h, another_h)
  result_h = h.dup
  another_h.each do |key, value|
    if h.has_key?(key) && h[key].is_a?(Hash) && value.is_a?(Hash)
      result_h[key] = deep_merge_hash(h[key], value)
    else
      result_h[key] = value
    end
  end
  result_h
end
has_banner?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 293
def has_banner?
  has_file?('assets/banner.png')
end
has_lib_js?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 281
def has_lib_js?
  lib_files.any?
end
has_manifest?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 285
def has_manifest?
  has_file?('manifest.json')
end
has_requirements?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 289
def has_requirements?
  has_file?('requirements.json')
end
legacy_non_iframe_app?() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 229
def legacy_non_iframe_app?
  iframe_urls = locations.values.flat_map(&:values)
  iframe_urls.all? { |l| l == LEGACY_URI_STUB }
end
process_translations(locale_path) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 275
def process_translations(locale_path)
  translations = File.exist?(locale_path) ? JSON.parse(File.read(locale_path)) : {}
  translations['app'].delete('package') if translations.has_key?('app')
  remove_zendesk_keys(translations)
end
read_file(path) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 328
def read_file(path)
  File.read(path_to(path))
end
read_json(path) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 332
def read_json(path)
  file = read_file(path)
  unless file.nil?
    JSON.parse(file)
  end
end
templates() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 234
def templates
  templates_dir = File.join(root, 'templates')
  Dir["#{templates_dir}/*.hdbs"].inject({}) do |memo, file|
    str = File.read(file)
    str.chomp!
    memo[File.basename(file, File.extname(file))] = str
    memo
  end
end
translations() click to toggle source
# File lib/zendesk_apps_support/package.rb, line 250
def translations
  return @translations if @is_cached && @translations

  @translations = begin
    translation_dir = File.join(root, 'translations')
    return {} unless File.directory?(translation_dir)

    locale_path = "#{translation_dir}/#{self.manifest_json['defaultLocale']}.json"
    default_translations = process_translations(locale_path)

    Dir["#{translation_dir}/*.json"].inject({}) do |memo, path|
      locale = File.basename(path, File.extname(path))

      locale_translations = if locale == self.manifest_json['defaultLocale']
        default_translations
      else
        deep_merge_hash(default_translations, process_translations(path))
      end

      memo[locale] = locale_translations
      memo
    end
  end
end
translations_for(locale) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 244
def translations_for(locale)
  trans = translations
  return trans[locale] if trans[locale]
  trans[self.manifest_json['defaultLocale']]
end
transpile(code) click to toggle source
# File lib/zendesk_apps_support/package.rb, line 301
def transpile(code)
  manifest_json['es2015'] ? Babel::Transpiler.transform(code)['code'] : code
end