magick_title 0.1.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.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ .DS_Store
4
+ Gemfile.lock
5
+ pkg/*
6
+ test/dummy/public/system
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in magick_title.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ Magick Title
2
+ ============
3
+
4
+ Want beautiful browser-compatible custom-smoothed & kerned fonts? Magick Title delivers just that by using imagemagick to generate titles based on the options you provide.
5
+
6
+ ** ----- under construction! ----- **
7
+
8
+ Usage
9
+ -----
10
+
11
+ Using MagickTitle is easy:
12
+
13
+ MagickTitle.say("Hello!").to_html
14
+
15
+ # outputs
16
+ # <h1><img src="/system/titles/hello.png" alt="Bienvenida al mundo de 28 Buenos Días " class="magick-title"></h1>
17
+
18
+ Without the h1 tag:
19
+
20
+ MagickTitle.say("Hello!").to_html(false)
21
+
22
+ # outputs
23
+ # <img src="/system/titles/hello.png" alt="Bienvenida al mundo de 28 Buenos Días " class="magick-title">
24
+
25
+
26
+ To just get an instance of MagickTitle::Image:
27
+
28
+ title = MagickTitle.say("Hello!")
29
+
30
+ puts title.filename #=> "hello.png"
31
+ puts title.url #=> "/system/titles/hello.png"
32
+
33
+
34
+ More to come!
35
+
36
+
37
+ To Do
38
+ -----
39
+
40
+ * Write tests
41
+ * Write documentation
42
+ * Auto ActiveRecord integration (this will be a seperate HasImage gem)
43
+ * Clean up and publish demo app
44
+
45
+
46
+ License
47
+ -------
48
+
49
+ Copyright (c) 2011 Spencer Steffen, released under the New BSD License All rights reserved.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ require 'rake/testtask'
3
+
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test' << 'lib'
8
+ t.verbose = true
9
+ end
10
+
11
+ desc "Default Task"
12
+ task :default => [ :test ]
@@ -0,0 +1,17 @@
1
+ class Hash
2
+ # Stolen from rails
3
+ def symbolize_keys
4
+ self.inject({}){|result, (key, value)|
5
+ new_key = case key
6
+ when String then key.to_sym
7
+ else key
8
+ end
9
+ new_value = case value
10
+ when Hash then value.symbolize_keys
11
+ else value
12
+ end
13
+ result[new_key] = new_value
14
+ result
15
+ }
16
+ end
17
+ end
@@ -0,0 +1,169 @@
1
+ require 'fileutils' unless defined?(FileUtils)
2
+
3
+ module MagickTitle
4
+
5
+ class Image
6
+
7
+ # The hash of options used for building
8
+ attr_accessor :text
9
+
10
+ # The hash of options used for building
11
+ # This hash is subclassed as Options and has some fancy features
12
+ attr_accessor :options
13
+
14
+ # File path to destination folder
15
+ attr_accessor :path
16
+
17
+ # Returns the filename of the title
18
+ attr_reader :filename
19
+
20
+ # Relative url to the image
21
+ attr_reader :url
22
+
23
+
24
+ # Initializes a new image title with a string
25
+ def initialize(text="", opts={})
26
+ update(text, opts)
27
+ super
28
+ end
29
+
30
+
31
+ # updates the image title to reflect new text
32
+ def update(text, opts={})
33
+ @text = text
34
+ return false unless valid?
35
+ @options = (@options || MagickTitle.options).merge(opts.symbolize_keys)
36
+ @filename = unique_filename(@text)
37
+ @path = options.destination
38
+ @url = File.join((@path.match(/public(\/.*)/) || ['', './'])[1].to_s, @filename)
39
+ end
40
+
41
+
42
+
43
+ # saves title and generates image
44
+ def save
45
+ return false unless valid?
46
+ FileUtils.mkdir_p(path)
47
+ run('convert', title_command_string)
48
+ File.exists?(fullpath)
49
+ end
50
+
51
+
52
+ # Checks if the image title is valid
53
+ def valid?
54
+ 1 < @text.strip.length
55
+ end
56
+
57
+
58
+ # Returns the full path to the file
59
+ def fullpath
60
+ File.join(path, filename)
61
+ end
62
+
63
+
64
+
65
+ def to_html(opts={})
66
+ opts = { :parent => nil } if opts === false
67
+ opts = {
68
+ :parent => {
69
+ :tag => "h1",
70
+ :class => "image-title"
71
+ },
72
+ :class => "magick-title",
73
+ :alt => text,
74
+ :src => url
75
+ }.merge(opts)
76
+ parent = opts.delete(:parent)
77
+ parent = { :tag => parent } if parent.is_a?(String)
78
+ tag = %(<img #{hash_to_attributes(opts)}/>)
79
+ if parent
80
+ ptag = parent.delete(:tag)
81
+ tag = %(<#{ptag} #{hash_to_attributes(parent)}>#{tag}</#{ptag}>)
82
+ end
83
+ tag
84
+ end
85
+
86
+ def hash_to_attributes(hash)
87
+ attributes = ""
88
+ hash.each { |key, value| attributes << key.to_s << "=\"" << value << "\" " if value and 0 < value.length }
89
+
90
+ puts "* 88"
91
+ puts attributes.inspect
92
+
93
+ attributes
94
+ end
95
+
96
+
97
+ private
98
+
99
+
100
+ # builds an imagemagick identify command to the specified fild
101
+ def info_command_string(file)
102
+ "-format '%b,%w,%h' #{file}"
103
+ end
104
+
105
+ # builds an imagemagick command based on the supplied options
106
+ def title_command_string
107
+ %(
108
+ -trim
109
+ -antialias
110
+ -background '#{options.background_color}#{options.background_alpha}'
111
+ -fill '#{options.color}'
112
+ -font #{options.font_path}/#{options.font}
113
+ -pointsize #{options.font_size}
114
+ -size #{options.width}x#{options.height}
115
+ -weight #{options.weight}
116
+ -kerning #{options.kerning}
117
+ caption:'#{@text}'
118
+ #{fullpath}
119
+ ).gsub(/[\n\r\s]+/, ' ')
120
+ end
121
+
122
+ # Cleans and runs the supplied command
123
+ # (stolen from paperclip)
124
+ def run(cmd, params)
125
+ command = [path_for_command(cmd), params.to_s.gsub(/\\|\n|\r/, '')].join(" ")
126
+ puts command if options.log_command
127
+ `#{command}`
128
+ end
129
+
130
+ # returns the `bin` path to the command
131
+ def path_for_command(command)
132
+ path = [options.command_path, command].compact
133
+ File.join(*path)
134
+ end
135
+
136
+ # converts the text to a useable filename
137
+ # defaults to a random string if the filename is blank after replacing illegal chars
138
+ def fileize_text(text)
139
+ file = text.to_s.downcase.gsub(/[^a-z0-9\s\-\_]/, '').strip.gsub(/[\s\-\_]+/, '_')
140
+ unless 0 < file.length
141
+ o = [('a'..'z'),('0'..'9')].map{|i| i.to_a}.flatten
142
+ file = (0..31).map{ o[rand(o.length)] }.join
143
+ end
144
+ file
145
+ end
146
+
147
+
148
+ # creates a unique filename for the supplied text
149
+ def unique_filename(text)
150
+ file = fileize_text(text)
151
+ exists = exists_in_destination? file
152
+ dupe, count = nil, 0
153
+ while exists do
154
+ count += 1
155
+ dupe = "#{file}_#{count}"
156
+ exists = exists_in_destination? dupe
157
+ end
158
+ "#{dupe || file}.#{options.extension}"
159
+ end
160
+
161
+ # Checks if file exists in the destination option
162
+ def exists_in_destination?(file)
163
+ file += options.extension unless file.match(/\.[a-z]{3,4}$/)
164
+ File.exists?(File.join(options.destination, file))
165
+ end
166
+
167
+ end # Image
168
+
169
+ end # MagickTitle
@@ -0,0 +1,72 @@
1
+ module MagickTitle
2
+
3
+ class Options < Hash
4
+
5
+ # Initializes the options hash with the defaults
6
+ def initialize
7
+ super
8
+ default!
9
+ end
10
+
11
+ # Clears current options and resets to the defaults
12
+ def default!
13
+ clear
14
+ store :root, defined?(::Rails) ? ::Rails.root.to_s : "./"
15
+ merge! defaults
16
+ end
17
+
18
+ # A shortcut to [:root]
19
+ def root
20
+ @root ||= fetch(:root)
21
+ end
22
+
23
+ # The default options hash
24
+ def defaults
25
+ {
26
+ :root => "./",
27
+ :field_name => 'title',
28
+ :font => "HelveticaNeueLTStd-UltLt.otf",
29
+ :font_path => Proc.new{ File.join MagickTitle.root, "fonts" },
30
+ :font_size => 50,
31
+ :destination => Proc.new{ File.join MagickTitle.root, "public/system/titles" },
32
+ :extension => "png",
33
+ :width => 800,
34
+ :height => nil,
35
+ :background_color => '#ffffff',
36
+ :background_alpha => '00',
37
+ :color => '#68962c',
38
+ :weight => 400,
39
+ :kerning => 0,
40
+ :command_path => nil,
41
+ :log_command => false,
42
+ :cache => true
43
+ }
44
+ end
45
+
46
+ # Sets and option and converts its key to a symbol
47
+ def []=(key, value)
48
+ key = key.to_sym
49
+ raise ArgumentError, "MagickTitle::InvalidOption: #{key} is not an available option." unless defaults.keys.include?(key)
50
+ super(key, value)
51
+ end
52
+
53
+ # Turns the key into a symbol and returns the requested value
54
+ def [](key)
55
+ val = fetch key.to_sym
56
+ val.is_a?(Proc) ? val.call : val
57
+ end
58
+
59
+ # Retrieve a saved setting or return nil if it doesn't exist.
60
+ #
61
+ # Options.foo #=> "bar"
62
+ # Options.fuz #=> method missing error
63
+ #
64
+ def method_missing(method, *args, &block)
65
+ key = method.to_sym
66
+ val = fetch(key) # if has_key? key
67
+ val.nil? ? nil : val.is_a?(Proc) ? val.call : val
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,3 @@
1
+ module MagickTitle
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,40 @@
1
+ require 'magick_title/hash'
2
+ require 'magick_title/options'
3
+ require 'magick_title/image'
4
+
5
+ module MagickTitle
6
+
7
+ extend self
8
+
9
+ # A shortcut to options[:root]
10
+ def root
11
+ options.root
12
+ end
13
+
14
+ # Returns the options hash
15
+ def options
16
+ @options ||= Options.new
17
+ end
18
+
19
+ # Sets the options hash
20
+ def options=(value)
21
+ raise ArgumentError, "Magick Title options must be a Hash" unless value.is_a?(Hash)
22
+ value.each_pair do |key, value|
23
+ options[key] = value
24
+ end
25
+ options
26
+ end
27
+
28
+ # A helper tag to create or fetch and image title
29
+ #
30
+ # MagickTitle.image("Hello!")
31
+ # MagickTitle.say("Hi", :refresh => true)
32
+ #
33
+ def image(text, opts={})
34
+ title = ::MagickTitle::Image.new(text, opts)
35
+ title.save unless title.options.cache && File.exists?(title.fullpath)
36
+ title
37
+ end
38
+ alias :say :image
39
+
40
+ end # MagickTitle
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "magick_title/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "magick_title"
7
+ s.version = MagickTitle::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Spencer Steffen"]
10
+ s.email = ["spencer@citrusme.com"]
11
+ s.homepage = "https://github.com/citrus/magick_title"
12
+ s.summary = %q{Converts text to an image using imagemagick.}
13
+ s.description = %q{Want beautiful browser-compatible custom-smoothed & kerned fonts? Magick Title delivers just that by using imagemagick to generate titles based on the options you provide.}
14
+
15
+ s.rubyforge_project = "magick_title"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_development_dependency 'shoulda', '2.11.3'
23
+ s.add_development_dependency 'rack-test', '0.5.7'
24
+ s.add_development_dependency 'sinatra', '1.1.0'
25
+
26
+ end
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "sinatra"
4
+ gem "magick_title", :path => File.expand_path("../../../", __FILE__)
data/test/dummy/app.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'bundler/setup'
2
+ Bundler.require if defined?(Bundler)
3
+
4
+
5
+ MagickTitle.options = { :font_size => 56 }
6
+
7
+
8
+ use Rack::Static
9
+
10
+ get '/' do
11
+ erb :index
12
+ end
13
+
14
+ post '/' do
15
+ @image_title = MagickTitle::Image.new(params[:text], params[:options])
16
+ @success = @image_title.save
17
+ erb :index
18
+ end
Binary file
@@ -0,0 +1,31 @@
1
+ body {
2
+ font-family: "HelveticaNeue", Helvetica, Arial, sans-serif;
3
+ color: #080603;
4
+ }
5
+ a {
6
+ text-decoration: none;
7
+ color: #68962c;
8
+ }
9
+ .container {
10
+ width: 500px;
11
+ margin: 0 auto;
12
+ }
13
+ .header {
14
+ border-bottom: 1px solid #ddd;
15
+ }
16
+ .header a {
17
+ display: inline-block;
18
+ padding: 4px 10px;
19
+ background-color: #eee;
20
+ }
21
+
22
+ .flash {
23
+ padding: 10px 0;
24
+ border-bottom: 1px solid #ddd;
25
+ }
26
+ .flash.notice {
27
+ color: #68962c;
28
+ }
29
+ .flash.error {
30
+ color: #c00e0e;
31
+ }
@@ -0,0 +1,42 @@
1
+ <% if @success && @image_title %>
2
+ <h1>Success!</h1>
3
+ <img src=<%= @image_title.url.inspect %> alt=<%= @image_title.text.inspect %>/>
4
+ <% elsif @success === false %>
5
+ <h1>Failed.</h1>
6
+ <% else %>
7
+ <%= MagickTitle.say("Hello!").to_html %>
8
+ <h2><%= MagickTitle.say("Welcome to MagickTitle!", :cache => false, :font => 'PermanentMarker.ttf', :font_size => 20, :color => '#999').to_html(false) %></h2>
9
+ <% end %>
10
+
11
+
12
+ <h2>Generate an image title!</h2>
13
+
14
+ <form action="/" method="post">
15
+ <p>
16
+ <label for="text">Text:</label>
17
+ <input type="text" name="text" id="name"/>
18
+ </p>
19
+ <p>
20
+ <label for="options_font">Font:</label>
21
+ <select name="options[font]" id="options_font">
22
+ <option value="Cuprum.ttf">Cuprum</option>
23
+ <option value="HelveticaNeueLTStd-UltLt.otf">Helvetica Neue Ultra Light</option>
24
+ <option value="PermanentMarker.ttf">Permanent Marker</option>
25
+
26
+ </select>
27
+ </p>
28
+
29
+ <p>
30
+ <label for="options_color">Color:</label>
31
+ <select name="options[color]" id="options_color">
32
+ <option value="#ff0000">Red</option>
33
+ <option value="#0000ff">Blue</option>
34
+ <option value="#000000">Black</option>
35
+ <option value="#00ff00">Green</option>
36
+ </select>
37
+ </p>
38
+
39
+ <p>
40
+ <input type="submit" value="generate"/>
41
+ </p>
42
+ </form>
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Magick Title Demo</title>
5
+ <link rel="stylesheet" type="text/css" href="styles.css" />
6
+ </head>
7
+ <body>
8
+
9
+ <div class="container">
10
+
11
+ <%= yield %>
12
+
13
+ </div>
14
+
15
+ </body>
16
+ </html>
data/test/helper.rb ADDED
@@ -0,0 +1,6 @@
1
+ ENV["environment"] = "test"
2
+
3
+ require 'test/unit'
4
+ #require 'rack/test'
5
+ require 'shoulda'
6
+ require 'magick_title'
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ class TestImage < Test::Unit::TestCase
4
+
5
+ def setup
6
+ MagickTitle.options[:root] = File.expand_path("../dummy", __FILE__)
7
+ end
8
+
9
+ context "a valid title" do
10
+
11
+ setup do
12
+ @title = MagickTitle.say("hello!")
13
+ end
14
+
15
+ should "return an image title" do
16
+ assert @title.is_a?(MagickTitle::Image)
17
+ assert File.exists?(@title.fullpath)
18
+ end
19
+
20
+ should "create an html img tag" do
21
+ tag = @title.to_html
22
+ assert tag.is_a?(String)
23
+ assert tag.match("src=#{@title.url.inspect}")
24
+ assert tag.match("alt=#{@title.text.inspect}")
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ require 'helper'
2
+
3
+ class TestImage < Test::Unit::TestCase
4
+
5
+ def setup
6
+ MagickTitle.options[:root] = File.expand_path("../dummy", __FILE__)
7
+ end
8
+
9
+
10
+ should "not allow empty string" do
11
+ @title = MagickTitle::Image.new("")
12
+ assert !@title.valid?
13
+ assert !@title.save
14
+ end
15
+
16
+
17
+ context "a valid image title" do
18
+
19
+ setup do
20
+ @title = MagickTitle::Image.new("hello")
21
+ end
22
+
23
+ should "allow valid string" do
24
+ assert @title.valid?
25
+ end
26
+
27
+ should "save a valid title" do
28
+ assert @title.save
29
+ assert File.exists?(@title.fullpath)
30
+ end
31
+
32
+ end
33
+
34
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: magick_title
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Spencer Steffen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-02-24 00:00:00 -08:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: shoulda
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - "="
23
+ - !ruby/object:Gem::Version
24
+ version: 2.11.3
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack-test
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - "="
34
+ - !ruby/object:Gem::Version
35
+ version: 0.5.7
36
+ type: :development
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: sinatra
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - "="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.1.0
47
+ type: :development
48
+ version_requirements: *id003
49
+ description: Want beautiful browser-compatible custom-smoothed & kerned fonts? Magick Title delivers just that by using imagemagick to generate titles based on the options you provide.
50
+ email:
51
+ - spencer@citrusme.com
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - .gitignore
60
+ - Gemfile
61
+ - README.md
62
+ - Rakefile
63
+ - lib/magick_title.rb
64
+ - lib/magick_title/hash.rb
65
+ - lib/magick_title/image.rb
66
+ - lib/magick_title/options.rb
67
+ - lib/magick_title/version.rb
68
+ - magick_title.gemspec
69
+ - test/dummy/Gemfile
70
+ - test/dummy/app.rb
71
+ - test/dummy/fonts/Cuprum.ttf
72
+ - test/dummy/fonts/HelveticaNeueLTStd-UltLt.otf
73
+ - test/dummy/fonts/PermanentMarker.ttf
74
+ - test/dummy/public/styles.css
75
+ - test/dummy/views/index.erb
76
+ - test/dummy/views/layout.erb
77
+ - test/helper.rb
78
+ - test/test_image_title.rb
79
+ - test/test_magick_title.rb
80
+ has_rdoc: true
81
+ homepage: https://github.com/citrus/magick_title
82
+ licenses: []
83
+
84
+ post_install_message:
85
+ rdoc_options: []
86
+
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ requirements: []
102
+
103
+ rubyforge_project: magick_title
104
+ rubygems_version: 1.5.0
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Converts text to an image using imagemagick.
108
+ test_files:
109
+ - test/dummy/Gemfile
110
+ - test/dummy/app.rb
111
+ - test/dummy/fonts/Cuprum.ttf
112
+ - test/dummy/fonts/HelveticaNeueLTStd-UltLt.otf
113
+ - test/dummy/fonts/PermanentMarker.ttf
114
+ - test/dummy/public/styles.css
115
+ - test/dummy/views/index.erb
116
+ - test/dummy/views/layout.erb
117
+ - test/helper.rb
118
+ - test/test_image_title.rb
119
+ - test/test_magick_title.rb