kanoko 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c507e252c2624f4482ad7e29ac990c0a698300f5
4
- data.tar.gz: 416bc6b1987141e93dcb646e83e571434e6bea71
3
+ metadata.gz: 951798a023b45334f2180ac2a616bb1f66c90f7e
4
+ data.tar.gz: 5185345e9249e30edea76b5fad351b11fde1d48b
5
5
  SHA512:
6
- metadata.gz: fc89740eacc7b58c509b2cf8d84405945eb1fb1e3e2dc1eb6cd5a158c5f7f43d7b4719ab1d20de31cb231feb7c18a842f360fc6dad40159fa67c0c7215f92e18
7
- data.tar.gz: 0f05b0052f0784639d6a42564bf04ee06b709860cbf6ace572fff11cb145cffaedd692b3eeca3c4096d1ca8a5d013454dec952b1db9a6c11c9a54c53b814dfcf
6
+ metadata.gz: 59c18db72d747e198ee233e93d54a728283c2057ad36895b8cb51dbd16cb35e30d875842e37e877413a56fe0f93f5ee160b9de2775ea9277dfcae24710f4d861
7
+ data.tar.gz: db41f1f05a3ff41c872ca1d9ede236486cbff8ec0b5805f89b67ce0fea9cb7b0e73c152d4178dd4c9fa6f4ca80050f2a914b7fa4073fbcc2c179518ec4430b4f
data/README.md CHANGED
@@ -3,6 +3,8 @@ kanoko
3
3
 
4
4
  [![Build Status](https://travis-ci.org/spice-life/kanoko.svg?branch=master)](https://travis-ci.org/spice-life/kanoko)
5
5
 
6
+ ![logo](https://raw.githubusercontent.com/spice-life/kanoko/master/logo.png)
7
+
6
8
  **kanoko** is an active image generate application.
7
9
 
8
10
  # Quick Start
@@ -20,6 +20,7 @@ module Kanoko
20
20
  def configure=(value)
21
21
  @configure = value
22
22
  end
23
+ module_function :configure=
23
24
 
24
25
  def path_for(*function, src)
25
26
  hash = make_hash(*function, src)
@@ -31,22 +31,30 @@ require 'kanoko'
31
31
  module Kanoko
32
32
  module Application
33
33
  class Convert < Sinatra::Application
34
+
34
35
  # /123abc456def=/resize/200x200/crop/100x100/path/to/src
35
36
  get '/:hash/*' do
36
- request_uri = URI.parse env["REQUEST_URI"]
37
+ request_uri = URI.parse(env["REQUEST_URI"] || "/#{params[:captures].join('/')}")
37
38
  hash = params[:hash]
38
39
  unless params[:splat]
39
40
  logger.error "invalid url #{request_uri}"
40
41
  return 400
41
42
  end
43
+
42
44
  splat = params[:splat][0]
43
- function = Function.new splat
44
- hint_src = splat[function.to_path.length..-1]
45
+ argument = ArgumentParser.new splat
46
+
47
+ hint_src = splat[argument.path.length..-1]
48
+ unless hint_src
49
+ logger.error "invalid url #{request_uri}"
50
+ return 400
51
+ end
52
+
45
53
  hint_index = request_uri.to_s.index(hint_src)
46
54
  src_path = request_uri.to_s[hint_index..-1]
47
55
 
48
- unless hash == Kanoko.make_hash(*(function.to_a.flatten), src_path)
49
- logger.error "hash check failed #{[*(function.to_a.flatten), src_path]}"
56
+ unless hash == Kanoko.make_hash(*(argument.to_a.flatten), src_path)
57
+ logger.error "hash check failed #{[*(argument.to_a.flatten), src_path]}"
50
58
  return 400
51
59
  end
52
60
 
@@ -61,50 +69,14 @@ module Kanoko
61
69
  src_file.fdatasync
62
70
 
63
71
  Tempfile.open("dst") do |dst_file|
64
- default_env = {"OMP_NUM_THREADS" => "1"}
65
- command = 'convert'
66
- default_options = [
67
- '-depth', '8'
68
- ]
69
- options = []
70
-
71
- function.each do |name, arg|
72
- func_options = case name.to_sym
73
- when :crop
74
- [
75
- '-crop', arg
76
- ]
77
-
78
- when :fill
79
- [
80
- '-gravity', 'north',
81
- '-extent', arg,
82
- '-background', 'transparent',
83
- ]
84
-
85
- when :resize
86
- [
87
- '-define', "jpeg:size=#{arg}",
88
- '-thumbnail', arg,
89
- ]
90
-
91
- else
92
- logger.error "undefined func #{name}"
93
- return 400
94
- end
95
-
96
- options.concat func_options
97
- end
98
-
99
72
  system_command = [
100
- default_env,
101
- command,
102
- default_options,
103
- options,
73
+ {"OMP_NUM_THREADS" => "1"},
74
+ 'convert',
75
+ '-depth', '8',
76
+ argument.options,
104
77
  src_file.path,
105
78
  dst_file.path
106
79
  ].flatten
107
-
108
80
  result = system *system_command
109
81
 
110
82
  unless result
@@ -152,8 +124,12 @@ module Kanoko
152
124
  end
153
125
  end
154
126
  end
127
+
128
+ error 404 do
129
+ ""
130
+ end
155
131
  end
156
132
  end
157
133
  end
158
134
 
159
- require 'kanoko/application/convert/function'
135
+ require 'kanoko/application/convert/argument_parser'
@@ -0,0 +1,45 @@
1
+ require 'kanoko/application/convert/function'
2
+
3
+ module Kanoko
4
+ module Application
5
+ class Convert
6
+ class ArgumentParser
7
+ include Enumerable
8
+ extend Forwardable
9
+ def_delegators :@args, :each, :to_a
10
+
11
+ attr_reader :options
12
+
13
+ def initialize(args)
14
+ @args, @options = ArgumentParser.parse args
15
+ end
16
+
17
+ def to_path
18
+ map { |i| "/#{i.join('/')}" }.join
19
+ end
20
+ alias path to_path
21
+
22
+ private
23
+
24
+ class << self
25
+ def parse(path)
26
+ args = []
27
+ options = []
28
+ items = path.split('/')
29
+ while item = items.shift
30
+ id = item.to_sym
31
+ if Function.list.include?(id)
32
+ function = Function.new
33
+ method = function.method(id)
34
+ arg = items.shift(method.arity)
35
+ options.concat method.call(*arg)
36
+ args.push [id, *arg]
37
+ end
38
+ end
39
+ [args, options]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,36 +1,49 @@
1
1
  module Kanoko
2
2
  module Application
3
3
  class Convert
4
+ # You can make customize function.
5
+ # It just make or overwhrite instance method.
6
+ # example:
7
+ # class Kanoko::Application::Convert::Function
8
+ # # get "/new_func/new_value"
9
+ # # => add imagemagick option
10
+ # # -new-option new_value
11
+ # def new_func(arg)
12
+ # ['-new-option', arg]
13
+ # end
14
+ # end
4
15
  class Function
5
- include Enumerable
6
- extend Forwardable
7
- def_delegators :@args, :each, :to_a, :to_h
16
+ class << self
17
+ def list
18
+ instance_methods(false)
19
+ end
20
+ end
8
21
 
9
- def initialize(args)
10
- @args = parse args
22
+ def crop(arg)
23
+ [
24
+ '-crop', arg
25
+ ]
11
26
  end
12
27
 
13
- def to_path
14
- paths = []
15
- @args.each do |func, arg|
16
- paths << "/#{func}/#{arg}"
17
- end
18
- paths.join
28
+ def fill(arg)
29
+ [
30
+ '-gravity', 'north',
31
+ '-extent', arg,
32
+ '-background', 'transparent',
33
+ ]
19
34
  end
20
35
 
21
- private
36
+ def resize(arg)
37
+ [
38
+ '-define', "jpeg:size=#{arg}",
39
+ '-thumbnail', arg,
40
+ ]
41
+ end
22
42
 
23
- def parse(args)
24
- hash = {}
25
- items = args.split('/')
26
- items.each_slice(2) do |funcname, arg|
27
- if funcname.match(/\./)
28
- break
29
- else
30
- hash[funcname.to_sym] = arg.to_s
31
- end
32
- end
33
- hash
43
+ def auto_orient
44
+ [
45
+ '-auto-orient'
46
+ ]
34
47
  end
35
48
  end
36
49
  end
@@ -1,3 +1,3 @@
1
1
  module Kanoko
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
Binary file
@@ -0,0 +1,7 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'minitest/autorun'
4
+ require 'stringio'
5
+ require "rack/test"
6
+ require "exifr"
7
+ require "kanoko/application/convert"
@@ -1,9 +1,4 @@
1
- require 'digest/sha1'
2
- require 'stringio'
3
- require 'minitest/autorun'
4
- require "rack/test"
5
- require "exifr"
6
- require "kanoko/application/convert"
1
+ require 'helper'
7
2
 
8
3
  class TestKanokoApplicationConvert < Minitest::Test
9
4
  include Rack::Test::Methods
@@ -23,7 +18,6 @@ class TestKanokoApplicationConvert < Minitest::Test
23
18
  end
24
19
 
25
20
  def setup
26
- ENV['RACK_ENV'] = 'test'
27
21
  Kanoko.configure.digest_func = "sha1"
28
22
  Kanoko.configure.secret_key = "test"
29
23
  end
@@ -35,29 +29,71 @@ class TestKanokoApplicationConvert < Minitest::Test
35
29
  end
36
30
 
37
31
  def test_resize
38
- url = Kanoko.path_for(:resize, "10x10", "src.jpg")
39
- get url, {}, {"REQUEST_URI" => url}
32
+ path = Kanoko.path_for(:resize, "10x10", "src.jpg")
33
+ get path
40
34
  assert last_response.ok?
41
35
  assert 0 < last_response.body.length
42
36
  assert_jpeg File.read("test/resize.jpg"), last_response.body
43
37
  end
44
38
 
45
39
  def test_resize_and_crop
46
- url = Kanoko.path_for(:resize, "10x10", :crop, "5x5+1+1", "src.jpg")
47
- get url, {}, {"REQUEST_URI" => url}
40
+ path = Kanoko.path_for(:resize, "10x10", :crop, "5x5+1+1", "src.jpg")
41
+ get path
48
42
  assert last_response.ok?
49
43
  assert 0 < last_response.body.length
50
44
  assert_jpeg File.read("test/resize_and_crop.jpg"), last_response.body
51
45
  end
52
46
 
53
- def test_not_found
54
- get "/nothing"
55
- assert_equal 404, last_response.status
47
+ def test_auto_orient
48
+ path = Kanoko.path_for(:auto_orient, "src.jpg")
49
+ get path
50
+ assert last_response.ok?
51
+ assert 0 < last_response.body.length
52
+ assert_jpeg File.read("test/src.jpg"), last_response.body
53
+ end
56
54
 
57
- post "/nothing"
58
- assert_equal 404, last_response.status
55
+ def test_resize_and_auto_orient
56
+ path = Kanoko.path_for(:resize, "10x10", :auto_orient, "src.jpg")
57
+ get path
58
+ assert last_response.ok?
59
+ assert 0 < last_response.body.length
60
+ assert_jpeg File.read("test/resize.jpg"), last_response.body
61
+ end
59
62
 
60
- delete "/nothing"
63
+ def test_undefined_func
64
+ path = Kanoko.path_for(:undefined, "10x10", "src.jpg")
65
+ get path
66
+ assert_equal 400, last_response.status
67
+ assert_equal "", last_response.body
68
+ end
69
+
70
+ def test_root_not_found
71
+ path = "/"
72
+ get path
61
73
  assert_equal 404, last_response.status
74
+ assert_equal "", last_response.body
75
+ end
76
+
77
+ def test_invalid_path
78
+ path = "/invalid/path/to/src"
79
+ get path
80
+ assert_equal 400, last_response.status
81
+ assert_equal "", last_response.body
82
+ end
83
+
84
+ class Kanoko::Application::Convert::Function
85
+ def method_for_500
86
+ ['-undefined-imagemagick-option']
87
+ end
88
+ end
89
+
90
+ def test_500
91
+ path = Kanoko.path_for(:method_for_500, "src.jpg")
92
+ out, err = capture_subprocess_io do
93
+ get path
94
+ end
95
+ assert_equal 500, last_response.status
96
+ assert_equal "", last_response.body
97
+ assert_match /convert: unrecognized option `-undefined-imagemagick-option'/, err
62
98
  end
63
99
  end
@@ -0,0 +1,58 @@
1
+ require 'helper'
2
+
3
+ class TestKanokoApplicationConvertArgumentParser < Minitest::Test
4
+ include Kanoko::Application
5
+ class Kanoko::Application::Convert::Function
6
+ def empty_option
7
+ []
8
+ end
9
+ def one_option
10
+ ['func1']
11
+ end
12
+ def one_arg_and_one_option(arg)
13
+ ['func2', arg]
14
+ end
15
+ end
16
+
17
+ def test_empty
18
+ a = Convert::ArgumentParser.new("")
19
+ assert_equal [], a.to_a
20
+ assert_equal [], a.options
21
+ assert_equal "", a.path
22
+ end
23
+
24
+ def test_empty_option
25
+ a = Convert::ArgumentParser.new("empty_option/10x10")
26
+ assert_equal [[:empty_option]], a.to_a
27
+ assert_equal [], a.options
28
+ assert_equal "/empty_option", a.path
29
+ end
30
+
31
+ def test_one_option
32
+ a = Convert::ArgumentParser.new("one_option/10x10")
33
+ assert_equal [[:one_option]], a.to_a
34
+ assert_equal "/one_option", a.path
35
+ assert_equal ['func1'], a.options
36
+ end
37
+
38
+ def test_one_arg_and_one_option
39
+ a = Convert::ArgumentParser.new("one_arg_and_one_option/10x10")
40
+ assert_equal [[:one_arg_and_one_option, '10x10']], a.to_a
41
+ assert_equal "/one_arg_and_one_option/10x10", a.path
42
+ assert_equal ['func2', '10x10'], a.options
43
+ end
44
+
45
+ def test_one_option_and_one_arg_and_one_option
46
+ a = Convert::ArgumentParser.new("one_option/one_arg_and_one_option/10x10")
47
+ assert_equal [[:one_option], [:one_arg_and_one_option, '10x10']], a.to_a
48
+ assert_equal "/one_option/one_arg_and_one_option/10x10", a.path
49
+ assert_equal ['func1', 'func2', '10x10'], a.options
50
+ end
51
+
52
+ def test_nothing
53
+ a = Convert::ArgumentParser.new("nothing/10x10")
54
+ assert_equal [], a.to_a
55
+ assert_equal "", a.path
56
+ assert_equal [], a.options
57
+ end
58
+ end
@@ -1,5 +1,4 @@
1
- require 'minitest/autorun'
2
- require 'kanoko/configure'
1
+ require 'helper'
3
2
 
4
3
  class TestKanokoConfigure < Minitest::Test
5
4
  def setup
@@ -1,5 +1,4 @@
1
- require 'minitest/autorun'
2
- require 'kanoko'
1
+ require 'helper'
3
2
 
4
3
  class TestKanoko < Minitest::Test
5
4
  def setup
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kanoko
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-11 00:00:00.000000000 Z
11
+ date: 2015-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -110,14 +110,18 @@ files:
110
110
  - kanoko.gemspec
111
111
  - lib/kanoko.rb
112
112
  - lib/kanoko/application/convert.rb
113
+ - lib/kanoko/application/convert/argument_parser.rb
113
114
  - lib/kanoko/application/convert/function.rb
114
115
  - lib/kanoko/configure.rb
115
116
  - lib/kanoko/errors.rb
116
117
  - lib/kanoko/version.rb
118
+ - logo.png
119
+ - test/helper.rb
117
120
  - test/resize.jpg
118
121
  - test/resize_and_crop.jpg
119
122
  - test/src.jpg
120
123
  - test/test_application_convert.rb
124
+ - test/test_application_convert_argumentparser.rb
121
125
  - test/test_configure.rb
122
126
  - test/test_kanoko.rb
123
127
  homepage: https://github.com/spice-life/kanoko
@@ -145,9 +149,11 @@ signing_key:
145
149
  specification_version: 4
146
150
  summary: kanoko is a active image generater library.
147
151
  test_files:
152
+ - test/helper.rb
148
153
  - test/resize.jpg
149
154
  - test/resize_and_crop.jpg
150
155
  - test/src.jpg
151
156
  - test/test_application_convert.rb
157
+ - test/test_application_convert_argumentparser.rb
152
158
  - test/test_configure.rb
153
159
  - test/test_kanoko.rb