le_meme 0.0.8 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d259d15403afedfcf9afff3d29004ea4d778f180
4
- data.tar.gz: 509820a6f6e562852d82e0494ad3e4e2f81be81e
3
+ metadata.gz: 855301d19080a1db16d6df06321f7dbfcc8bb712
4
+ data.tar.gz: 0596203d86d7345eda25226571cec379b6b12ac0
5
5
  SHA512:
6
- metadata.gz: a432b9ba98e2390e5409a1dd327a4d6ee3b9d059c3b76b2b0185e71e4833e16841a394e175efc9b8509d668abd9a1473d0ed2176b7b84be3b562e0b2a3c202a6
7
- data.tar.gz: 82c70074224e66c354f074d1786747c1d820756371c7dd403337136a994ddaede68f2a83094f64d2821614eb185a7bf4bff806099530e01684968e66449e017c
6
+ metadata.gz: 0bdd71930c20ecd3b8aa3bea58e193db74e4eeddd69c2a3af25db7111e3e1538163b52919be9bc9c0a0dd95d7c0ce7014ca4353224fdc43fe6f707062366e891
7
+ data.tar.gz: de6f304bbaeca7733b128b49717b9e012af2d062b9a0d7d3d06760a04a0302f444846f58afcaba4a5967fa4dee60ebc87e66d4a4a6128093b23043763d2cf550
@@ -0,0 +1,5 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.1
3
+
4
+ Metrics/LineLength:
5
+ Enabled: false
data/README.md CHANGED
@@ -37,15 +37,20 @@ Should be straightforward enough for even the dankest memer.
37
37
  ### I want to make memes in my ruby application
38
38
  Easy enough!
39
39
 
40
+ #### Using a template
40
41
  ```ruby
41
42
  require 'le_meme'
43
+ LeMeme::MemeLib.new_with_default_memes.meme(template: 'maymay', top: 'Top text', bottom: 'Bottom Text').to_file
44
+ ```
42
45
 
43
- meme = LeMeme.new
46
+ #### Using any old image
44
47
 
45
- meme.m(top: 'dank memes!', bottom: 'bottom text')
48
+ ```ruby
49
+ require 'le_meme'
50
+ LeMeme::Meme.new('~/Desktop/to_be_memed.jpg', top: 'Top text', bottom: 'bottom text').to_file
46
51
  ```
47
52
 
48
- See the [docs](http://www.rubydoc.info/gems/le_meme) for all the shrektastic details
53
+ See the [docs](http://www.rubydoc.info/gems/le_meme) for all the memetastic details
49
54
 
50
55
  ## Contributing
51
56
 
@@ -60,12 +65,7 @@ Because the world needs more dank memes!
60
65
 
61
66
  Actually, because I wanted to take some time and clean up the core of [memebot](http://github.com/paradox460/memebot), and figured making the essential meme generation a gem was the best way to do it. Now I can spam my coworkers with memes in hipchat as well.
62
67
 
63
- ## TODO
64
- - [ ] Allow dynamic additon of memes to internal memecache
65
- - [ ] Test `meme` binary
66
-
67
- ## License
68
-
68
+ ## LICENSE
69
69
  ```
70
70
  Copyright (c) 2015 Jeff Sandberg
71
71
 
data/Rakefile CHANGED
@@ -5,4 +5,4 @@ RSpec::Core::RakeTask.new(:spec) do |task|
5
5
  task.rspec_opts = ['--color', '--format', 'd']
6
6
  end
7
7
 
8
- task :default => :spec
8
+ task default: :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'le_meme'
5
+ require 'pry'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ Pry.start
data/bin/meme CHANGED
@@ -1,61 +1,90 @@
1
- #!/Usr/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
+ require 'bundler/setup'
3
4
  require 'le_meme'
4
- require 'slop'
5
+ require 'optparse'
6
+ require 'pry'
5
7
 
6
- memegen = LeMeme.new
7
- opts = Slop.new(strict: true, help: true) do
8
- banner <<-HEREDOC
8
+ options = {}
9
+
10
+ if ARGV.empty?
11
+ exit(0) unless $stdout.tty?
12
+ $stdout.puts 'Usage: meme [options] [top-text] [bottom-text]'
13
+ $stdout.puts ' run -h for help'
14
+ exit(0)
15
+ end
16
+
17
+ memelib = LeMeme::MemeLib.new_with_default_memes
18
+
19
+ OptionParser.new do |opts|
20
+ opts.banner = <<-HEREDOC
9
21
  Usage: meme [options] [top-text] [bottom-text]
10
22
 
11
23
  Top and bottom may be set by the last 2 unprefixed arguments, or by their respective flags.
12
24
  If you don't specify a meme, either via image path or by template, we'll pick one for you.
13
25
  HEREDOC
14
- separator '---'
15
-
16
- on 't', 'top=', 'top text'
17
- on 'b', 'bottom=', 'bottom text.'
18
- on 'm', 'meme=', 'meme template you want to use, see --templates'
19
- on 'p', 'path=', 'path to an image to use for the meme'
20
- on 'w', 'watermark=', 'text to watermark the image'
21
- on 'o', 'outpath=', 'path to save the final meme to'
22
- on 'O', 'open', "Open the file in your system's default image viewer"
23
-
24
- on 'templates', 'list all the meme templates' do
25
- puts memegen.memes.keys.join("\n")
26
- exit
26
+
27
+ opts.separator '---'
28
+
29
+ opts.on('-tTOP', '--top=TOP', 'top text') do |top|
30
+ options[:top] = top
27
31
  end
28
- on 'v', 'version', 'display the current version' do
29
- $stdout.puts LeMeme::VERSION
30
- exit
32
+ opts.on('-bBOTTOM', '--bottom=BOTTOM', 'bottom text') do |bottom|
33
+ options[:bottom] = bottom
34
+ end
35
+ opts.on('-wWATERMARK', '--watermark=WATERMARK', 'watermark text') do |watermark|
36
+ options[:watermark] = watermark
31
37
  end
32
- end
33
- if ARGV.empty?
34
- $stdout.puts opts if $stdout.tty?
35
- exit(0)
36
- end
37
38
 
38
- opts.parse!
39
+ opts.separator ''
39
40
 
40
- top = opts[:top] || ARGV[0]
41
- bottom = opts[:bottom] || ARGV[1]
41
+ opts.on('-mTEMPLATE', '--meme=TEMPLATE', 'meme template you want to use. See --templates for list') do |template|
42
+ options[:template] = template
43
+ end
42
44
 
45
+ opts.on('-pPATH', '--path=PATH', 'path to image file to use') do |path|
46
+ options[:path] = path
47
+ end
48
+ opts.on('-oPATH', '--outpath=PATH', 'path to save generated meme') do |path|
49
+ options[:outpath] = path
50
+ end
51
+ opts.on('-O', '--open', 'open when finished') do |o|
52
+ options[:open] = o
53
+ end
43
54
 
44
- if opts[:path]
45
- output = memegen.meme(path: opts[:path], top: top, bottom: bottom, watermark: opts[:watermark], outpath: opts[:outpath])
46
- else
47
- name = opts[:meme].strip if opts[:meme]
48
- output = memegen.fast_meme(name: name, top: top, bottom: bottom, watermark: opts[:watermark], outpath: opts[:outpath])
49
- end
55
+ opts.separator ''
56
+
57
+ opts.on('--templates', 'list all the meme templates') do
58
+ puts memelib.memes.keys.join("\n")
59
+ exit(0)
60
+ end
61
+
62
+ opts.on('-h', '--help', 'prints this help') do
63
+ puts opts
64
+ exit(0)
65
+ end
66
+ end.parse!
67
+
68
+ top = options[:top] || ARGV[0]
69
+ bottom = options[:bottom] || ARGV[1]
70
+
71
+ meme = if options[:path]
72
+ LeMeme::Meme.new(options[:path], top: top, bottom: bottom, watermark: options[:watermark])
73
+ else
74
+ template = options[:template].nil? ? nil : options[:template].strip
75
+ memelib.meme(template: template, top: top, bottom: bottom, watermark: options[:watermark])
76
+ end
77
+
78
+ output = meme.to_file(options[:outpath]).path
50
79
 
51
- if opts[:open]
80
+ if options[:open]
52
81
  case RbConfig::CONFIG['host_os']
53
82
  when /mswin|mingw|cygwin/
54
- `start #{output}`
83
+ `start '#{output}'`
55
84
  when /darwin/
56
- `open -F #{output}`
85
+ `open -F '#{output}'`
57
86
  when /linux|bsd/
58
- `xdg-open #{output}`
87
+ `xdg-open '#{output}'`
59
88
  else
60
89
  $stderr.puts "Sorry, don't know how to open on your system! (#{RbConfig::Config['host_os']})"
61
90
  end
@@ -16,14 +16,16 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0")
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.7'
22
- spec.add_development_dependency 'rake', '~> 10.0'
23
- spec.add_development_dependency 'pry', '~> 0.10'
24
- spec.add_development_dependency 'rspec', '~> 3.1'
21
+ spec.required_ruby_version = '>= 2.1'
25
22
 
26
- spec.add_runtime_dependency 'rmagick', '~> 2.13'
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'pry'
26
+ spec.add_development_dependency 'pry-byebug'
27
+ spec.add_development_dependency 'rspec'
28
+
29
+ spec.add_runtime_dependency 'rmagick', '~> 2.15'
27
30
  spec.add_runtime_dependency 'word_wrapper', '~> 0.5.0'
28
- spec.add_runtime_dependency 'slop', '~> 3.6'
29
31
  end
@@ -1,184 +1,10 @@
1
- require 'le_meme/version'
2
1
  require 'rmagick'
3
2
  require 'word_wrapper'
4
- require 'pathname'
5
-
6
- # Create some dank memes
7
- #
8
- # @author Jeff Sandberg <paradox460@gmail.com>
9
- class LeMeme
10
- VALID_IMAGE_EXTENSIONS = /\.(jp[e]?g|png|gif)$/i
11
-
12
- attr_reader :memes
13
-
14
- # Create a new instance of LeMeme, for generating memes.
15
- #
16
- # @param [Array] Directories of images you want the gem to know about. Scrapes images in said directory
17
- # @return [String] description of returned object
18
- def initialize(*dirs)
19
- @memes = {}
20
- load_directory!
21
- dirs.each do |dir|
22
- load_directory!(dir)
23
- end
24
- end
25
-
26
- # Create a meme with the given text
27
- #
28
- # @param path [String] The path to the image file you want to annotate.
29
- # @param top [String] The text you want to appear on the top of the meme.
30
- # @param bottom [String] The text you want to appear on the bottom of the meme.
31
- # @param watermark [String] The watermark text. If nil it is omitted
32
- # @param outpath [String] Where do you want to put the generated meme. Defaults to /tmp/meme-<timestamp>.<extension>
33
- # @param nowrite [Boolean] Returns the meme as a blob (string) instead of writing to disk.
34
- # @return [String] Either the generated meme object (if nowrite) or a path to the meme
35
- def generate(path:, top: nil, bottom: nil, watermark: nil, outpath: nil, nowrite: false)
36
- top = (top || '').upcase
37
- bottom = (bottom || '').upcase
38
-
39
- path = Pathname.new(path).realpath
40
-
41
- canvas = Magick::ImageList.new(path)
42
-
43
- caption_meme(top, Magick::NorthGravity, canvas) unless top.empty?
44
- caption_meme(bottom, Magick::SouthGravity, canvas) unless bottom.empty?
45
-
46
- # Draw the watermark
47
- unless watermark.nil?
48
- watermark_draw = Magick::Draw.new
49
- watermark_draw.annotate(canvas, 0, 0, 0, 0, " #{watermark}") do
50
- self.font = 'Helvetica'
51
- self.fill = 'white'
52
- self.text_antialias(false)
53
- self.font_weight = 100
54
- self.gravity = Magick::SouthEastGravity
55
- self.pointsize = 10
56
- self.undercolor = 'hsla(0,0,0,.5)'
57
- end
58
- end
59
-
60
- output_path = outpath || "/tmp/meme-#{Time.now.to_i}#{path.extname}"
61
- if nowrite
62
- canvas.to_blob
63
- else
64
- canvas.write(output_path)
65
- output_path
66
- end
67
- end
68
- alias_method :meme, :generate
69
3
 
70
- # Create a meme, using the pre-loaded templates.
71
- # If no template is specified, randomly picks one
72
- #
73
- # @param name [String] Name of the template to use. See #memes
74
- # @param top [String] The text you want to appear on the top of the meme.
75
- # @param bottom [String] The text you want to appear on the bottom of the meme.
76
- # @param watermark [String] The watermark text. If nil it is omitted
77
- # @param outpath [String] Where do you want to put the generated meme. Defaults to /tmp/meme-<timestamp>.<extension>
78
- # @param nowrite [Boolean] Returns the meme as a blob (string) instead of writing to disk.
79
- # @return [String] Either the generated meme object (if nowrite) or a path to the meme
80
- def fast_meme(name: nil, top: nil, bottom: nil, watermark: nil, outpath: nil, nowrite: false)
81
- if name.nil?
82
- path = @memes[@memes.keys.sample]
83
- elsif @memes[name].nil?
84
- fail ArgumentError, "#{name} is not a pre-loaded meme"
85
- else
86
- path = @memes[name]
87
- end
88
- generate(path: path, top: top, bottom: bottom, watermark: watermark, outpath: outpath, nowrite: nowrite)
89
- end
90
- alias_method :m, :fast_meme
91
-
92
- private
93
-
94
- # Load all images in a directory as memes.
95
- # Last loaded directory overrides first, if there are name conflicts.
96
- #
97
- # @param directory [String] Directory to scrape.
98
- def load_directory!(directory = nil)
99
- directory = directory.nil? ? "#{File.join(File.dirname(File.expand_path(__FILE__)), '../memes')}/*.jpg" : "#{directory}/*"
100
- paths = Dir.glob(directory).select do |path|
101
- path =~ VALID_IMAGE_EXTENSIONS
102
- end
103
- @memes.merge!(paths.reduce({}) do |images, path|
104
- path = Pathname.new(path).realpath
105
- name = path.split.last.sub(VALID_IMAGE_EXTENSIONS, '').to_s
106
- images.merge(name => path)
107
- end)
108
- end
109
-
110
- # Caption a canvas
111
- #
112
- # @param text [String] The text to put on as a caption
113
- # @param gravity [Grav] RMagick Gravity Constant
114
- # @param canvas [Magick::ImageList] ImageList/Canvas to compose the text onto
115
- # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
116
- def caption_meme(text, gravity, canvas)
117
- text.gsub!('\\', '\\\\\\')
118
-
119
- # 28 is the biggest pointsize memes dont look like shit on
120
- min_pointsize = 28
121
- max_pointsize = 128
122
- current_pointsize = min_pointsize
123
- current_stroke = current_pointsize / 30.0
124
-
125
- max_width = canvas.columns - 20
126
- max_height = (canvas.rows / 2) - 20
127
-
128
- draw = Magick::Draw.new
129
- draw.font = File.join(File.dirname(File.expand_path(__FILE__)), '..', 'fonts', 'Impact.ttf')
130
- draw.font_weight = Magick::BoldWeight
131
- metrics = nil
132
-
133
- # Non-ragged word-wrap
134
- text = word_wrap(text)
135
-
136
- # Calculate out the largest pointsize that will fit
137
- loop do
138
- draw.pointsize = current_pointsize
139
- last_metrics = metrics
140
- metrics = draw.get_multiline_type_metrics(text)
141
-
142
- if metrics.width + current_stroke > max_width ||
143
- metrics.height + current_stroke > max_height ||
144
- current_pointsize > max_pointsize
145
- if current_pointsize > min_pointsize
146
- current_pointsize -= 1
147
- current_stroke = current_pointsize / 30.0
148
- metrics = last_metrics
149
- end
150
- break
151
- else
152
- current_pointsize += 1
153
- current_stroke = current_pointsize / 30.0
154
- end
155
- end
156
- # rubocop:disable Style/RedundantSelf
157
- draw.annotate(canvas, canvas.columns, canvas.rows - 10, 0, 0, text) do
158
- self.interline_spacing = -(current_pointsize / 5)
159
- self.stroke_antialias(true)
160
- self.stroke = 'black'
161
- self.fill = 'white'
162
- self.gravity = gravity
163
- self.stroke_width = current_stroke
164
- self.pointsize = current_pointsize
165
- end
166
- # rubocop:enable Style/RedundantSelf
167
- end
168
- # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
4
+ require 'le_meme/version'
5
+ require 'le_meme/meme'
6
+ require 'le_meme/meme_lib'
169
7
 
170
- # Wrap the text to fit on a meme
171
- # This basically uses the wordwrapper library, and then does some calculations to split super-long strings
172
- #
173
- # @param text [String] The text string to word-wrap.
174
- # @param col [Fixnum] The number of "columns" to wrap at
175
- # @return [String] The text, with the
176
- def word_wrap(text, col: 24)
177
- text.strip.gsub(/\n\r/, '\s')
178
- text = WordWrapper::MinimumRaggedness.new(col, text).wrap
179
- text = text.split("\n").map do |line|
180
- line.length > col ? line.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/, "\\1\\3\n").strip : line
181
- end * "\n"
182
- text.strip
183
- end
8
+ module LeMeme
9
+ IMAGE_EXTENSIONS = /\.(jp[e]?g|png|gif)$/i
184
10
  end
@@ -0,0 +1,107 @@
1
+ module LeMeme
2
+ # A single meme object
3
+ class Meme
4
+ attr_accessor(*%i(path top bottom watermark))
5
+ # @param [String, Pathanem] path Path to an image for the meme background
6
+ # @param [String] top: nil The text on the top of the meme
7
+ # @param [String] bottom: nil The text on the bottom of the meme
8
+ # @param [String] watermark: nil Watermark text
9
+ # @return [Meme] A new meme object
10
+ def initialize(path, top: nil, bottom: nil, watermark: nil)
11
+ @path = File.expand_path(path)
12
+ @top = top.to_s.upcase
13
+ @bottom = bottom.to_s.upcase
14
+ @watermark = watermark
15
+ @canvas = Magick::ImageList.new(@path)
16
+ end
17
+
18
+ # Outputs the meme to the file system
19
+ #
20
+ # @param [String] path = nil Where to save the meme
21
+ # @return [File] File object representing the meme
22
+ def to_file(path = nil)
23
+ path = File.expand_path(path.nil? ? "#{ENV['TMPDIR']}meme-#{Time.now.to_i}.jpg" : path)
24
+ generate!
25
+
26
+ file = File.new(path, 'w+')
27
+ @canvas.write(path)
28
+
29
+ file
30
+ end
31
+
32
+ # Get a binary string representing the meme
33
+ #
34
+ # @return [String]
35
+ def to_blob
36
+ generate!
37
+
38
+ @canvas.to_blob
39
+ end
40
+
41
+ private
42
+
43
+ def generate!
44
+ return if @generated
45
+ @generated = true
46
+ caption(@top, Magick::NorthGravity) unless @top.empty?
47
+ caption(@bottom, Magick::SouthGravity) unless @bottom.empty?
48
+ watermark unless watermark.nil?
49
+ end
50
+
51
+ # rubocop:disable Metrics/MethodLength
52
+ def caption(text, gravity)
53
+ text = word_wrap(text)
54
+ draw, pointsize = calculate_pointsize(text)
55
+
56
+ draw.annotate(@canvas, @canvas.columns, @canvas.rows - 10, 0, 0, text) do
57
+ self.interline_spacing = -(pointsize / 5)
58
+ stroke_antialias(true)
59
+ self.stroke = 'black'
60
+ self.fill = 'white'
61
+ self.gravity = gravity
62
+ self.stroke_width = pointsize / 30.0
63
+ self.pointsize = pointsize
64
+ end
65
+ end
66
+ # rubocop:enable Metrics/MethodLength
67
+
68
+ def watermark
69
+ draw = Magick::Draw.new
70
+ draw.annotate(@canvas, 0, 0, 0, 0, " #{@watermark}") do
71
+ self.fill = 'white'
72
+ text_antialias(false)
73
+ self.font_weight = 100
74
+ self.gravity = Magick::SouthEastGravity
75
+ self.pointsize = 10
76
+ self.undercolor = 'hsla(0,0,0,.5)'
77
+ end
78
+ end
79
+
80
+ # rubocop:disable Metrics/AbcSize
81
+ def calculate_pointsize(text, size_range: 28...128)
82
+ draw = Magick::Draw.new
83
+ draw.font = File.join(File.dirname(File.expand_path(__FILE__)), '..', '..', 'fonts', 'Impact.ttf')
84
+ draw.font_weight = Magick::BoldWeight
85
+
86
+ size = size_range.detect(-> { size_range.last }) do |pointsize|
87
+ draw.pointsize = pointsize + 1
88
+ current_stroke = pointsize / 30.0
89
+
90
+ metrics = draw.get_multiline_type_metrics(text)
91
+
92
+ metrics.width + current_stroke > @canvas.columns - 20 || metrics.height + current_stroke > (@canvas.rows / 2) - 20
93
+ end
94
+ [draw, size]
95
+ end
96
+ # rubocop:enable Metrics/AbcSize
97
+
98
+ def word_wrap(text, col: 24)
99
+ text.strip.gsub(/\n\r/, '\s')
100
+ text = WordWrapper::MinimumRaggedness.new(col, text).wrap
101
+ text = text.split("\n").map do |line|
102
+ line.length > col ? line.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/, "\\1\\3\n").strip : line
103
+ end * "\n"
104
+ text.strip
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,49 @@
1
+ module LeMeme
2
+ # Utility for easily generating memes based off templates
3
+ class MemeLib
4
+ attr_reader :memes
5
+ # Creates a meme library
6
+ #
7
+ # @param [String] *dirs Directory glob patterns to meme templates
8
+ # @return [MemeLib]
9
+ def initialize(*dirs)
10
+ @memes = {}
11
+ dirs.each(&method(:load_directory!))
12
+ end
13
+
14
+ # Creates a meme library, preloaded with the included templates
15
+ #
16
+ # @return [MemeLib]
17
+ def self.new_with_default_memes
18
+ path = File.join(File.dirname(File.expand_path(__FILE__)), '..', '..', 'memes', '*')
19
+ new(path)
20
+ end
21
+
22
+ # Loads a directory into the MemeLib, for template consumption
23
+ # Clobbers any existing templates
24
+ #
25
+ # @param [String] dir Directory glob pattern to meme templates
26
+ # @return [Hash] Hash of all templates and their filepaths
27
+ def load_directory!(dir)
28
+ paths = Dir.glob(dir).grep LeMeme::IMAGE_EXTENSIONS
29
+ @memes.merge!(paths.reduce({}) do |images, path|
30
+ path = File.expand_path(path)
31
+ name = path.split.last.sub(LeMeme::IMAGE_EXTENSIONS, '').to_s
32
+ images.merge(name => path)
33
+ end)
34
+ end
35
+
36
+ # Create a meme from a template
37
+ #
38
+ # @param [String] template: nil The template to use. Omit for random template
39
+ # @param [String] top: nil
40
+ # @param [String] bottom: nil
41
+ # @param [String] watermark: nil
42
+ # @return [LeMeme::Meme]
43
+ def meme(template: nil, top: nil, bottom: nil, watermark: nil)
44
+ path = template.nil? ? @memes.values.sample : @memes[template]
45
+
46
+ Meme.new(path, top: top, bottom: bottom, watermark: watermark)
47
+ end
48
+ end
49
+ end
@@ -1,3 +1,4 @@
1
- class LeMeme
2
- VERSION = "0.0.8"
1
+ # frozen_string_literal: true
2
+ module LeMeme
3
+ VERSION = '0.1.0'.freeze
3
4
  end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe LeMeme::Meme do
4
+ subject { LeMeme::Meme.new('memes/maymay.jpg') }
5
+ describe :new do
6
+ context 'without text' do
7
+ it { is_expected.to be_a LeMeme::Meme }
8
+ it { expect(subject.path).to match(%r{memes/maymay.jpg$}) }
9
+ end
10
+
11
+ context 'with text' do
12
+ subject do
13
+ LeMeme::Meme.new('memes/maymay.jpg', top: 'top text', bottom: 'bottom text')
14
+ end
15
+
16
+ it { expect(subject.top).to eql('TOP TEXT') }
17
+ it { expect(subject.bottom).to eql('BOTTOM TEXT') }
18
+ end
19
+ end
20
+
21
+ describe :to_file do
22
+ it { expect(subject.to_file).to be_a(File) }
23
+ it { expect(subject.to_file.path).to match(/#{ENV['TMPDIR']}meme-\d+.jpg/) }
24
+ end
25
+
26
+ describe :to_blob do
27
+ it { expect(subject.to_blob).to be_a(String) }
28
+ it { expect(subject.to_blob.size).to eql(43_685) }
29
+ end
30
+ end
@@ -1,6 +1,4 @@
1
1
  require 'pry'
2
2
  require 'le_meme'
3
3
 
4
- RSpec.configure do |c|
5
- c.raise_errors_for_deprecations!
6
- end
4
+ RSpec.configure(&:raise_errors_for_deprecations!)
metadata CHANGED
@@ -1,131 +1,136 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: le_meme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Sandberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-17 00:00:00.000000000 Z
11
+ date: 2016-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.7'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.7'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '0.10'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '0.10'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
56
+ name: pry-byebug
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '3.1'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '3.1'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: rmagick
70
+ name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '2.13'
76
- type: :runtime
75
+ version: '0'
76
+ type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '2.13'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: word_wrapper
84
+ name: rmagick
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.5.0
89
+ version: '2.15'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.5.0
96
+ version: '2.15'
97
97
  - !ruby/object:Gem::Dependency
98
- name: slop
98
+ name: word_wrapper
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '3.6'
103
+ version: 0.5.0
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: '3.6'
110
+ version: 0.5.0
111
111
  description: A gem that generates memes. Can be used as a library or command-line
112
112
  executable.
113
113
  email:
114
114
  - paradox460@gmail.com
115
115
  executables:
116
+ - console
116
117
  - meme
117
118
  extensions: []
118
119
  extra_rdoc_files: []
119
120
  files:
120
121
  - ".gitignore"
122
+ - ".rubocop.yml"
121
123
  - Gemfile
122
124
  - LICENSE.txt
123
125
  - README.md
124
126
  - Rakefile
127
+ - bin/console
125
128
  - bin/meme
126
129
  - fonts/Impact.ttf
127
130
  - le_meme.gemspec
128
131
  - lib/le_meme.rb
132
+ - lib/le_meme/meme.rb
133
+ - lib/le_meme/meme_lib.rb
129
134
  - lib/le_meme/version.rb
130
135
  - memes/10guy.jpg
131
136
  - memes/aaduck.jpg
@@ -208,7 +213,7 @@ files:
208
213
  - memes/wonka.jpg
209
214
  - memes/yee.jpg
210
215
  - memes/yuno.jpg
211
- - spec/le_meme_spec.rb
216
+ - spec/le_meme/meme_spec.rb
212
217
  - spec/spec_helper.rb
213
218
  homepage: http://github.com/paradox460/le_meme
214
219
  licenses:
@@ -222,7 +227,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
222
227
  requirements:
223
228
  - - ">="
224
229
  - !ruby/object:Gem::Version
225
- version: '0'
230
+ version: '2.1'
226
231
  required_rubygems_version: !ruby/object:Gem::Requirement
227
232
  requirements:
228
233
  - - ">="
@@ -230,10 +235,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
235
  version: '0'
231
236
  requirements: []
232
237
  rubyforge_project:
233
- rubygems_version: 2.4.5
238
+ rubygems_version: 2.5.1
234
239
  signing_key:
235
240
  specification_version: 4
236
241
  summary: Dank memes, in gem form
237
242
  test_files:
238
- - spec/le_meme_spec.rb
243
+ - spec/le_meme/meme_spec.rb
239
244
  - spec/spec_helper.rb
@@ -1,68 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe LeMeme do
4
- let(:meme) { LeMeme.new }
5
-
6
- describe '#generate' do
7
- let(:image) { File.join(File.dirname(File.expand_path(__FILE__)), '../memes/maymay.jpg') }
8
- context 'without an image path' do
9
- it 'should raise ArgumentError with "missing keyword: path"' do
10
- expect { meme.generate }.to raise_error(ArgumentError, 'missing keyword: path')
11
- end
12
- end
13
- context 'with an image path' do
14
- x = ['text', nil] * 3
15
- x.permutation(3).to_a.uniq.each do |top, bottom, watermark|
16
- it "should generate a meme with top: '#{top}', bottom: '#{bottom}', and watermark: '#{watermark}'" do
17
- expect_any_instance_of(Magick::ImageList).to receive(:write).and_return("/tmp/meme-#{Time.now.to_i}.jpg")
18
- expect(meme.generate(path: image, top: top, bottom: bottom, watermark: watermark)).to match(%r{/tmp/meme-\d+.jpg})
19
- end
20
- end
21
- end
22
- context 'with an outpath' do
23
- it 'should generate a meme at the specified outpath' do
24
- expect_any_instance_of(Magick::ImageList).to receive(:write).and_return('test.jpg')
25
- expect(meme.generate(path: image, top: 'top', bottom: 'bottom', outpath: 'test.jpg')).to eq('test.jpg')
26
- end
27
- end
28
- context 'with nowrite set to true' do
29
- it 'should output the meme as a blob string' do
30
- mymeme = meme.generate(path: image, nowrite: true)
31
- expect(mymeme.size).to eq(43618)
32
- end
33
- end
34
- end
35
-
36
- describe '#meme' do
37
- it 'should be an alias of #generate' do
38
- expect(meme.method(:meme)).to eq(meme.method(:generate))
39
- end
40
- end
41
-
42
- describe '#fast_meme' do
43
- let(:template) { 'maymay' }
44
- it 'should pass its params to generate_meme' do
45
- expect(meme).to receive(:generate) do |args|
46
- expect(args[:path]).to eq(Pathname.new('/Users/jeffsandberg/Developer/le_meme/memes/maymay.jpg'))
47
- expect(args[:top]).to eq('top text')
48
- expect(args[:bottom]).to eq('bottom text')
49
- expect(args[:watermark]).to eq('watermark')
50
- expect(args[:outpath]).to eq('outpath')
51
- end
52
- meme.fast_meme(name: template, top: 'top text', bottom: 'bottom text', watermark: 'watermark', outpath: 'outpath')
53
- end
54
-
55
- context 'without a specified template' do
56
- it 'should generate a meme' do
57
- expect_any_instance_of(Magick::ImageList).to receive(:write).and_return("/tmp/meme-#{Time.now.to_i}.jpg")
58
- expect(meme.fast_meme).to match(%r{/tmp/meme-\d+.jpg})
59
- end
60
- end
61
- end
62
-
63
- describe '#m' do
64
- it 'should be an alias of #fast_meme' do
65
- expect(meme.method(:m)).to eq(meme.method(:fast_meme))
66
- end
67
- end
68
- end