neofiles 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +1 -0
- data/README.md +417 -0
- data/Rakefile +40 -0
- data/app/assets/images/neofiles/loading.gif +0 -0
- data/app/assets/images/neofiles/swf-thumb-100x100.png +0 -0
- data/app/assets/images/neofiles/watermark.png +0 -0
- data/app/assets/javascripts/neofiles/index.js.coffee +3 -0
- data/app/assets/javascripts/neofiles/jquery.fileupload.js +1128 -0
- data/app/assets/javascripts/neofiles/jquery.iframe-transport.js +172 -0
- data/app/assets/javascripts/neofiles/jquery.neofiles.js.coffee +191 -0
- data/app/assets/stylesheets/neofiles/index.css.scss +3 -0
- data/app/assets/stylesheets/neofiles/neofiles.css.scss +149 -0
- data/app/controllers/concerns/neofiles/not_found.rb +21 -0
- data/app/controllers/neofiles/admin_controller.rb +228 -0
- data/app/controllers/neofiles/admin_test_controller.rb +5 -0
- data/app/controllers/neofiles/files_controller.rb +28 -0
- data/app/controllers/neofiles/images_controller.rb +130 -0
- data/app/helpers/neofiles/neofiles_helper.rb +188 -0
- data/app/models/neofiles/file.rb +319 -0
- data/app/models/neofiles/file_chunk.rb +18 -0
- data/app/models/neofiles/image.rb +119 -0
- data/app/models/neofiles/swf.rb +45 -0
- data/app/views/neofiles/admin/_file_compact.html.haml +85 -0
- data/app/views/neofiles/admin/file_compact.html.haml +1 -0
- data/app/views/neofiles/admin_test/file_compact.erb +7 -0
- data/config/locales/ru.yml +21 -0
- data/config/routes.rb +1 -0
- data/lib/neofiles.rb +94 -0
- data/lib/neofiles/engine.rb +33 -0
- data/lib/neofiles/version.rb +3 -0
- metadata +131 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
# Special case of Neofiles::File for dealing with SWF movies.
|
2
|
+
#
|
3
|
+
# Alongside usual file things, stores width & height of Flash clip.
|
4
|
+
#
|
5
|
+
require_dependency 'image_spec'
|
6
|
+
|
7
|
+
class Neofiles::Swf < Neofiles::File
|
8
|
+
|
9
|
+
class SwfFormatException < Exception; end
|
10
|
+
|
11
|
+
field :width, type: Integer
|
12
|
+
field :height, type: Integer
|
13
|
+
|
14
|
+
before_save :compute_dimensions
|
15
|
+
|
16
|
+
# Return array with width & height decorated with singleton function to_s returning 'WxH' string.
|
17
|
+
def dimensions
|
18
|
+
dim = [width, height]
|
19
|
+
def dim.to_s
|
20
|
+
join 'x'
|
21
|
+
end
|
22
|
+
dim
|
23
|
+
end
|
24
|
+
|
25
|
+
# Overrides parent "admin views" with square 100x100 Flash thumbnail.
|
26
|
+
def admin_compact_view(view_context)
|
27
|
+
view_context.neofiles_link self, view_context.tag(:img, src: view_context.image_path('neofiles/swf-thumb-100x100.png')), target: '_blank'
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Store dimensions on #save.
|
35
|
+
def compute_dimensions
|
36
|
+
return unless @file
|
37
|
+
|
38
|
+
spec = ::ImageSpec.new(@file)
|
39
|
+
if spec.content_type != 'application/x-shockwave-flash'
|
40
|
+
raise SwfFormatException.new I18n.t('neofiles.swf_type_incorrect', content_type: spec.content_type)
|
41
|
+
end
|
42
|
+
self.width = spec.width
|
43
|
+
self.height = spec.height
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
- widget_id ||= input_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, '_').sub(/_$/, '')
|
2
|
+
- desc = file.try(:description).try(:to_s).try!(:strip).try!(:truncate, 15).presence
|
3
|
+
- empty_desc = t 'neofiles.views.no_description'
|
4
|
+
|
5
|
+
- classes = []
|
6
|
+
- classes << 'neofiles-image-compact-empty' unless file
|
7
|
+
- classes << 'neofiles-image-compact-with-description' if file && with_desc
|
8
|
+
.neofiles-image-compact(id=widget_id data-url=neofiles_file_save_path){class: classes}
|
9
|
+
|
10
|
+
- if error.present?
|
11
|
+
%p.neofiles-error
|
12
|
+
= error
|
13
|
+
|
14
|
+
- if file
|
15
|
+
.neofiles-image-compact-view= file.admin_compact_view self
|
16
|
+
|
17
|
+
%a(href=neofiles_file_remove_path class="neofiles-image-compact-remove")
|
18
|
+
%i.icon-remove.glyphicon.glyphicon-remove
|
19
|
+
|
20
|
+
- if Neofiles.is_admin? self
|
21
|
+
- options_form = capture do
|
22
|
+
- if file.description.present?
|
23
|
+
%p= file.description
|
24
|
+
|
25
|
+
%p= t 'neofiles.views.created_at', local_date: l(file.created_at, format: t('neofiles.views.local_date_format'))
|
26
|
+
|
27
|
+
- file_options = []
|
28
|
+
- if file.respond_to? :dimensions
|
29
|
+
- file_options << "#{file.dimensions.join('×').html_safe} px"
|
30
|
+
- file_options << "#{number_to_human_size file.length, precision: 0}"
|
31
|
+
%p= file_options.join(', ')
|
32
|
+
|
33
|
+
- if file.owner_type.present? || file.owner_id.present?
|
34
|
+
%p #{t 'neofiles.views.owner'}: #{file.owner_type}#{file.owner_id}
|
35
|
+
|
36
|
+
- if file.respond_to? :no_wm
|
37
|
+
%p.checkbox
|
38
|
+
- uniq_name = "#{widget_id}_no_wm"
|
39
|
+
%label(for=uniq_name)
|
40
|
+
= check_box_tag uniq_name, '1', file.no_wm, class: 'neofiles-image-compact-nowm', data: {update_url: neofiles_file_update_path}
|
41
|
+
= t 'neofiles.views.no_wm'
|
42
|
+
|
43
|
+
%a(href="#" tabindex="0" class="neofiles-image-compact-options" data-toggle="popover" data-trigger="click" data-placement="top" data-html="true" data-animation="false" data-title="#{file.filename}" data-content=options_form)
|
44
|
+
%i.icon-wrench.glyphicon.glyphicon-wrench
|
45
|
+
|
46
|
+
- if with_desc
|
47
|
+
- description_form = capture do
|
48
|
+
- area_name = "#{widget_id}_description"
|
49
|
+
= text_area_tag area_name, file.description, class: 'neofiles-image-compact-description-input', rows: 10, data: {update_url: neofiles_file_update_path}
|
50
|
+
.text-center
|
51
|
+
%button.btn.btn-primary.btn-small.neofiles-image-compact-description-save= t 'neofiles.views.save'
|
52
|
+
|
53
|
+
- popover_template = capture do
|
54
|
+
.popover.neofiles-image-compact-description-popover(role="tooltip")
|
55
|
+
.arrow
|
56
|
+
%h3.popover-title
|
57
|
+
.popover-content
|
58
|
+
|
59
|
+
.neofiles-image-compact-description
|
60
|
+
%a.neofiles-image-compact-description-handle(href="#" data-empty=empty_desc data-toggle="popover" data-trigger="click" data-placement="bottom" data-html="true" data-animation="false" data-title="#{t 'neofiles.views.description'}" data-content=description_form data-template=popover_template){class: ('neofiles-image-compact-description-empty' unless desc)}= desc || empty_desc
|
61
|
+
|
62
|
+
%span.neofiles-image-compact-upload-icon
|
63
|
+
%i.icon-upload.glyphicon.glyphicon-upload
|
64
|
+
|
65
|
+
- common_options = {id: nil, disabled: disabled}
|
66
|
+
= hidden_field_tag input_name, file.try(:id), common_options.merge(class: 'neofiles-image-transfer-input')
|
67
|
+
= hidden_field_tag 'neofiles[id]', file.try(:id), common_options
|
68
|
+
= hidden_field_tag 'neofiles[input_name]', input_name, common_options
|
69
|
+
= hidden_field_tag 'neofiles[widget_id]', widget_id, common_options
|
70
|
+
|
71
|
+
= hidden_field_tag 'neofiles[clean_remove]', clean_remove ? 1 : 0, common_options
|
72
|
+
= hidden_field_tag 'neofiles[append_create]', file ? 0 : (append_create ? 1 : 0), common_options
|
73
|
+
= hidden_field_tag 'neofiles[multiple]', multiple ? 1 : 0, common_options
|
74
|
+
= hidden_field_tag 'neofiles[with_desc]', with_desc ? 1 : 0, common_options
|
75
|
+
|
76
|
+
= file_field_tag 'neofiles[file][]', id: nil, class: 'neofiles-image-compact-file', disabled: disabled, multiple: multiple && !file
|
77
|
+
|
78
|
+
:javascript
|
79
|
+
$(function() {
|
80
|
+
$("##{widget_id}").image();
|
81
|
+
});
|
82
|
+
|
83
|
+
- if append_create and file
|
84
|
+
= render partial: 'file_compact', locals: {file: nil, input_name: input_name, widget_id: widget_id + '_ap', clean_remove: clean_remove, append_create: true, error: nil, disabled: disabled, multiple: multiple, with_desc: with_desc}
|
85
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
= render partial: 'file_compact', locals: {file: @file, widget_id: @widget_id, input_name: @input_name, error: @error, clean_remove: @clean_remove, append_create: @append_create, disabled: @disabled, multiple: @multiple, with_desc: @with_desc}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
ru:
|
2
|
+
neofiles:
|
3
|
+
403_access_denied: Ошибка 403: недостаточно прав для получения файла в таком формате
|
4
|
+
404_not_found: Ошибка 404: файл не найден
|
5
|
+
file_not_found: Файл не найден
|
6
|
+
data_not_passed: Не переданы данные для сохранения
|
7
|
+
file_not_passed: Не передан файл для сохранения
|
8
|
+
id_not_passed: Не передан ID
|
9
|
+
unknown_file_type: Не могу создать файл неизвестного типа %{type}
|
10
|
+
swf_type_incorrect: Файл с расширением SWF определяется как %{content_type}
|
11
|
+
mini_magick_error: Не могу обработать переданное изображение
|
12
|
+
unsupported_image_type: Формат картинок %{type} не поддерживается
|
13
|
+
|
14
|
+
views:
|
15
|
+
no_description: Без описания
|
16
|
+
local_date_format: %d.%m.%Y <span class="muted text-muted">в %H:%M</span>
|
17
|
+
created_at: Создан %{local_date}
|
18
|
+
owner: Владелец
|
19
|
+
no_wm: не ставить водяной знак
|
20
|
+
save: Сохранить
|
21
|
+
description: Описание
|
data/config/routes.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Neofiles::Engine.routes.draw(&Neofiles.routes_proc)
|
data/lib/neofiles.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'neofiles/engine'
|
2
|
+
|
3
|
+
module Neofiles
|
4
|
+
# Attach Neofiles specific routes in your routes.rb file:
|
5
|
+
#
|
6
|
+
# instance_eval &Neofiles.routes_proc
|
7
|
+
mattr_accessor :routes_proc
|
8
|
+
@@routes_proc = proc do
|
9
|
+
scope 'neofiles', module: :neofiles do
|
10
|
+
# admin routes
|
11
|
+
get '/admin/file_compact/', to: 'admin#file_compact', as: :neofiles_file_compact
|
12
|
+
post '/admin/file_save/', to: 'admin#file_save', as: :neofiles_file_save
|
13
|
+
post '/admin/file_remove/', to: 'admin#file_remove', as: :neofiles_file_remove
|
14
|
+
post '/admin/file_update/', to: 'admin#file_update', as: :neofiles_file_update
|
15
|
+
|
16
|
+
# admin routes for WYSIWYG editor Redactor.js
|
17
|
+
post '/admin/redactor-upload/', to: 'admin#redactor_upload', as: :neofiles_redactor_upload
|
18
|
+
get '/admin/redactor-list/:owner_type/:owner_id/:type', to: 'admin#redactor_list', as: :neofiles_redactor_list
|
19
|
+
|
20
|
+
# web frontend for serving images and other files
|
21
|
+
get '/serve/:id', to: 'files#show', as: :neofiles_file
|
22
|
+
get '/serve-image/:id(/:format(/c:crop)(/q:quality))', to: 'images#show', as: :neofiles_image, constraints: {format: /[1-9]\d*x[1-9]\d*/, crop: /[10]/, quality: /[1-9]\d*/}
|
23
|
+
|
24
|
+
# serve images w/o watermark - path has prefix nowm_ to let Nginx ot other web server not cache these queries,
|
25
|
+
# unlike usual /serve-image/:id
|
26
|
+
get '/nowm-serve-image/:id', to: 'images#show', as: :neofiles_image_nowm, defaults: {nowm: true}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Calculate image dimensions after resize. Returns [w, h] or nil if some info is lacking (e.g. image passed as ID so
|
31
|
+
# no width & height available).
|
32
|
+
#
|
33
|
+
# image_file - Neofiles::Image, ID or Hash
|
34
|
+
# width, height - max width and height after resize
|
35
|
+
# resize_options - {crop: '1'/'0'}, @see Neofiles::ImagesController#show
|
36
|
+
#
|
37
|
+
# Can call ImageMagick.
|
38
|
+
#
|
39
|
+
def resized_image_dimensions(image_file, width, height, resize_options)
|
40
|
+
# dimensions are equal to requested ones if cropping
|
41
|
+
return width, height if crop_requested? resize_options
|
42
|
+
|
43
|
+
# otherwise ask ImageMagick - prepare input vars...
|
44
|
+
image_file = Neofiles::Image.find image_file if image_file.is_a?(String)
|
45
|
+
return nil if image_file.nil?
|
46
|
+
|
47
|
+
if image_file.is_a? Neofiles::Image
|
48
|
+
image_file_width = image_file.width
|
49
|
+
image_file_height = image_file.height
|
50
|
+
else
|
51
|
+
image_file_width = image_file[:width]
|
52
|
+
image_file_height = image_file[:height]
|
53
|
+
end
|
54
|
+
|
55
|
+
return if image_file_width.blank? || image_file_height.blank?
|
56
|
+
|
57
|
+
# ... construct request ...
|
58
|
+
command = MiniMagick::CommandBuilder.new(:convert) # convert input file...
|
59
|
+
command.size([image_file_width, image_file_height].join 'x') # with the given dimensions...
|
60
|
+
command.xc('white') # and filled with whites...
|
61
|
+
command.resize([width, height].join 'x') # to fit in the given rectangle...
|
62
|
+
command.push('info:-') # return info about the resulting file
|
63
|
+
|
64
|
+
# ... and send it to ImageMagick
|
65
|
+
# the result will be: xc:white XC 54x100 54x100+0+0 16-bit DirectClass 0.070u 0:00.119
|
66
|
+
# extract dimensions and return them as array of integers
|
67
|
+
MiniMagick::Image.new(nil, nil).run(command).match(/ (\d+)x(\d+) /).values_at(1, 2).map(&:to_i)
|
68
|
+
|
69
|
+
rescue
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
# Is request params hash contains crop request?
|
74
|
+
def crop_requested?(params)
|
75
|
+
params[:crop].present? and params[:crop] != '0'
|
76
|
+
end
|
77
|
+
|
78
|
+
# Is request params hash contains quality request?
|
79
|
+
def quality_requested?(params)
|
80
|
+
!!quality_requested(params)
|
81
|
+
end
|
82
|
+
|
83
|
+
# The quality value requested, from request params hash.
|
84
|
+
def quality_requested(params)
|
85
|
+
params[:quality].to_i if params[:quality].present? and params[:quality] != '0'
|
86
|
+
end
|
87
|
+
|
88
|
+
# Is current user considered "admin"? "Admin" means the user can fetch images w/o watermarks.
|
89
|
+
def is_admin?(context)
|
90
|
+
Rails.application.config.neofiles.try(:current_admin).try(:call, context)
|
91
|
+
end
|
92
|
+
|
93
|
+
module_function :resized_image_dimensions, :crop_requested?, :quality_requested?, :quality_requested, :is_admin?
|
94
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Neofiles
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
config.autoload_paths << File.expand_path('../..', __FILE__)
|
4
|
+
config.neofiles = ActiveSupport::OrderedOptions.new
|
5
|
+
|
6
|
+
# mongo specific settings
|
7
|
+
config.neofiles.mongo_files_collection = 'files.files'
|
8
|
+
config.neofiles.mongo_chunks_collection = 'files.chunks'
|
9
|
+
config.neofiles.mongo_client = 'neofiles'
|
10
|
+
config.neofiles.mongo_default_chunk_size = 4.megabytes
|
11
|
+
|
12
|
+
# image related settings
|
13
|
+
config.neofiles.image_rotate_exif = true # rotate image, if exif contains orientation info
|
14
|
+
config.neofiles.image_clean_exif = true # clean all exif fields on save
|
15
|
+
config.neofiles.image_max_dimensions = nil # resize huge originals to meaningful size: [w, h], {width: w, height: h}, wh
|
16
|
+
config.neofiles.image_max_crop_width = 2000 # users can request resizing only up to this width
|
17
|
+
config.neofiles.image_max_crop_height = 2000 # users can request resizing only up to this height
|
18
|
+
|
19
|
+
# default watermarker — redefine to set special watermarking logic
|
20
|
+
# by default, watermark only images larger than 300x300 with watermark at the bottom center, taken from file
|
21
|
+
# /app/assets/images/neofiles/watermark.png
|
22
|
+
config.neofiles.watermarker = ->(image, no_watermark: false, watermark_width:, watermark_height:){
|
23
|
+
if watermark_width < 300 || watermark_height < 300 || no_watermark
|
24
|
+
return image.to_blob
|
25
|
+
end
|
26
|
+
|
27
|
+
image.composite(MiniMagick::Image.open(Rails.root.join('app', 'assets', 'images', 'neofiles', 'watermark.png'))) do |c|
|
28
|
+
c.gravity 'south'
|
29
|
+
c.geometry '200x+0+20'
|
30
|
+
end.to_blob
|
31
|
+
}
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: neofiles
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Konanykhin Ilya
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-11-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 4.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 4.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: mongoid
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 5.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 5.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: ruby-imagespec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.4.1
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.4.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mini_magick
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.7.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.7.0
|
69
|
+
description: 'Library for managing files: creating & storing, linking to file owners,
|
70
|
+
serving files from MongoDB'
|
71
|
+
email:
|
72
|
+
- rails@neolabs.kz
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- LICENSE
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- app/assets/images/neofiles/loading.gif
|
81
|
+
- app/assets/images/neofiles/swf-thumb-100x100.png
|
82
|
+
- app/assets/images/neofiles/watermark.png
|
83
|
+
- app/assets/javascripts/neofiles/index.js.coffee
|
84
|
+
- app/assets/javascripts/neofiles/jquery.fileupload.js
|
85
|
+
- app/assets/javascripts/neofiles/jquery.iframe-transport.js
|
86
|
+
- app/assets/javascripts/neofiles/jquery.neofiles.js.coffee
|
87
|
+
- app/assets/stylesheets/neofiles/index.css.scss
|
88
|
+
- app/assets/stylesheets/neofiles/neofiles.css.scss
|
89
|
+
- app/controllers/concerns/neofiles/not_found.rb
|
90
|
+
- app/controllers/neofiles/admin_controller.rb
|
91
|
+
- app/controllers/neofiles/admin_test_controller.rb
|
92
|
+
- app/controllers/neofiles/files_controller.rb
|
93
|
+
- app/controllers/neofiles/images_controller.rb
|
94
|
+
- app/helpers/neofiles/neofiles_helper.rb
|
95
|
+
- app/models/neofiles/file.rb
|
96
|
+
- app/models/neofiles/file_chunk.rb
|
97
|
+
- app/models/neofiles/image.rb
|
98
|
+
- app/models/neofiles/swf.rb
|
99
|
+
- app/views/neofiles/admin/_file_compact.html.haml
|
100
|
+
- app/views/neofiles/admin/file_compact.html.haml
|
101
|
+
- app/views/neofiles/admin_test/file_compact.erb
|
102
|
+
- config/locales/ru.yml
|
103
|
+
- config/routes.rb
|
104
|
+
- lib/neofiles.rb
|
105
|
+
- lib/neofiles/engine.rb
|
106
|
+
- lib/neofiles/version.rb
|
107
|
+
homepage: http://neoweb.kz
|
108
|
+
licenses:
|
109
|
+
- MIT
|
110
|
+
metadata: {}
|
111
|
+
post_install_message:
|
112
|
+
rdoc_options: []
|
113
|
+
require_paths:
|
114
|
+
- lib
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
requirements: []
|
126
|
+
rubyforge_project:
|
127
|
+
rubygems_version: 2.5.1
|
128
|
+
signing_key:
|
129
|
+
specification_version: 4
|
130
|
+
summary: Serves and manages files & images.
|
131
|
+
test_files: []
|