galgen 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/COPYING +13 -0
  2. data/README.textile +5 -0
  3. data/bin/galgen +328 -0
  4. metadata +112 -0
data/COPYING ADDED
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2011+ Voker57 <voker57@gmail.com>
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
+
7
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8
+
9
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10
+
11
+ The name of author may not be used to endorse or promote products derived from this software without specific prior written permission.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.textile ADDED
@@ -0,0 +1,5 @@
1
+ p=. !http://dump.bitcheese.net/files/galgen.png!
2
+
3
+ GalGen is for Gallery Generator. It's written in Ruby and generates static HTML galleries from images and their descriptions.
4
+
5
+ More info here: http://bitcheese.net/wiki/code/galgen
data/bin/galgen ADDED
@@ -0,0 +1,328 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'fileutils'
5
+ require 'tilt'
6
+ require 'RedCloth'
7
+ require 'builder'
8
+
9
+ class GalGen
10
+ def initialize(rootdir)
11
+ @rootdir = rootdir
12
+ default_config = {
13
+ :thumb_size => "800x600",
14
+ :minithumb_size => "200x150",
15
+ :atom_items => 10,
16
+ :total_feed => "gindex.xml"
17
+ }
18
+ @config = if File.readable?(@rootdir + "/" + "galgen.yml")
19
+ default_config.merge(YAML.load_file(@rootdir + "/" + "galgen.yml"))
20
+ else
21
+ puts "Using default config; create galgen.yml to override"
22
+ default_config
23
+ end
24
+ @sorting_func = lambda do |a,b|
25
+ if a[:modified] == b[:modified]
26
+ a[:image_name] <=> b[:image_name]
27
+ else
28
+ a[:modified] <=> b[:modified]
29
+ end
30
+ end
31
+ # Supply default versions of templates if they don't exist
32
+ if !File.readable?(@rootdir + "/image.erb")
33
+ puts "Creating image.erb"
34
+ File.open(@rootdir + "/image.erb", "w") do |f|
35
+ f.write <<-EOF
36
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
37
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us"><head><title><%= image_title %></title>
38
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
39
+ </head>
40
+ <body>
41
+ <a href="..">..</a> / <a href="<%= gallery_url %>"><%= gallery_title %></a> / <a href="<% image_page_url %>"><% image_title %></a>
42
+
43
+ <h1> <%= image_title %> </h1>
44
+
45
+ <div >
46
+ <a href="<%= image_url %>">
47
+ <img src="<%= image_thumb_url %>" />
48
+ </a>
49
+ <br />
50
+ <%= image_description %>
51
+ </div>
52
+
53
+ <div>
54
+ <% if defined? prev_image_url %>
55
+ <a href="<%= prev_image_url %>">&lt;&lt;&lt;</a>
56
+ <% else %>
57
+ &lt;&lt;&lt;
58
+ <% end %>
59
+ |
60
+ <% if defined? next_image_url %>
61
+ <a href="<%= next_image_url %>">&gt;&gt;&gt;</a>
62
+ <% else %>
63
+ &gt;&gt;&gt;
64
+ <% end %>
65
+ </div>
66
+ </body>
67
+ </html>
68
+ EOF
69
+ end
70
+ end
71
+ if !File.readable?(@rootdir + "/gallery.erb")
72
+ puts "Creating gallery.erb"
73
+ File.open(@rootdir + "/gallery.erb", "w") do |f|
74
+ f.write <<-EOF
75
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
76
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-us" lang="en-us">
77
+ <head>
78
+ <title><% gallery_title %></title>
79
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
80
+ </head>
81
+ <body>
82
+ <a href="<%= gallery_url %>"><%= gallery_title %></a>
83
+
84
+ <h1> <a href="<%= gallery_url %>"><%= gallery_title %></a> </h1>
85
+
86
+ <%= gallery_description %>
87
+
88
+ <%= gallery_previews %>
89
+
90
+ <%= image_previews %>
91
+ </body>
92
+ </html>
93
+ EOF
94
+ end
95
+ end
96
+ if !File.readable?(@rootdir + "/image_preview.erb")
97
+ puts "Creating image_preview.erb"
98
+ File.open(@rootdir + "/image_preview.erb", "w") do |f|
99
+ f.write <<-EOF
100
+ <div>
101
+ <a href="<%= image_page_url %>">
102
+ <img src="<%= image_minithumb_url %>" />
103
+ <br />
104
+ <h3 style="display:inline">
105
+ <%= image_title %>
106
+ </h3>
107
+ </a>
108
+ </a>
109
+ </div>
110
+ EOF
111
+ end
112
+ end
113
+ if !File.readable?(@rootdir + "/gallery_preview.erb")
114
+ puts "Creating gallery_preview.erb"
115
+ File.open(@rootdir + "/gallery_preview", "w") do |f|
116
+ f.write <<-EOF
117
+
118
+ <h2>
119
+ <a href="<%= gallery_url %>"><%=gallery_title%></a>
120
+ </h2>
121
+ <%= gallery_description %>
122
+ EOF
123
+ end
124
+ end
125
+ @image_tmpl = Tilt::ERBTemplate.new(@rootdir + "/image.erb")
126
+ @gallery_tmpl = Tilt::ERBTemplate.new(@rootdir + "/gallery.erb")
127
+ @image_p_tmpl = Tilt::ERBTemplate.new(@rootdir + "/image_preview.erb")
128
+ @gallery_p_tmpl = Tilt::ERBTemplate.new(@rootdir + "/gallery_preview.erb")
129
+ end
130
+
131
+ attr_reader :config
132
+ attr_reader :sorting_func
133
+
134
+ def check_timestamp(source, target)
135
+ if source.is_a? Array
136
+ source.map { |s| check_timestamp(s, target)} - [true] == []
137
+ elsif !File.exists?(target)
138
+ false
139
+ else
140
+ File.mtime(source) <= File.mtime(target)
141
+ end
142
+ end
143
+
144
+ def generate(out_directory)
145
+ FileUtils.mkdir_p(out_directory)
146
+ gallery_vars = generate_gallery(out_directory)
147
+
148
+ xo = File.open(([out_directory] + gallery_vars[:gallery_path] + [config[:total_feed]]).join("/"), "w")
149
+
150
+ xml = Builder::XmlMarkup.new(:target => xo)
151
+ xml.instruct!
152
+ xml.feed("xmlns"=>"http://www.w3.org/2005/Atom") do |feed|
153
+ feed.title("Updates to all galleries")
154
+ feed.link("href" => config[:http_base])
155
+ gallery_vars[:children].sort(&sorting_func).last(config[:atom_items]).each do |c_img|
156
+ feed.entry do |entry|
157
+ entry.title(c_img[:image_title])
158
+ entry.updated(c_img[:modified].strftime("%FT%T%z"))
159
+ uri = ([config[:http_base]] + c_img[:gallery_path] + [c_img[:image_page_url]]).join("/")
160
+ img_uri = ([config[:http_base]] + ["images", "thumb"] + c_img[:gallery_path] + [c_img[:image_name]]).join("/")
161
+ full_uri = ([config[:http_base]] + ["images", "full"] + c_img[:gallery_path] + [c_img[:image_name]]).join("/")
162
+ entry.id(uri)
163
+ entry.link("href" => uri)
164
+ entry.content({"type" => "html"}, "<a href='#{img_uri}'><img src='#{full_uri}' /></a> #{c_img[:description]}")
165
+ end
166
+ end
167
+ end
168
+
169
+ xo.close
170
+
171
+ puts ([out_directory] + gallery_vars[:gallery_path] + [config[:total_feed]]).join("/")
172
+ end
173
+
174
+ def generate_gallery(out_directory, gallery_path = [])
175
+ directory = ([@rootdir] + gallery_path).join("/galleries/")
176
+
177
+ FileUtils.mkdir_p(([out_directory] + gallery_path).join("/")) if gallery_path.length > 0
178
+
179
+ static_dir = [@rootdir, "static"].join("/")
180
+
181
+ if File.exists? static_dir and not check_timestamp(static_dir, out_directory + "/static")
182
+ FileUtils.cp_r static_dir, out_directory
183
+ puts "static/*"
184
+ end
185
+
186
+ gallery_previews = ""
187
+ children_children = []
188
+ if File.exists?(directory + "/" + "galleries")
189
+ (Dir.entries(directory + "/" + "galleries") - [".",".."]).each do |gallery|
190
+ child = generate_gallery(out_directory, gallery_path + [gallery])
191
+ child[:gallery_url] = gallery + "/"
192
+ gallery_previews << @gallery_p_tmpl.render(nil, child)
193
+ children_children += child[:children]
194
+ end
195
+ end
196
+
197
+ gallery_description_file = [directory, "index.textile"].join("/")
198
+ gallery_title = gallery_path.last
199
+ gallery_description = ""
200
+ if File.readable?(gallery_description_file)
201
+ desc_text = File.read(gallery_description_file)
202
+ g_title = desc_text.scan(/^(.*?)(\n\n|$)/)[0][0]
203
+ if g_title.length > 0
204
+ gallery_title = g_title
205
+ end
206
+ if desc_text =~ /\n\n/
207
+ gallery_description = RedCloth.new(desc_text.gsub(/^.*?(\n\n)/,"")).to_html
208
+ end
209
+ end
210
+ gallery_vars = { :gallery_title => gallery_title, :gallery_url => './', :gallery_description => gallery_description, :root => (gallery_path.length == 0 ? "." : ([".."] * gallery_path.length).join("/")), :gallery_path => gallery_path }
211
+ gallery_vars[:children] = children_children
212
+ previews = ""
213
+ child_images = []
214
+ if File.exists? [directory, "images"].join("/")
215
+ images = (Dir.entries([directory, "images"].join("/")) - [".",".."]).sort
216
+ clean_images = images.map {|i| i.gsub(/^\d+_/,"").gsub(/\.\w+$/,"")}
217
+ images.each do |image_name|
218
+ full_image_name = [directory, "images", image_name].join("/")
219
+ description_file = [directory, "descriptions", image_name + ".textile"].join("/")
220
+ clean_image_name = image_name.gsub(/^\d+_/,"")
221
+ base_image_name = clean_image_name.gsub(/\.\w+$/,"")
222
+ description = ""
223
+ title = base_image_name
224
+ if File.readable?(description_file)
225
+ desc_text = File.read(description_file)
226
+ i_title = desc_text.scan(/^(.*?)(\n\n|$)/)[0][0]
227
+ if i_title.length > 0
228
+ title = i_title
229
+ end
230
+ if desc_text =~ /\n\n/
231
+ description = RedCloth.new(desc_text.gsub(/^.*?(\n\n)/,"")).to_html
232
+ end
233
+ end
234
+ image_vars = { :image_title => title, :image_description => description, :image_page_url => base_image_name + ".html", :image_url => (([".."] * gallery_path.length) + ["images", "full"] + gallery_path + [clean_image_name]).join("/"), :image_thumb_url => (([".."] * gallery_path.length) + ["images", "thumb"] + gallery_path + [clean_image_name]).join("/"), :image_minithumb_url => (([".."] * gallery_path.length) + ["images", "minithumb"] + gallery_path + [clean_image_name]).join("/"), :image_name => clean_image_name, :modified => File.mtime(full_image_name), :original_name => image_name}
235
+
236
+ idx = clean_images.index(base_image_name)
237
+
238
+ if idx != 0
239
+ image_vars[:prev_image_url] = clean_images[idx-1] + ".html"
240
+ end
241
+
242
+ if idx != clean_images.size - 1
243
+ image_vars[:next_image_url] = clean_images[idx+1] + ".html"
244
+ end
245
+
246
+ FileUtils.mkdir_p(([out_directory, "images", "full"] + gallery_path).join("/"))
247
+ FileUtils.mkdir_p(([out_directory, "images", "thumb"] + gallery_path).join("/"))
248
+ FileUtils.mkdir_p(([out_directory, "images", "minithumb"] + gallery_path).join("/"))
249
+
250
+ full_path = ([out_directory, "images", "full"] + gallery_path + [clean_image_name]).join("/")
251
+ unless check_timestamp(full_image_name, full_path)
252
+ FileUtils.cp(full_image_name, full_path)
253
+ puts full_path
254
+ end
255
+
256
+
257
+ thumb_path = ([out_directory, "images", "thumb"] + gallery_path + [clean_image_name]).join("/")
258
+ unless check_timestamp(full_image_name, thumb_path)
259
+ `convert #{full_image_name} -resize #{config[:thumb_size]} #{thumb_path}`
260
+ puts thumb_path
261
+ end
262
+
263
+ minithumb_path = ([out_directory, "images", "minithumb"] + gallery_path + [clean_image_name]).join("/")
264
+ unless check_timestamp(full_image_name, minithumb_path)
265
+ `convert #{full_image_name} -resize #{config[:minithumb_size]} #{minithumb_path}`
266
+ puts minithumb_path
267
+ end
268
+
269
+ File.open(([out_directory] + gallery_path + [base_image_name + ".html"]).join("/"),"w") do |f|
270
+ f.write(@image_tmpl.render(nil, gallery_vars.merge(image_vars)))
271
+ puts ([out_directory] + gallery_path + [base_image_name + ".html"]).join("/")
272
+ end
273
+
274
+ previews << @image_p_tmpl.render(nil, gallery_vars.merge(image_vars))
275
+ child_images << gallery_vars.merge(image_vars)
276
+ end
277
+ end
278
+ FileUtils.mkdir_p(([out_directory] + gallery_path).join("/"))
279
+ File.open(([out_directory] + gallery_path + ["index.html"]).join("/"), "w") do |f|
280
+ f.write(@gallery_tmpl.render(nil, gallery_vars.merge(:image_previews => previews, :gallery_previews => gallery_previews)))
281
+ puts ([out_directory] + gallery_path + ["index.html"]).join("/")
282
+ end
283
+
284
+ gallery_vars[:children] += child_images
285
+
286
+ atom_feed = ([out_directory] + gallery_path + ["index.xml"]).join("/")
287
+ xo = File.open(atom_feed, "w")
288
+
289
+ xml = Builder::XmlMarkup.new(:target => xo)
290
+ xml.instruct!
291
+ xml.feed("xmlns"=>"http://www.w3.org/2005/Atom") do |feed|
292
+ feed.title("Updates to '#{gallery_title}'")
293
+ feed.link("href" => ([config[:http_base]] + gallery_path).join("/"))
294
+ child_images.sort(&sorting_func).last(config[:atom_items]).each do |c_img|
295
+ p
296
+ feed.entry do |entry|
297
+ entry.title(c_img[:image_title])
298
+ entry.updated(c_img[:modified].strftime("%FT%T%z"))
299
+ uri = ([config[:http_base]] + gallery_path + [c_img[:image_page_url]]).join("/")
300
+ img_uri = ([config[:http_base]] + ["images", "thumb"] + gallery_path + [c_img[:image_name]]).join("/")
301
+ full_uri = ([config[:http_base]] + ["images", "full"] + gallery_path + [c_img[:image_name]]).join("/")
302
+ entry.id(uri)
303
+ entry.link("href" => uri)
304
+ entry.content({"type" => "html"}, "<a href='#{img_uri}'><img src='#{full_uri}' /></a> #{c_img[:description]}")
305
+ end
306
+ end
307
+ end
308
+
309
+ puts atom_feed
310
+
311
+ xo.close
312
+
313
+
314
+
315
+ gallery_vars
316
+ end
317
+
318
+ end
319
+
320
+ if ARGV.size < 2
321
+ puts "Usage: galgen <input_directory> <output_directory>"
322
+ puts "Manual: http://bitcheese.net/wiki/code/galgen/manual"
323
+ exit
324
+ end
325
+
326
+ galgen = GalGen.new(ARGV[0])
327
+
328
+ galgen.generate(ARGV[1])
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: galgen
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Voker57
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-02-19 00:00:00 +03:00
18
+ default_executable: galgen
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: builder
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 2
31
+ - 0
32
+ version: "2.0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: RedCloth
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 15
44
+ segments:
45
+ - 1
46
+ - 0
47
+ version: "1.0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: tilt
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 15
59
+ segments:
60
+ - 1
61
+ - 0
62
+ version: "1.0"
63
+ type: :runtime
64
+ version_requirements: *id003
65
+ description: Static HTML gallery generator
66
+ email: voker57@gmail.com
67
+ executables:
68
+ - galgen
69
+ extensions: []
70
+
71
+ extra_rdoc_files: []
72
+
73
+ files:
74
+ - bin/galgen
75
+ - COPYING
76
+ - README.textile
77
+ has_rdoc: true
78
+ homepage: http://bitcheese.net/wiki/code/galgen
79
+ licenses: []
80
+
81
+ post_install_message:
82
+ rdoc_options: []
83
+
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ hash: 3
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ requirements: []
105
+
106
+ rubyforge_project:
107
+ rubygems_version: 1.3.7
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: Gallery Generator
111
+ test_files: []
112
+