BBenezech-papermill 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ .DS_Store
2
+ log/*.log
3
+ tmp/**/*
4
+ config/database.yml
5
+ db/*.sqlite3
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [name of plugin creator]
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/README.rdoc ADDED
@@ -0,0 +1,62 @@
1
+ = Papermill
2
+
3
+ Asset management made easy.. Painfully easy.
4
+ Try the demo to see for yourself.
5
+
6
+ See papermill_module.rb for a complete list of available options.
7
+ These options can be application wide, for a class, or set at the last moment for the helper.
8
+
9
+ In your model:
10
+
11
+ papermill :assets
12
+
13
+ In your layout:
14
+
15
+ <%= papermill_stylesheet_tag %>
16
+ <%= papermill_javascript_tag :with_jquery => true %>
17
+
18
+ In your edit form:
19
+
20
+ f.images_upload(:my_image_gallery)
21
+ f.image_upload(:header_image)
22
+
23
+ Finally, in your views:
24
+
25
+ # Some template image :
26
+ <%= image_tag @article.assets(:header_image).first.url("800x>") %>
27
+
28
+ # Some image gallery:
29
+ <ul>
30
+ <% @article.assets(:my_image_gallery).each do |image| %>
31
+ <li><%= link_to(image_tag(image.url("100x100>")), image.url) %></li>
32
+ <% end %>
33
+ </ul>
34
+
35
+ Also see http://gist.github.com/177714.txt to get up-to-date installation steps.
36
+ See the API here http://rdoc.info/projects/BBenezech/papermill
37
+
38
+ == Word of caution:
39
+
40
+ Beta.
41
+
42
+ This is xNIX only (system("rm ...")).
43
+
44
+ You'll need rails 2.3, since this is an engine. Anyway, copying the controller/view/routes to your project will make it work on an older version of rails.
45
+
46
+ You'll need rails 2.2, since their are calls to I18n.t. But it shouldn't be too hard to work-around either.
47
+
48
+ == Usage :
49
+
50
+ === Demo :
51
+
52
+ You can use the custom template generator to get an example application up and running in no time.
53
+
54
+ rails -m http://gist.github.com/177714.txt papermill-example
55
+
56
+ === Translation:
57
+
58
+ Papermill is fully Rails 2.2 I18n-able.
59
+
60
+ Copy config/locale/papermill.yml to your root config/locale folder to modify any wording in a any locale.
61
+
62
+ Copyright (c) 2009 Benoit Bénézech, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the papermill plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the papermill plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'Papermill'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "papermill"
29
+ gemspec.summary = "Paperclip wrapper"
30
+ gemspec.description = "Paperclip wrapper"
31
+ gemspec.email = "benoit.benezech@gmail.com"
32
+ gemspec.homepage = "http://github.com/BBenezech/papermill"
33
+ gemspec.authors = ["Benoit Bénézech"]
34
+ end
35
+ rescue LoadError
36
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
37
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,80 @@
1
+ class PapermillController < ApplicationController
2
+
3
+ skip_before_filter :verify_authenticity_token
4
+
5
+ def show
6
+ begin
7
+ if Papermill::PAPERMILL_DEFAULTS[:alias_only]
8
+ style = Papermill::PAPERMILL_DEFAULTS[:aliases][params[:style]]
9
+ else
10
+ style = Papermill::PAPERMILL_DEFAULTS[:aliases][params[:style]] || params[:style]
11
+ end
12
+ raise unless style
13
+ asset = PapermillAsset.find(params[:id])
14
+ temp_thumbnail = Paperclip::Thumbnail.make(asset_file = asset.file, style)
15
+ new_parent_folder_path = File.dirname(new_image_path = asset_file.path(params[:style]))
16
+ FileUtils.mkdir_p new_parent_folder_path unless File.exists? new_parent_folder_path
17
+ FileUtils.cp temp_thumbnail.path, new_image_path
18
+ redirect_to asset.url(params[:style])
19
+ rescue
20
+ render :text => t("not-processed", :scope => "papermill"), :status => "500"
21
+ end
22
+ end
23
+
24
+ def destroy
25
+ begin
26
+ @asset = PapermillAsset.find(params[:id])
27
+ render :update do |page|
28
+ if @asset.destroy
29
+ page << "jQuery('#papermill_asset_#{params[:id]}').remove()"
30
+ else
31
+ page << "jQuery('#papermill_asset_#{params[:id]}').show()"
32
+ message = t("not-deleted", :ressource => @asset.name, :scope => "papermill")
33
+ page << %{ notify("#{message}", error) }
34
+ end
35
+ end
36
+ rescue ActiveRecord::RecordNotFound
37
+ render :update do |page|
38
+ page << "jQuery('#papermill_asset_#{params[:id]}').remove()"
39
+ message = t("not-found", :ressource => params[:id].to_s, :scope => "papermill")
40
+ page << %{ notify("#{message}", "warning") }
41
+ end
42
+ end
43
+ end
44
+
45
+ def update
46
+ @asset = PapermillAsset.find params[:id]
47
+ @asset.update(params)
48
+ render :update do |page|
49
+ message = t("updated", :ressource => @asset.name, :scope => "papermill")
50
+ page << %{ notify("#{message}", "notice") }
51
+ end
52
+ end
53
+
54
+ def edit
55
+ @asset = PapermillAsset.find params[:id]
56
+ end
57
+
58
+ def create
59
+ params[:assetable_type] = params[:assetable_type].camelize
60
+ asset_class = params[:assetable_type].constantize.papermill_associations[params[:association].to_sym][:class]
61
+ params[:swfupload_file] = params.delete(:Filedata)
62
+ @old_asset = asset_class.find(:first, :conditions => {:assetable_key => params[:assetable_key].to_s, :assetable_type => params[:assetable_type], :assetable_id => params[:assetable_id]}) unless params[:gallery]
63
+ @asset = asset_class.new(params.reject{|key, value| !(PapermillAsset.columns.map(&:name)+["swfupload_file"]).include?(key.to_s)})
64
+
65
+ if @asset.save
66
+ @old_asset.destroy if @old_asset
67
+ render :partial => "papermill/asset", :object => @asset, :locals => {:thumbnail => params[:thumbnail], :gallery => params[:gallery], :thumbnail_style => params[:thumbnail_style]}
68
+ else
69
+ message = t("not-created", :scope => "papermill")
70
+ render :text => message, :status => "500"
71
+ end
72
+ end
73
+
74
+ def sort
75
+ params[:papermill_asset].each_with_index do |id, index|
76
+ PapermillAsset.find(id).update_attribute(:position, index + 1)
77
+ end
78
+ render :nothing => true
79
+ end
80
+ end
@@ -0,0 +1,11 @@
1
+ <%- dom_id = dom_id(asset) -%>
2
+ <%- delete_link = %{<a onclick="if(confirm('#{escape_javascript I18n.t("delete-confirmation", :scope => :papermill, :resource => asset.name)}')){ $.ajax({async:true, beforeSend:function(request){$('##{dom_id}').hide();}, dataType:'script', error:function(request){$('##{dom_id}').show();}, type:'delete', url:'#{papermill_url(asset)}'})}; return false;" href="#" class="delete"><img title="#{escape_javascript t("delete", :scope => "papermill", :ressource => asset.name)}" src="/images/papermill/delete.png" alt="delete"/></a>} %>
3
+
4
+ <li id="<%= dom_id %>" rel="<%= edit_papermill_url(asset) %>" title="<%= t("#{thumbnail_style ? "thumbnail-" : ""}edit-title", :scope => "papermill", :ressource => asset.name) %>">
5
+ <%= delete_link %>
6
+ <%- if thumbnail_style -%>
7
+ <%= render :partial => "papermill/thumbnail_asset", :object => asset, :locals => {:thumbnail_style => thumbnail_style} %>
8
+ <%- else -%>
9
+ <%= render :partial => "papermill/raw_asset", :object => asset %>
10
+ <%- end -%>
11
+ </li>
@@ -0,0 +1 @@
1
+ <%= link_to(raw_asset.name, raw_asset.url, :class => "name") -%>
@@ -0,0 +1,6 @@
1
+ <% if thumbnail_asset.image? %>
2
+ <span class="image"><%= image_tag(thumbnail_asset.url(thumbnail_style)) %></span>
3
+ <% else %>
4
+ <span class="name" title="<%= thumbnail_asset.name %>"><%= truncate(thumbnail_asset.name, :length => 15) %></span>
5
+ <span class="infos"><%= thumbnail_asset.content_type[1] %></span>
6
+ <% end %>
@@ -0,0 +1,30 @@
1
+ en:
2
+ papermill:
3
+ not-processed: "Error/ressource not processed"
4
+ updated: "{{ressource}} updated"
5
+ not-deleted: "{{ressource}} could not be deleted"
6
+ not-created: "Ressource could not be created"
7
+ not-found: "Asset #{{ressource}} not found"
8
+ edit-title: "" # You can use {{ressource}}
9
+ thumbnail-edit-title: ""
10
+ upload-button-wording: "Upload..."
11
+ delete: "Remove {{ressource}}"
12
+ delete-confirmation: "Delete '{{resource}}'?"
13
+ SWFUPLOAD_PENDING: "Pending..."
14
+ SWFUPLOAD_LOADING: "Loading..."
15
+ SWFUPLOAD_ERROR: "Something happened while loading" # + " <file_name> (<swfupload error message> [<error code>])"
16
+ fr:
17
+ papermill:
18
+ not-processed: "Erreur/ressource non trouvée"
19
+ updated: "{{ressource}} mise à jour"
20
+ not-deleted: "{{ressource}} n'a pas pu être supprimée"
21
+ not-created: "La ressource n'a pas pu être créée"
22
+ not-found: "Asset #{{ressource}} non trouvé"
23
+ edit-title: ""
24
+ thumbnail-edit-title: ""
25
+ upload-button-wording: "Charger.."
26
+ delete: "Supprimer {{ressource}}"
27
+ delete-confirmation: "Êtes-vous sûr de vouloir supprimer '{{resource}}' ?"
28
+ SWFUPLOAD_PENDING: "En attente..."
29
+ SWFUPLOAD_LOADING: "Chargement..."
30
+ SWFUPLOAD_ERROR: "Une erreur est survenue pendant le chargement de"
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.resources :papermill, :collection => { :sort => :post }
3
+ map.connect "#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}", :controller => "papermill", :action => "show"
4
+ end
@@ -0,0 +1,3 @@
1
+ script/generate papermill MyTableName
2
+
3
+ This will create the migration table.
@@ -0,0 +1,16 @@
1
+ class PapermillGenerator < Rails::Generator::NamedBase
2
+ attr_accessor :class_name, :migration_name
3
+
4
+ def initialize(args, options = {})
5
+ super
6
+ @class_name = args[0]
7
+ end
8
+
9
+ def manifest
10
+ @migration_name = file_name.camelize
11
+ record do |m|
12
+ # Migration creation
13
+ m.migration_template "migrate/papermill_migration.rb.erb", "db/migrate", :migration_file_name => migration_name.underscore
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,22 @@
1
+ class <%= migration_name %> < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :papermill_assets do |t|
4
+ t.string :file_file_name
5
+ t.string :file_content_type
6
+ t.integer :file_file_size
7
+ t.integer :position
8
+ t.text :description
9
+ t.string :copyright
10
+ t.string :title
11
+ t.integer :assetable_id
12
+ t.string :assetable_type
13
+ t.string :assetable_key
14
+ t.string :type
15
+ t.timestamps
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ drop_table :papermill_assets
21
+ end
22
+ end
data/init.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'core_extensions'
2
+ Object.send :include, ObjectExtensions
3
+ Hash.send :include, HashExtensions
4
+ String.send :include, StringExtensions
5
+
6
+ I18n.load_path = [File.join(File.dirname(__FILE__), 'config/locale/papermill.yml')] + I18n.load_path
7
+
8
+ require 'papermill'
9
+ ActionView::Base.send :include, PapermillHelper
10
+ ActiveRecord::Base.send :include, Papermill
data/install.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "fileutils"
2
+
3
+ FileUtils.cp_r(
4
+ Dir[File.join(File.dirname(__FILE__), 'public')],
5
+ File.join(RAILS_ROOT),
6
+ :verbose => true
7
+ )
@@ -0,0 +1,25 @@
1
+ module HashExtensions
2
+ def deep_merge(hash)
3
+ target = dup
4
+ hash.keys.each do |key|
5
+ if hash[key].is_a? Hash and self[key].is_a? Hash
6
+ target[key] = target[key].deep_merge(hash[key])
7
+ next
8
+ end
9
+ target[key] = hash[key]
10
+ end
11
+ target
12
+ end
13
+ end
14
+ module StringExtensions
15
+ def simple_sql_sanitizer
16
+ gsub(/\\/, '\&\&').gsub(/'/, "''")
17
+ end
18
+ end
19
+
20
+ module ObjectExtensions
21
+ # Nil if empty.
22
+ def nie
23
+ self.blank? ? nil : self
24
+ end
25
+ end
data/lib/papermill.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'papermill/papermill_module'
2
+ require 'papermill/papermill_asset'
3
+ require 'papermill/form_builder'
4
+ require 'papermill/papermill_helper'
@@ -0,0 +1,91 @@
1
+ class ActionView::Helpers::FormBuilder
2
+
3
+ def assets_upload(key = nil, method = nil, options = {})
4
+ papermill_upload_field key, method, { :thumbnail => false }.update(options)
5
+ end
6
+ def asset_upload(key = nil, method = nil, options = {})
7
+ papermill_upload_field key, method, { :gallery => false, :thumbnail => false }.update(options)
8
+ end
9
+ def images_upload(key = nil, method = nil, options = {})
10
+ papermill_upload_field key, method, options
11
+ end
12
+ def image_upload(key = nil, method = nil, options = {})
13
+ papermill_upload_field key, method, { :gallery => false }.update(options)
14
+ end
15
+
16
+ private
17
+ def papermill_upload_field(key, method, options = {})
18
+ assetable = @template.instance_variable_get("@#{@object_name}")
19
+ method ||= options[:association] || :papermill_assets
20
+ key ||= options[:key] || nil
21
+ options = assetable.class.papermill_options.deep_merge(options)
22
+ assetable_id = assetable.id || assetable.timestamp
23
+ assetable_type = assetable.class.to_s.underscore
24
+ id = "papermill_#{assetable_type}_#{assetable_id}_#{key}_#{method}"
25
+ if options[:thumbnail]
26
+ w = options[:thumbnail][:width] || options[:thumbnail][:height] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:height] * options[:thumbnail][:aspect_ratio]).to_i || nil
27
+ h = options[:thumbnail][:height] || options[:thumbnail][:width] && options[:thumbnail][:aspect_ratio] && (options[:thumbnail][:width] / options[:thumbnail][:aspect_ratio]).to_i || nil
28
+ options[:thumbnail][:style] ||= (w || h) && "#{w || options[:thumbnail][:max_width]}x#{h || options[:thumbnail][:max_height]}>" || "original"
29
+ if options[:thumbnail][:inline_css]
30
+ size = []
31
+ size << "width:#{w}px" if w
32
+ size << "height:#{h}px" if h
33
+ size = size.join("; ")
34
+ @template.content_for :inline_css do
35
+ inline_css = ["\n"]
36
+ if options[:gallery]
37
+ vp = options[:gallery][:vpadding].to_i
38
+ hp = options[:gallery][:hpadding].to_i
39
+ vm = options[:gallery][:vmargin].to_i
40
+ hm = options[:gallery][:hmargin].to_i
41
+ b = options[:gallery][:border_thickness].to_i
42
+ gallery_width = (options[:gallery][:width] || w) && "width:#{options[:gallery][:width] || options[:gallery][:columns]*(w+(hp+hm+b)*2)}px;" || ""
43
+ gallery_height = (options[:gallery][:height] || h) && "#{options[:gallery][:autogrow] ? "" : "min-"}height:#{options[:gallery][:height] || options[:gallery][:lines]*(h+(vp+vm+b)*2)}px;" || ""
44
+ inline_css << %{##{id} { #{gallery_width} #{gallery_height} }}
45
+ inline_css << %{##{id} li { margin:#{vm}px #{hm}px; border-width:#{b}px; padding:#{vp}px #{hp}px; #{size}; }}
46
+ else
47
+ inline_css << %{##{id}, ##{id} li { #{size} }}
48
+ end
49
+ inline_css << %{##{id} .name { width:#{w || "100"}px; }}
50
+ inline_css.join("\n")
51
+ end
52
+ end
53
+ end
54
+ create_url = @template.url_for(:controller => "/papermill", :action => "create", :escape => false, :association => method.to_s, :assetable_key => key, :assetable_id => assetable_id, :assetable_type => assetable_type, :gallery => (options[:gallery] != false), :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]))
55
+ html = []
56
+ if assetable.new_record? && !@timestamped
57
+ html << self.hidden_field(:timestamp, :value => assetable.timestamp)
58
+ @timestamped = true
59
+ end
60
+ html << %{<div style="height: #{options[:swfupload][:button_height]}px;"><span id="browse_for_#{id}" class="swf_button"></span></div>}
61
+ conditions = {:assetable_type => assetable.class.sti_name, :assetable_id => assetable_id}
62
+ conditions.merge!({:assetable_key => key.to_s}) if key
63
+ html << @template.content_tag(:ul, :id => id, :class => "papermill #{(options[:thumbnail] ? "papermill-thumb-container" : "papermill-asset-container")} #{(options[:gallery] ? "papermill-multiple-items" : "papermill-unique-item")}") {
64
+ @template.render :partial => "papermill/asset", :collection => assetable.class.papermill_associations[method][:class].find(:all, :conditions => conditions, :order => "position"), :locals => { :thumbnail_style => (options[:thumbnail] && options[:thumbnail][:style]) }
65
+ }
66
+ @template.content_for :inline_js do
67
+ %{
68
+ #{%{$("##{id}").sortable({update:function(){jQuery.ajax({async:true, data:jQuery(this).sortable('serialize'), dataType:'script', type:'post', url:'#{@template.controller.send("sort_papermill_url")}'})}})} if options[:gallery]}
69
+ new SWFUpload({
70
+ upload_id: "#{id}",
71
+ upload_url: "#{@template.escape_javascript create_url}",
72
+ file_size_limit: "#{options[:file_size_limit_mb].megabytes}",
73
+ file_types: "#{options[:images_only] ? '*.jpg;*.jpeg;*.png;*.gif' : ''}",
74
+ file_types_description: "#{options[:thumbnail] ? 'Images' : 'Files'}",
75
+ file_queue_limit: "#{!options[:gallery] ? '1' : '0'}",
76
+ file_queued_handler: Upload.file_queued,
77
+ file_dialog_complete_handler: Upload.file_dialog_complete,
78
+ upload_start_handler: Upload.upload_start,
79
+ upload_progress_handler: Upload.upload_progress,
80
+ upload_error_handler: Upload.upload_error,
81
+ upload_success_handler: Upload.upload_success,
82
+ upload_complete_handler: Upload.upload_complete,
83
+ button_placeholder_id : "browse_for_#{id}",
84
+ #{options[:swfupload].map{ |key, value| ["false", "true"].include?(value.to_s) ? "#{key.to_s}: #{value.to_s}" : "#{key.to_s}: '#{value.to_s}'" }.compact.join(", ")}
85
+ });
86
+ }
87
+ end
88
+ html.reverse! if options[:button_after_container]
89
+ html.join("\n")
90
+ end
91
+ end
@@ -0,0 +1,67 @@
1
+ class PapermillAsset < ActiveRecord::Base
2
+ acts_as_list :scope => 'assetable_key=\'#{assetable_key.simple_sql_sanitizer}\' AND assetable_id=#{assetable_id} AND assetable_type=\'#{assetable_type}\''
3
+
4
+ belongs_to :assetable, :polymorphic => true
5
+ before_destroy :destroy_files
6
+
7
+ named_scope :key, lambda { |key| { :conditions => { :assetable_key => key } } }
8
+
9
+ Paperclip::Attachment.interpolations[:assetable_type] = proc do |attachment, style|
10
+ attachment.instance.assetable_type.underscore.pluralize
11
+ end
12
+
13
+ Paperclip::Attachment.interpolations[:assetable_id] = proc do |attachment, style|
14
+ attachment.instance.assetable_id
15
+ end
16
+
17
+ Paperclip::Attachment.interpolations[:assetable_key] = proc do |attachment, style|
18
+ attachment.instance.assetable_key.to_url
19
+ end
20
+
21
+ Paperclip::Attachment.interpolations[:escaped_basename] = proc do |attachment, style|
22
+ Paperclip::Attachment.interpolations[:basename].call(attachment, style).to_url
23
+ end
24
+
25
+ has_attached_file :file,
26
+ :path => "#{Papermill::PAPERMILL_DEFAULTS[:public_root]}/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}",
27
+ :url => "/#{Papermill::PAPERMILL_DEFAULTS[:papermill_prefix]}/#{Papermill::PAPERCLIP_INTERPOLATION_STRING}"
28
+ validates_attachment_presence :file
29
+
30
+ #validates_attachment_content_type :file, :content_type => ['image/jpeg', 'image/pjpeg', 'image/jpg', 'image/png', 'image/gif']
31
+
32
+ # Fix the mime types. Make sure to require the mime-types gem
33
+ def swfupload_file=(data)
34
+ data.content_type = MIME::Types.type_for(data.original_filename).to_s
35
+ self.file = data
36
+ end
37
+
38
+ def name
39
+ file_file_name
40
+ end
41
+
42
+ def size
43
+ file_file_size
44
+ end
45
+
46
+ def url(style = nil)
47
+ file.url(style && CGI::escape(style.to_s))
48
+ end
49
+
50
+ def content_type
51
+ file_content_type.split("/") if file_content_type
52
+ end
53
+
54
+ def image?
55
+ content_type.first == "image" && content_type[1]
56
+ end
57
+
58
+ def interpolated_path(with = {}, up_to = nil)
59
+ Papermill::papermill_interpolated_path({":id" => self.id, ":assetable_id" => self.assetable_id, ":assetable_type" => self.assetable_type.underscore.pluralize}.merge(with), up_to)
60
+ end
61
+
62
+ # before_filter
63
+ def destroy_files
64
+ system "rm -rf #{self.interpolated_path({}, ':id')}/" if image?
65
+ true
66
+ end
67
+ end
@@ -0,0 +1,35 @@
1
+ module PapermillHelper
2
+
3
+ def papermill_javascript_tag(options = {})
4
+ html = []
5
+ root_folder = options[:path] || "javascripts"
6
+ if options[:with_jquery] || options[:with_jqueryui]
7
+ html << %{<script src="http://www.google.com/jsapi"></script>}
8
+ html << %{<script type="text/javascript">\n//<![CDATA[}
9
+ html << %{google.load("jquery", "1");} if options[:with_jquery]
10
+ html << %{google.load("jqueryui", "1");} if options[:with_jquery] || options[:with_jqueryui]
11
+ html << %{</script>}
12
+ end
13
+ html << %{<script src="http://swfupload.googlecode.com/svn/swfupload/tags/swfupload_v2.2.0_core/swfupload.js"></script>}
14
+ html << %{<script type="text/javascript">\n//<![CDATA[}
15
+ ["SWFUPLOAD_PENDING", "SWFUPLOAD_LOADING", "SWFUPLOAD_ERROR"].each do |js_constant|
16
+ html << %{var #{js_constant} = "#{I18n.t(js_constant, :scope => "papermill")}";}
17
+ end
18
+ html << %{//]]>\n</script>}
19
+ html << javascript_include_tag("/#{root_folder}/papermill", :cache => "swfupload-papermill")
20
+ html << '<script type="text/javascript">jQuery(document).ready(function() {'
21
+ html << @content_for_inline_js
22
+ html << '});</script>'
23
+ html.join("\n")
24
+ end
25
+
26
+ def papermill_stylesheet_tag(options = {})
27
+ html = []
28
+ root_folder = options[:path] || "stylesheets"
29
+ html << stylesheet_link_tag("/#{root_folder}/papermill")
30
+ html << %{<style type="text/css">}
31
+ html << @content_for_inline_css
32
+ html << %{</style>}
33
+ html.join("\n")
34
+ end
35
+ end
@@ -0,0 +1,182 @@
1
+ module Papermill
2
+
3
+ # Override these defaults :
4
+ # - in your application (environment.rb, ..) => in your [environment, development, production].rb file with Papermill::OPTIONS = {thumbnails => {..}, :gallery => {..}, etc. }
5
+ # - in your class => papermill <assoc_name>, :class_name => MySTIedPapermillAssetSubClass, thumbnails => {<my_thumbnail_parameters>}, :gallery => {<my_gallery_parameters>}, etc.
6
+ # - in your helper call => images_upload :my_gallery, {thumbnails => {..}, :gallery => {..}, etc. }
7
+ # Options will cascade as you expect them to.
8
+
9
+ # sizes (widths, paddings, etc..) are CSS pixel values.
10
+ PAPERMILL_DEFAULTS = {
11
+ :thumbnail => {
12
+ # you clearly want to override these two values in your templates.
13
+ # the rest is very optionnal and will "cascade" nicely
14
+ :width => 100, # Recommended if :gallery[:width] is nil
15
+ :height => 100, # Recommended if :gallery[:height] is nil
16
+ # set :width OR :height to nil to use aspect_ratio value. Remember that 4/3 == 1 => Use : 4.0/3
17
+ :aspect_ratio => nil,
18
+ :max_width => 1000,
19
+ :max_height => 1000,
20
+ # You can override computed ImageMagick transformation strings that defaults to "#{:width}x#{:height}>"
21
+ # Note that this is required if PAPERMILL_DEFAULTS[:alias_only] is true
22
+ :style => nil,
23
+ # set to false if you don't want inline CSS
24
+ :inline_css => true
25
+ },
26
+ # gallery
27
+ :gallery => {
28
+ # if thumbnail.inline_css is true, css will be generated automagically with these values. Great for quick scaffolding, and complete enough for real use.
29
+ :width => nil, # overrides calculated width. Recommended if :thumbnail[:width] is nil.
30
+ :height => nil, # overrides calculated height. Recommended if :thumbnail[:height] is nil.
31
+ :columns => 8, # number of columns. If thumbnail.width has a value, sets a width for the gallery, calculated from thumbnails width multiplied by :columns.
32
+ :lines => 2, # number of default lines. (height will autogrow) If thumbnail.height has a value, sets a min-height for the gallery, calculated from thumbnails height multiplied by :lines
33
+ :vpadding => 0, # vertical padding around thumbnails
34
+ :hpadding => 0, # horizontal padding around thumbnails
35
+ :vmargin => 1, # vertical margin around thumbnails
36
+ :hmargin => 1, # horizontal margin around thumbnails
37
+ :border_thickness => 2, # border around thumbnails
38
+ :autogrow => false # sets a min-height instead of height for the gallery
39
+ },
40
+ # options passed on to SWFUpload. To remove an option when overriding, set it to nil.
41
+ :swfupload => {
42
+ # !!! Will only work if the swf file comes from the server to where the files are sent. (Flash same origin security policy)
43
+ :flash_url => '/flashs/swfupload.swf',
44
+ # You can use upload-blank.png with your own wording or upload.png with default "upload" wording (looks nicer)
45
+ :button_image_url => '/images/papermill/upload-blank.png',
46
+ :button_width => 61,
47
+ :button_height => 22,
48
+ # Wording and CSS processed through an Adobe Flash styler. Result is terrible. Feel free to put a CSS button overlayed directly on the SWF button. See swfupload website.
49
+ :button_text => %{<span class="button-text">#{I18n.t("upload-button-wording", :scope => :papermill)}</span>},
50
+ :button_text_style => %{.button-text { color: red; font-size: 12pt; font-weight: bold; }},
51
+ :button_disabled => "false",
52
+ :button_text_top_padding => 4,
53
+ :button_text_left_padding => 4,
54
+ :debug => "false",
55
+ :prevent_swf_caching => "false"
56
+ # See swfupload.js for details.
57
+ },
58
+ :images_only => false, # set to true to forbid upload of anything else than images
59
+ :file_size_limit_mb => 10, # file max size
60
+ :button_after_container => false, # set to true to move the upload button below the container
61
+
62
+ # DO NOT CHANGE THESE IN YOUR CLASSES. Only application wide (routes depend on it..)
63
+ :alias_only => false, # set to true so that only aliases are authorized in url/path
64
+ :aliases => {
65
+ # "example" => "100x100#",
66
+ },
67
+ # path to the root of your public directory
68
+ :public_root => ":rails_root/public",
69
+ # added to :public_root as the root folder for all papermill items
70
+ :papermill_prefix => "papermill"
71
+ }.deep_merge( Papermill.const_defined?("OPTIONS") ? Papermill::OPTIONS : {} )
72
+
73
+
74
+ PAPERCLIP_INTERPOLATION_STRING = ":assetable_type/:assetable_id/:id/:style/:escaped_basename.:extension"
75
+
76
+ def self.included(base)
77
+ base.extend(ClassMethods)
78
+ end
79
+
80
+ def self.papermill_interpolated_path(replacements_pairs, up_to)
81
+ replacements_pairs = {"other" => "*", ":rails_root" => RAILS_ROOT}.merge(replacements_pairs)
82
+ a = "#{PAPERMILL_DEFAULTS[:public_root]}/#{PAPERMILL_DEFAULTS[:papermill_prefix]}/#{PAPERCLIP_INTERPOLATION_STRING}".split("/")
83
+ "#{a[0..(up_to && a.index(up_to) || -1)].map{ |s| s.starts_with?(':') ? (replacements_pairs[s] || replacements_pairs['other'] || s) : s }.join('/')}"
84
+ end
85
+
86
+ module ClassMethods
87
+ attr_reader :papermill_options
88
+ attr_reader :papermill_associations
89
+
90
+ # Dealing with STIed Asset table in papermill declaration is dead easy, since papermill follows ActiveRecord :has_many global syntax and the Convention over configuration concept :
91
+ # papermill <association_name>, :class_name => MySTIedPapermillAssetClassName
92
+ # class MyAsset < PapermillAsset
93
+ # ...
94
+ # end
95
+ # class MyAssetableClass < ActiveRecord::Base
96
+ # 1 -> papermill :my_association, :class_name => MyAsset
97
+ # 2 -> papermill :class_name => MyAsset
98
+ # 3 -> papermill :my_assets
99
+ # 4 -> papermill :my_other_assets
100
+ # 5 -> papermill
101
+ # end
102
+ # assetable = MyAssetableClass.new
103
+ # 1 -> assetable.my_association attached MyAsset objects (no magic here, association and class_name both specified)
104
+ # 2 -> assetable.my_assets attached MyAsset objects (association infered from :class_name as expected)
105
+ # 3 -> assetable.my_assets attached MyAsset objects (class_name guessed from association name)
106
+ # 4 -> assetable.my_other_assets attached PapermillAssets objects (couldn't find MyOtherAsset class or MyOtherAsset is not a PapermillAsset subclass, use default PapermillAsset superclass)
107
+ # 5 -> assetable.papermill_assets attached PapermillAssets objects (defaults)
108
+
109
+ def papermill(assoc = nil, options = {})
110
+ @papermill_associations ||= {}
111
+ asset_class = ((klass = options.delete(:class_name)) && (klass = (klass.to_s.singularize.camelize.constantize rescue nil)) && klass.superclass == PapermillAsset && klass || assoc && (klass = (assoc.to_s.singularize.camelize.constantize rescue nil)) && klass.superclass == PapermillAsset && klass || PapermillAsset)
112
+ assoc ||= asset_class.to_s.pluralize.underscore.to_sym
113
+
114
+ @papermill_associations.merge!({assoc => {:class => asset_class}})
115
+ @papermill_options = Papermill::PAPERMILL_DEFAULTS.deep_merge(options)
116
+ association_finder = assoc.to_s + "_finder"
117
+ # using finder_sql because ActiveRecord chokes with STI on polymorphic tables. (Stupidely uses class.to_s instead of class.sti_name in association, god knows when it will get fixed, but tickets seems on the way for rails 3.0)
118
+ has_many association_finder, :finder_sql => 'SELECT * FROM papermill_assets WHERE papermill_assets.assetable_id = #{id} AND papermill_assets.assetable_type = "#{self.class.sti_name}" AND papermill_assets.type ' + (asset_class == PapermillAsset ? "IS NULL" : %{= "#{asset_class.to_s}"}) + ' ORDER BY papermill_assets.position'
119
+ after_create :rebase_assets
120
+ # reinventing the wheel because ActiveRecord chokes on :finder_sql with associations
121
+ # TODO Clean the mess
122
+ define_method assoc do |*options|
123
+ klass = self.class.papermill_associations[assoc.to_sym][:class]
124
+ options = options.first || {}
125
+ conditions = {
126
+ :assetable_type => self.class.sti_name,
127
+ :assetable_id => self.id,
128
+ }.merge(options.delete(:conditions) || {})
129
+ order = (options.delete(:order) || "position ASC")
130
+ conditions.merge!({:type => klass.to_s}) unless klass == PapermillAsset
131
+ conditions.merge!({:assetable_key => options[:key].to_s}) if options[:key]
132
+ conditions.merge!({:type => options[:class_name]}) if options[:class_name]
133
+ asset_class.find(:all, :conditions => conditions, :order => order)
134
+ end
135
+
136
+ after_destroy :remove_papermill_folder
137
+ class_eval <<-EOV
138
+ include Papermill::InstanceMethods
139
+ EOV
140
+ end
141
+
142
+ def inherited(subclass)
143
+ subclass.instance_variable_set("@papermill_options", @papermill_options)
144
+ subclass.instance_variable_set("@papermill_associations", @papermill_associations)
145
+ super
146
+ end
147
+ end
148
+
149
+ module InstanceMethods
150
+ attr_writer :timestamp
151
+ def timestamp
152
+ @timestamp ||= "-#{(Time.now.to_f * 1000).to_i.to_s[4..-1]}"
153
+ end
154
+
155
+ def interpolated_path(with = {}, up_to = nil)
156
+ Papermill::papermill_interpolated_path({
157
+ ":assetable_type" => self.class.sti_name.underscore.pluralize,
158
+ ":assetable_id" => self.id
159
+ }.merge(with), up_to)
160
+ end
161
+
162
+ private
163
+
164
+ def rebase_assets
165
+ return true unless timestamp
166
+ PapermillAsset.find(:all, :conditions => {:assetable_id => self.timestamp}).each do |asset|
167
+ if asset.created_at < 2.hours.ago
168
+ asset.destroy
169
+ else
170
+ asset.update_attribute(:assetable_id, self.id)
171
+ end
172
+ end
173
+ system "mv #{interpolated_path({':assetable_id' => timestamp}, ':assetable_id')}/ #{interpolated_path({}, ':assetable_id')}/"
174
+ true
175
+ end
176
+
177
+ def remove_papermill_folder
178
+ system "rm -rf #{interpolated_path({}, ':assetable_id')}/"
179
+ true
180
+ end
181
+ end
182
+ end
data/papermill.gemspec ADDED
@@ -0,0 +1,77 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{papermill}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Benoit B\303\251n\303\251zech"]
12
+ s.date = %q{2009-08-30}
13
+ s.description = %q{Paperclip wrapper}
14
+ s.email = %q{benoit.benezech@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "MIT-LICENSE",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "app/controllers/papermill_controller.rb",
25
+ "app/views/papermill/_asset.html.erb",
26
+ "app/views/papermill/_raw_asset.html.erb",
27
+ "app/views/papermill/_thumbnail_asset.html.erb",
28
+ "config/locale/papermill.yml",
29
+ "config/routes.rb",
30
+ "generators/papermill/USAGE",
31
+ "generators/papermill/papermill_generator.rb",
32
+ "generators/papermill/templates/migrate/papermill_migration.rb.erb",
33
+ "init.rb",
34
+ "install.rb",
35
+ "lib/core_extensions.rb",
36
+ "lib/papermill.rb",
37
+ "lib/papermill/form_builder.rb",
38
+ "lib/papermill/papermill_asset.rb",
39
+ "lib/papermill/papermill_helper.rb",
40
+ "lib/papermill/papermill_module.rb",
41
+ "papermill.gemspec",
42
+ "public/.DS_Store",
43
+ "public/flashs/swfupload.swf",
44
+ "public/images/.DS_Store",
45
+ "public/images/papermill/.DS_Store",
46
+ "public/images/papermill/background.png",
47
+ "public/images/papermill/container-background.jpg",
48
+ "public/images/papermill/delete.png",
49
+ "public/images/papermill/upload-blank.png",
50
+ "public/images/papermill/upload.png",
51
+ "public/javascripts/papermill.js",
52
+ "public/stylesheets/papermill.css",
53
+ "tasks/papermill_tasks.rake",
54
+ "test/papermill_test.rb",
55
+ "test/test_helper.rb",
56
+ "uninstall.rb"
57
+ ]
58
+ s.homepage = %q{http://github.com/BBenezech/papermill}
59
+ s.rdoc_options = ["--charset=UTF-8"]
60
+ s.require_paths = ["lib"]
61
+ s.rubygems_version = %q{1.3.5}
62
+ s.summary = %q{Paperclip wrapper}
63
+ s.test_files = [
64
+ "test/papermill_test.rb",
65
+ "test/test_helper.rb"
66
+ ]
67
+
68
+ if s.respond_to? :specification_version then
69
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
70
+ s.specification_version = 3
71
+
72
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
73
+ else
74
+ end
75
+ else
76
+ end
77
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,89 @@
1
+ /*
2
+ Papermill SWFUpload wrapper
3
+ You'll need jQuery or a **very** little bit of rewriting for native/prototype
4
+ */
5
+
6
+ notify = function(message, type) {
7
+ // wrap with your own javascript alert system (here is the thing for jGrowl)
8
+ //if(type == "notice") { jQuery.noticeAdd({ text: message, stayTime: 4000, stay: false, type: type }) }
9
+ //if(type == "warning") { jQuery.noticeAdd({ text: message, stayTime: 9000, stay: false, type: type }) }
10
+ //if(type == "error") { jQuery.noticeAdd({ text: message, stayTime: 20000, stay: false, type: type }) }
11
+
12
+ // or simply
13
+ alert(type + ": " + message)
14
+ }
15
+
16
+
17
+ var Upload = {
18
+ // The total number of files queued with SWFUpload
19
+ files_queued: 0,
20
+
21
+ set_recipient_id: function(dom_id) {
22
+ this.recipient_id = dom_id
23
+ },
24
+ file_dialog_complete: function(num_selected, num_queued)
25
+ {
26
+ // SwfUpload doesn't order uploads by name out of the box...
27
+ this.sorted_queue = [];
28
+ this.index = 0;
29
+ if (num_queued > 0) {
30
+ file_queue = [];
31
+ global_index = 0;
32
+ index = 0;
33
+ do {
34
+ file = this.callFlash("GetFileByIndex", [global_index]);
35
+ if(file != null && file.filestatus == -1) {
36
+ file_queue[index] = file;
37
+ index++;
38
+ }
39
+ global_index++;
40
+ } while (file != null);
41
+ this.sorted_queue = file_queue.sort(function(a,b){
42
+ if(b.name < a.name){return (1)}
43
+ })
44
+ self = this;
45
+ jQuery(this.sorted_queue).each( function(index, file) {
46
+ li = jQuery('<li></li>').attr({ 'id': file.id, 'class': 'swfupload' });
47
+ li.append(jQuery('<span></span>').attr('class', 'name').html(file.name.substring(0, 10) + '...'));
48
+ li.append(jQuery('<span></span>').attr('class', 'status').html(SWFUPLOAD_PENDING));
49
+ li.append(jQuery('<span></span>').attr('class', 'progress').append('<span></span>'));
50
+
51
+ if(self.settings.file_queue_limit == 1) {
52
+ jQuery("#" + self.settings.upload_id).html(li);
53
+ } else {
54
+ jQuery("#" + self.settings.upload_id).append(li);
55
+ }
56
+ })
57
+ this.startUpload(this.sorted_queue[this.index++].id);
58
+ }
59
+ },
60
+
61
+ upload_start: function(file)
62
+ {
63
+ jQuery('#' + file.id + ' .status').html(SWFUPLOAD_LOADING);
64
+ },
65
+ upload_progress: function(file, bytes, total)
66
+ {
67
+ percent = Math.ceil((bytes / total) * 100);
68
+ jQuery('#' + file.id + ' .progress span').width(percent + '%');
69
+ },
70
+ upload_error: function(file, code, message)
71
+ {
72
+ notify(SWFUPLOAD_ERROR + " " + file.name + " (" + message + " [" + code + "])", "error");
73
+ jQuery('#' + file.id).remove();
74
+ },
75
+ upload_success: function(file, data)
76
+ {
77
+ jQuery('#' + file.id).replaceWith(jQuery(data));
78
+ },
79
+ upload_complete: function(file)
80
+ {
81
+ Upload.files_queued -= 1;
82
+ if(this.sorted_queue[this.index]) {
83
+ this.startUpload(this.sorted_queue[this.index++].id)
84
+ }
85
+ },
86
+ file_queue_error: function(file, error_code, message) {
87
+ upload_error(file, error_code, message)
88
+ }
89
+ }
@@ -0,0 +1,33 @@
1
+ .papermill a:hover { background:none; color:inherit; }
2
+ .papermill a img { border:0px; }
3
+ .papermill li:hover { border-color:blue; }
4
+ .papermill li a { display:block; }
5
+ .papermill .progress { display:block; border:1px solid #C2E3EF; text-align:left; height:6px; }
6
+ .papermill .progress span { background:#7BB963; height:6px; width:0; display:block; }
7
+
8
+ .papermill-thumb-container li { border:0px solid transparent; min-height:25px; min-width:25px; }
9
+ .papermill-thumb-container { position:relative; border:5px solid #EEE; padding:4px; overflow-x:hidden; }
10
+ .papermill-thumb-container li { display:block; float:left; position:relative; }
11
+ .papermill-thumb-container .delete { position:absolute; bottom:5px; right:5px; }
12
+ .papermill-thumb-container span { display:block; }
13
+ .papermill-thumb-container .name { font-size:10px; overflow:hidden; font-weight:bold; }
14
+ .papermill-thumb-container .infos { font-size:8px; overflow:hidden; }
15
+ .papermill-thumb-container .status { margin-bottom:10px; }
16
+
17
+ .papermill-asset-container { border:1px solid #EEE; padding:3px; }
18
+ .papermill-asset-container li { display:block; height:22px; }
19
+ .papermill-asset-container .swfupload .name { margin-left:21px; }
20
+ .papermill-asset-container .name { float:left; }
21
+ .papermill-asset-container .status { margin-left:5px; float:left; }
22
+ .papermill-asset-container .progress { float:left; margin-top:6px; margin-left:5px; width:100px; }
23
+ .papermill-asset-container .delete { float:left; margin-top:2px; margin-right:5px; }
24
+
25
+ .papermill-asset-container.papermill-multiple-items { padding-left:10px; border-left:5px solid #EEE; min-height:40px; }
26
+ .papermill-asset-container.papermill-multiple-items li { cursor:row-resize; }
27
+ .papermill-thumb-container.papermill-multiple-items li { cursor:move; }
28
+ .papermill-asset-container.papermill-unique-item { padding-left:5px; min-height:22px; }
29
+
30
+ /* Need some backgrounds?
31
+ .papermill li { background:transparent url(/images/papermill/background.png) repeat top left; }
32
+ .papermill-thumb-container { background:transparent url(/images/papermill/container-background.jpg) repeat top left; }
33
+ */
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,8 @@
1
+ require 'test_helper'
2
+
3
+ class PapermillTest < ActiveSupport::TestCase
4
+ # Replace this with your real tests.
5
+ test "the truth" do
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'active_support'
3
+ require 'active_support/test_case'
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: BBenezech-papermill
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - "Benoit B\xC3\xA9n\xC3\xA9zech"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-30 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Paperclip wrapper
17
+ email: benoit.benezech@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - .gitignore
26
+ - MIT-LICENSE
27
+ - README.rdoc
28
+ - Rakefile
29
+ - VERSION
30
+ - app/controllers/papermill_controller.rb
31
+ - app/views/papermill/_asset.html.erb
32
+ - app/views/papermill/_raw_asset.html.erb
33
+ - app/views/papermill/_thumbnail_asset.html.erb
34
+ - config/locale/papermill.yml
35
+ - config/routes.rb
36
+ - generators/papermill/USAGE
37
+ - generators/papermill/papermill_generator.rb
38
+ - generators/papermill/templates/migrate/papermill_migration.rb.erb
39
+ - init.rb
40
+ - install.rb
41
+ - lib/core_extensions.rb
42
+ - lib/papermill.rb
43
+ - lib/papermill/form_builder.rb
44
+ - lib/papermill/papermill_asset.rb
45
+ - lib/papermill/papermill_helper.rb
46
+ - lib/papermill/papermill_module.rb
47
+ - papermill.gemspec
48
+ - public/.DS_Store
49
+ - public/flashs/swfupload.swf
50
+ - public/images/.DS_Store
51
+ - public/images/papermill/.DS_Store
52
+ - public/images/papermill/background.png
53
+ - public/images/papermill/container-background.jpg
54
+ - public/images/papermill/delete.png
55
+ - public/images/papermill/upload-blank.png
56
+ - public/images/papermill/upload.png
57
+ - public/javascripts/papermill.js
58
+ - public/stylesheets/papermill.css
59
+ - tasks/papermill_tasks.rake
60
+ - test/papermill_test.rb
61
+ - test/test_helper.rb
62
+ - uninstall.rb
63
+ has_rdoc: false
64
+ homepage: http://github.com/BBenezech/papermill
65
+ licenses:
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --charset=UTF-8
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: "0"
76
+ version:
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: "0"
82
+ version:
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.5
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Paperclip wrapper
90
+ test_files:
91
+ - test/papermill_test.rb
92
+ - test/test_helper.rb