phrasing_plus 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 910cd01178a5275a7f64fcee6559e40cd55e3ea8
4
+ data.tar.gz: 81a5b83e8b3c63576390e0b12299887e28f63e43
5
+ SHA512:
6
+ metadata.gz: 92f1f24a18ef66e7b7cb767f535780949923e760402e1aedd44d21910fefc823a78dc580915d1ebd8252311bc27cabb424f13e8c4c64c3b52d524fd3ded64f7d
7
+ data.tar.gz: b601ddd336c10342a88c062c7840b8a89a7ce502a467ce7546e5eb09cdd59cd68ff299a20bfc8675dfc617b9abe591fb5b5836900d28580e414169b0443b084b
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Damir Svrtan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'PhrasingPlus'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
@@ -0,0 +1,120 @@
1
+ function PhrasingImageWidget(options){
2
+ var fileInput = options.fileInput;
3
+ var $fileInputLabel = options.$fileInputLabel;
4
+ var $discardChangeLabel = options.$discardChangeLabel;
5
+ var $wrapper = options.$wrapper;
6
+ var $image = options.$image;
7
+ var $form = options.$form;
8
+ var $submitButton = options.$submitButton;
9
+
10
+ var getImageSrc = function(){
11
+ if($image.size() !== 0){
12
+ $image.attr('src');
13
+ }else{
14
+ $wrapper.css('background-image');
15
+ }
16
+ };
17
+
18
+ var setImageSrc = function(src){
19
+ if($image.size() !== 0){
20
+ $image.attr('src', src);
21
+ }else{
22
+ $wrapper.css('background-image', src);
23
+ }
24
+ };
25
+
26
+ var showChosenImage = function(){
27
+ rememberOriginalImage();
28
+ setChosenImageAsSource();
29
+ $fileInputLabel.hide();
30
+ $discardChangeLabel.show();
31
+ $submitButton.show();
32
+ };
33
+
34
+ var setChosenImageAsSource = function(){
35
+ if (fileInput.files && fileInput.files[0]) {
36
+ var reader = new FileReader();
37
+ reader.onload = function (e) {
38
+ if($image.size() !== 0){
39
+ setImageSrc(e.target.result);
40
+ }else{
41
+ setImageSrc('url(' + e.target.result + ')');
42
+ }
43
+ };
44
+ reader.readAsDataURL(fileInput.files[0]);
45
+ }
46
+ };
47
+
48
+ var rememberOriginalImage = function(){
49
+ $wrapper.data('original-src', getImageSrc());
50
+ };
51
+
52
+ var discardChosenImage = function(){
53
+ revertImageToOriginal();
54
+ $form[0].reset();
55
+ $fileInputLabel.show();
56
+ $discardChangeLabel.hide();
57
+ $submitButton.hide();
58
+ };
59
+
60
+ var revertImageToOriginal = function(){
61
+ setImageSrc($wrapper.data('original-src'));
62
+ $wrapper.removeData('original-src');
63
+ };
64
+
65
+ var uploadChosenImage = function(){
66
+ $.ajax({
67
+ type: "PUT",
68
+ url: $form.attr('action'),
69
+ data: new FormData( $form[0] ),
70
+ processData: false,
71
+ contentType: false,
72
+ success: function(data)
73
+ {
74
+ handleSuccessfullUpload(data);
75
+ },
76
+ error: function(data){
77
+ handleFailedUpload(data);
78
+ }
79
+ });
80
+ };
81
+
82
+ var handleSuccessfullUpload = function(data){
83
+ $form[0].reset();
84
+ addNewSrcToImage(data.image.url);
85
+ $fileInputLabel.show();
86
+ $discardChangeLabel.hide();
87
+ $submitButton.hide();
88
+ showSuccessNotification(data);
89
+ };
90
+
91
+ var showSuccessNotification = function(data){
92
+ alert('Image successfully updated');
93
+ };
94
+
95
+ var addNewSrcToImage = function(imgSrc){
96
+ if($image.size() !== 0){
97
+ setImageSrc(imgSrc);
98
+ }else{
99
+ setImageSrc('url(' + imgSrc + ')');
100
+ }
101
+ $wrapper.removeData('original-src');
102
+ };
103
+
104
+ var handleFailedUpload = function(data){
105
+ $form[0].reset();
106
+ revertImageToOriginal();
107
+ $fileInputLabel.show();
108
+ $discardChangeLabel.hide();
109
+ $submitButton.hide();
110
+ showFailureNotification(data);
111
+ };
112
+
113
+ var showFailureNotification = function(data){
114
+ alert(data.responseJSON.errors);
115
+ };
116
+
117
+ return { showChosenImage: showChosenImage,
118
+ discardChosenImage: discardChosenImage,
119
+ uploadChosenImage: uploadChosenImage };
120
+ }
@@ -0,0 +1,54 @@
1
+ //=require phrasing_image_widget
2
+ var generatePhrasingImageWidget = function($wrapper){
3
+ return new PhrasingImageWidget({
4
+ fileInput : $wrapper.find('.phrasing-image-file-input')[0],
5
+ $fileInputLabel : $wrapper.find('.phrasing-image-edit-label'),
6
+ $discardChangeLabel : $wrapper.find('.phrasing-image-discard-change-label'),
7
+ $wrapper : $wrapper,
8
+ $image : $wrapper.find('img.phrasable-image'),
9
+ $form : $wrapper.find('.phrasing-image-edit-form'),
10
+ $submitButton : $wrapper.find('.phrasing-image-submit-button')
11
+ });
12
+ };
13
+
14
+ var fetchPhrasingImageWidget = function($wrapper){
15
+ var widget = $wrapper.data('widget');
16
+
17
+ if(widget === undefined){
18
+ widget = generatePhrasingImageWidget($wrapper);
19
+ $wrapper.data('widget', widget);
20
+ }
21
+
22
+ return widget;
23
+ };
24
+
25
+ $(document).ready(function(){
26
+ if(Phrasing.isEditModeEnabled()){
27
+ $('.phrasable-image-wrapper, .phrasable-background-image').addClass('phrasable-on');
28
+ }
29
+
30
+ Phrasing.Bus.on('phrasing:edit-mode:on', function(){
31
+ $('.phrasable-image-wrapper, .phrasable-background-image').addClass('phrasable-on');
32
+ });
33
+
34
+ Phrasing.Bus.on('phrasing:edit-mode:off', function(){
35
+ $('.phrasable-image-wrapper, .phrasable-background-image').removeClass('phrasable-on');
36
+ });
37
+
38
+ $('.phrasing-image-file-input').change(function(){
39
+ var phrasingImageWidget = fetchPhrasingImageWidget($(this).closest('.phrasable-image-wrapper, .phrasable-background-image'));
40
+ phrasingImageWidget.showChosenImage();
41
+ });
42
+
43
+ $('.phrasing-image-discard-change-label').on('click', function(){
44
+ var phrasingImageWidget = fetchPhrasingImageWidget($(this).closest('.phrasable-image-wrapper, .phrasable-background-image'));
45
+ phrasingImageWidget.discardChosenImage();
46
+ });
47
+
48
+ $(".phrasing-image-edit-form").submit(function(e) {
49
+ var phrasingImageWidget = fetchPhrasingImageWidget($(this).closest('.phrasable-image-wrapper, .phrasable-background-image'));
50
+ phrasingImageWidget.uploadChosenImage();
51
+ e.preventDefault();
52
+ });
53
+
54
+ });
@@ -0,0 +1,92 @@
1
+ .phrasing-image-holder{
2
+ form.phrasing-image-edit-form {
3
+ display: none;
4
+ position: absolute;
5
+ top: 0;
6
+ right: 0;
7
+
8
+ label{
9
+ font-family: "icomoon";
10
+ font-size: 13px;
11
+ font-weight: 200;
12
+
13
+ position: absolute;
14
+ right: 20px;
15
+
16
+ width: 180px;
17
+ padding: 12px 0;
18
+
19
+ text-align: center;
20
+
21
+ color: white;
22
+ border: 2px solid white;
23
+ -webkit-border-radius: 35px;
24
+ -moz-border-radius: 35px;
25
+ border-radius: 35px;
26
+ }
27
+
28
+ label.phrasing-image-edit-label {
29
+ top: 20px;
30
+ background: #898989;
31
+ }
32
+
33
+ label.phrasing-image-discard-change-label{
34
+ top: 65px;
35
+ background: #F1A515;
36
+ display: none;
37
+ }
38
+
39
+ .phrasing-image-file-input {
40
+ display: none;
41
+ }
42
+
43
+ .phrasing-image-submit-button {
44
+ font-family: "icomoon";
45
+ font-size: 13px;
46
+ font-weight: 200;
47
+
48
+ position: absolute;
49
+ top: 20px;
50
+ right: 20px;
51
+
52
+ display: none;
53
+
54
+ width: 181px;
55
+ height: 42px;
56
+
57
+ color: white;
58
+ border: 2px solid white;
59
+ -webkit-border-radius: 35px;
60
+ -moz-border-radius: 35px;
61
+ border-radius: 35px;
62
+ background: #56AE45;
63
+ }
64
+ }
65
+
66
+ &.phrasable-on{
67
+ .phrasing-image-edit-form{
68
+ display: block;
69
+ }
70
+ }
71
+ }
72
+
73
+ span.phrasable-image-wrapper{
74
+ @extend .phrasing-image-holder;
75
+ position: relative;
76
+ display: inline-block;
77
+
78
+ .phrasable-image {
79
+ position: relative;
80
+ }
81
+
82
+ &.phrasable-on {
83
+ .phrasable-image {
84
+ opacity: .8;
85
+ }
86
+ }
87
+ }
88
+
89
+ .phrasable-background-image{
90
+ @extend .phrasing-image-holder;
91
+ position: relative;
92
+ }
@@ -0,0 +1,15 @@
1
+ class PhrasingImagesController < ActionController::Base
2
+ include PhrasingHelper
3
+
4
+ def update
5
+ phrasing_image = PhrasingImage.find(params[:id])
6
+ phrasing_image.image = params[:phrasing_image][:image]
7
+
8
+ if phrasing_image.save
9
+ render json: phrasing_image, status: 200
10
+ else
11
+ render json: { errors: phrasing_image.errors.values.first }, status: 403
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,14 @@
1
+ module PhrasingPlusHelper
2
+ def phrasing_image_tag(key, options = {})
3
+ image = PhrasingImage.find_or_create_by(key: key)
4
+ image_widget = PhrasingImageWidget.new(image, self, options)
5
+ render 'phrasing_plus/editable_image', widget: image_widget
6
+ end
7
+
8
+ def phrasing_background_image_tag(key, options = {}, &block)
9
+ image = PhrasingImage.find_or_create_by(key: key)
10
+ wrapped_html = capture(&block) if block_given?
11
+ image_widget = PhrasingBackgroundImageWidget.new(image, self, wrapped_html, options)
12
+ render 'phrasing_plus/editable_background_image', widget: image_widget
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ class PhrasingImage < ActiveRecord::Base
2
+ mount_uploader :image, PhrasingImageUploader
3
+
4
+ validates :key, presence: true
5
+ end
@@ -0,0 +1,7 @@
1
+ class PhrasingImageUploader < CarrierWave::Uploader::Base
2
+ storage :file
3
+
4
+ def extension_white_list
5
+ %w(jpg jpeg gif png)
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ = content_tag(widget.tag, widget.options) do
2
+ - if can_edit_phrases?
3
+ = render 'phrasing_plus/form', widget: widget
4
+ = widget.wrapped_html
@@ -0,0 +1,4 @@
1
+ %span{ widget.wrapper_options }
2
+ = image_tag(widget.image_url, widget.options)
3
+ - if can_edit_phrases?
4
+ = render 'phrasing_plus/form', widget: widget
@@ -0,0 +1,5 @@
1
+ = form_for(widget, html: { class: 'phrasing-image-edit-form'}) do |f|
2
+ = f.label(:image, 'Click to edit image', class: 'phrasing-image-edit-label', for: "phrasing_image_image_#{widget.id}")
3
+ = f.file_field(:image, class: 'phrasing-image-file-input', id: "phrasing_image_image_#{widget.id}")
4
+ = f.label(:discard_change, class: 'phrasing-image-discard-change-label')
5
+ = f.button('Save image', class: 'phrasing-image-submit-button')
@@ -0,0 +1,35 @@
1
+ require 'phrasing_plus/dummy_image'
2
+
3
+ class PhrasingBackgroundImageWidget < SimpleDelegator
4
+
5
+ HTML_CLASS = 'phrasable-background-image'
6
+
7
+ attr_accessor :options, :wrapped_html
8
+
9
+ def initialize(phrasing_image, view_context, wrapped_html, options = {})
10
+ super(phrasing_image)
11
+ @view_context = view_context
12
+ @wrapped_html = wrapped_html
13
+ @options = options.merge(style: "background-image: url(#{image_url})")
14
+ @tag = @options.delete(:tag)
15
+
16
+ return unless view_context.can_edit_phrases?
17
+
18
+ add_phrasable_image_class
19
+ end
20
+
21
+ def tag
22
+ @tag || :div
23
+ end
24
+
25
+ private
26
+
27
+ def image_url
28
+ image.url || PhrasingPlus::DummyImage.new(options).url
29
+ end
30
+
31
+ def add_phrasable_image_class
32
+ options[:class] = [options[:class], HTML_CLASS].compact.join(' ')
33
+ end
34
+
35
+ end
@@ -0,0 +1,38 @@
1
+ require 'phrasing_plus/dummy_image'
2
+
3
+ class PhrasingImageWidget < SimpleDelegator
4
+
5
+ HTML_CLASS = 'phrasable-image'
6
+ WRAPPER_HTML_CLASS = 'phrasable-image-wrapper'
7
+
8
+ attr_accessor :options, :wrapper_options
9
+
10
+ def initialize(phrasing_image, view_context, options = {})
11
+ super(phrasing_image)
12
+ @view_context = view_context
13
+ @options = options
14
+ @wrapper_options = @options.delete(:wrapper_html) || {}
15
+
16
+ return unless view_context.can_edit_phrases?
17
+
18
+ add_phrasable_image_class
19
+ add_phrasable_image_wrapper_class
20
+ end
21
+
22
+ def image_url
23
+ image.url || PhrasingPlus::DummyImage.new(options).url
24
+ end
25
+
26
+ private
27
+
28
+ attr_accessor :view_context
29
+
30
+ def add_phrasable_image_class
31
+ options[:class] = [options[:class], HTML_CLASS].compact.join(' ')
32
+ end
33
+
34
+ def add_phrasable_image_wrapper_class
35
+ wrapper_options[:class] = [wrapper_options[:class], WRAPPER_HTML_CLASS].compact.join(' ')
36
+ end
37
+
38
+ end
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ resources :phrasing_images, only: [:update]
3
+ end
@@ -0,0 +1,13 @@
1
+ class PhrasingPlusGenerator < Rails::Generators::Base
2
+ include Rails::Generators::Migration
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ def create_migrations
6
+ phrasing_image_migration = "db/migrate/create_phrasing_images.rb"
7
+ migration_template phrasing_image_migration, phrasing_image_migration
8
+ end
9
+
10
+ def self.next_migration_number(*)
11
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ class CreatePhrasingImages < ActiveRecord::Migration
2
+ def change
3
+ create_table :phrasing_images do |t|
4
+ t.string :key
5
+ t.string :image
6
+
7
+ t.timestamps null: false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ module PhrasingPlus
2
+ class DummyImage
3
+
4
+ BG_COLOR = '7d857c'
5
+ COLOR = 'dea9bb'
6
+
7
+ def initialize(options = {})
8
+ @options = options
9
+ end
10
+
11
+ def url
12
+ "http://placehold.it/#{size}/#{BG_COLOR}/#{COLOR}"
13
+ end
14
+
15
+ private
16
+
17
+ attr_accessor :options
18
+
19
+ def size
20
+ options[:size] || "#{width}x#{height}"
21
+ end
22
+
23
+ def width
24
+ options[:width] || 300
25
+ end
26
+
27
+ def height
28
+ options[:height] || 300
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+ require 'phrasing'
2
+ require 'carrierwave'
3
+
4
+ module PhrasingPlus
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module PhrasingPlus
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,4 @@
1
+ require "phrasing_plus/engine"
2
+
3
+ module PhrasingPlus
4
+ end
metadata ADDED
@@ -0,0 +1,135 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phrasing_plus
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Damir Svrtan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-14 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.2.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.2.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: phrasing
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 4.0.0rc5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 4.0.0rc5
41
+ - !ruby/object:Gem::Dependency
42
+ name: carrierwave
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.10.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.10.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A mountable Phrasing adapter for editing images inline.
84
+ email:
85
+ - damir.svrtan@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - MIT-LICENSE
91
+ - Rakefile
92
+ - app/assets/javascripts/phrasing_image_widget.js
93
+ - app/assets/javascripts/phrasing_plus.js
94
+ - app/assets/stylesheets/phrasing_plus.scss
95
+ - app/controllers/phrasing_images_controller.rb
96
+ - app/helpers/phrasing_plus_helper.rb
97
+ - app/models/phrasing_image.rb
98
+ - app/uploaders/phrasing_image_uploader.rb
99
+ - app/views/phrasing_plus/_editable_background_image.html.haml
100
+ - app/views/phrasing_plus/_editable_image.html.haml
101
+ - app/views/phrasing_plus/_form.html.haml
102
+ - app/widgets/phrasing_background_image_widget.rb
103
+ - app/widgets/phrasing_image_widget.rb
104
+ - config/routes.rb
105
+ - lib/generators/phrasing_plus/phrasing_plus_generator.rb
106
+ - lib/generators/phrasing_plus/templates/db/migrate/create_phrasing_images.rb
107
+ - lib/phrasing_plus.rb
108
+ - lib/phrasing_plus/dummy_image.rb
109
+ - lib/phrasing_plus/engine.rb
110
+ - lib/phrasing_plus/version.rb
111
+ homepage: https://github.com/infinum/phrasing_plus
112
+ licenses:
113
+ - MIT
114
+ metadata: {}
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubyforge_project:
131
+ rubygems_version: 2.2.2
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: Edit images inline
135
+ test_files: []