imagesize 0.0.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.
- data/History.txt +4 -0
- data/Manifest.txt +28 -0
- data/README.txt +3 -0
- data/Rakefile +97 -0
- data/lib/image_size.rb +5 -0
- data/lib/image_size/image_size.rb +284 -0
- data/lib/image_size/version.rb +9 -0
- data/scripts/txt2html +67 -0
- data/setup.rb +1585 -0
- data/test/2-4-7.png +0 -0
- data/test/4_1_2.gif +0 -0
- data/test/bmp.bmp +0 -0
- data/test/cursor.xbm +6 -0
- data/test/detect.swf +0 -0
- data/test/pbm.pbm +0 -0
- data/test/pcx.pcx +0 -0
- data/test/pgm.pgm +5 -0
- data/test/test.xpm +38 -0
- data/test/test_helper.rb +2 -0
- data/test/test_image_size.rb +71 -0
- data/test/tiff.tiff +0 -0
- data/test/tokyo_tower.jpg +0 -0
- data/test/tower_e.gif.psd +0 -0
- data/website/index.html +80 -0
- data/website/index.txt +31 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +129 -0
- data/website/template.rhtml +48 -0
- metadata +74 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
lib/image_size.rb
|
6
|
+
lib/image_size/version.rb
|
7
|
+
lib/image_size/image_size.rb
|
8
|
+
scripts/txt2html
|
9
|
+
setup.rb
|
10
|
+
test/test_helper.rb
|
11
|
+
test/test_image_size.rb
|
12
|
+
test/2-4-7.png
|
13
|
+
test/4_1_2.gif
|
14
|
+
test/bmp.bmp
|
15
|
+
test/cursor.xbm
|
16
|
+
test/detect.swf
|
17
|
+
test/pbm.pbm
|
18
|
+
test/pcx.pcx
|
19
|
+
test/pgm.pgm
|
20
|
+
test/test.xpm
|
21
|
+
test/tiff.tiff
|
22
|
+
test/tokyo_tower.jpg
|
23
|
+
test/tower_e.gif.psd
|
24
|
+
website/index.html
|
25
|
+
website/index.txt
|
26
|
+
website/javascripts/rounded_corners_lite.inc.js
|
27
|
+
website/stylesheets/screen.css
|
28
|
+
website/template.rhtml
|
data/README.txt
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rake/packagetask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
require 'rake/contrib/rubyforgepublisher'
|
9
|
+
require 'fileutils'
|
10
|
+
require 'hoe'
|
11
|
+
include FileUtils
|
12
|
+
require File.join(File.dirname(__FILE__), 'lib', 'image_size', 'version')
|
13
|
+
|
14
|
+
AUTHOR = 'Keisuke Minami' # can also be an array of Authors
|
15
|
+
EMAIL = "keisuke@rccn.com"
|
16
|
+
DESCRIPTION = "measure image size(GIF, PNG, JPEG ,,, etc)"
|
17
|
+
GEM_NAME = 'imagesize' # what ppl will type to install your gem
|
18
|
+
RUBYFORGE_PROJECT = 'imagesize' # The unix name for your project
|
19
|
+
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
20
|
+
|
21
|
+
|
22
|
+
NAME = "imagesize"
|
23
|
+
REV = nil # UNCOMMENT IF REQUIRED: File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
|
24
|
+
VERS = ENV['VERSION'] || (Imagesize::VERSION::STRING + (REV ? ".#{REV}" : ""))
|
25
|
+
CLEAN.include ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store']
|
26
|
+
RDOC_OPTS = ['--quiet', '--title', 'imagesize documentation',
|
27
|
+
"--opname", "index.html",
|
28
|
+
"--line-numbers",
|
29
|
+
"--main", "README",
|
30
|
+
"--inline-source"]
|
31
|
+
|
32
|
+
class Hoe
|
33
|
+
def extra_deps
|
34
|
+
@extra_deps.reject { |x| Array(x).first == 'hoe' }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Generate all the Rake tasks
|
39
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
40
|
+
hoe = Hoe.new(GEM_NAME, VERS) do |p|
|
41
|
+
p.author = AUTHOR
|
42
|
+
p.description = DESCRIPTION
|
43
|
+
p.email = EMAIL
|
44
|
+
p.summary = DESCRIPTION
|
45
|
+
p.url = HOMEPATH
|
46
|
+
p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
|
47
|
+
p.test_globs = ["test/**/test_*.rb"]
|
48
|
+
p.clean_globs = CLEAN #An array of file patterns to delete on clean.
|
49
|
+
|
50
|
+
# == Optional
|
51
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
52
|
+
#p.extra_deps = [] # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
|
53
|
+
#p.spec_extras = {} # A hash of extra values to set in the gemspec.
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
desc 'Generate website files'
|
58
|
+
task :website_generate do
|
59
|
+
Dir['website/**/*.txt'].each do |txt|
|
60
|
+
sh %{ ruby scripts/txt2html #{txt} > #{txt.gsub(/txt$/,'html')} }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
desc 'Upload website files to rubyforge'
|
65
|
+
task :website_upload do
|
66
|
+
config = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
|
67
|
+
host = "#{config["username"]}@rubyforge.org"
|
68
|
+
remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/"
|
69
|
+
# remote_dir = "/var/www/gforge-projects/#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
|
70
|
+
local_dir = 'website'
|
71
|
+
sh %{rsync -av #{local_dir}/ #{host}:#{remote_dir}}
|
72
|
+
end
|
73
|
+
|
74
|
+
desc 'Generate and upload website files'
|
75
|
+
task :website => [:website_generate, :website_upload]
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
### ここから持ってきた設定
|
80
|
+
### http://d.hatena.ne.jp/secondlife/20061106/1162785661
|
81
|
+
Rake::RDocTask.new do |rdoc|
|
82
|
+
rdoc.rdoc_dir = 'html'
|
83
|
+
rdoc.options += RDOC_OPTS
|
84
|
+
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
|
85
|
+
if ENV['DOC_FILES']
|
86
|
+
rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
|
87
|
+
else
|
88
|
+
# rdoc.rdoc_files.include('README', 'CHANGELOG')
|
89
|
+
rdoc.rdoc_files.include('README.txt')
|
90
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "Publish to RubyForge"
|
95
|
+
task :rubyforge => [:rdoc, :package] do
|
96
|
+
Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'gawgaw61').upload
|
97
|
+
end
|
data/lib/image_size.rb
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
#!ruby
|
2
|
+
|
3
|
+
class ImageSize
|
4
|
+
# Image Type Constants
|
5
|
+
module Type
|
6
|
+
OTHER = "OTHER"
|
7
|
+
GIF = "GIF"
|
8
|
+
PNG = "PNG"
|
9
|
+
JPEG = "JPEG"
|
10
|
+
BMP = "BMP"
|
11
|
+
PPM = "PPM" # PPM is like PBM, PGM, & XV
|
12
|
+
PBM = "PBM"
|
13
|
+
PGM = "PGM"
|
14
|
+
# XV = "XV"
|
15
|
+
XBM = "XBM"
|
16
|
+
TIFF = "TIFF"
|
17
|
+
XPM = "XPM"
|
18
|
+
PSD = "PSD"
|
19
|
+
PCX = "PCX"
|
20
|
+
SWF = "SWF"
|
21
|
+
end
|
22
|
+
|
23
|
+
JpegCodeCheck = [
|
24
|
+
"\xc0", "\xc1", "\xc2", "\xc3",
|
25
|
+
"\xc5", "\xc6", "\xc7",
|
26
|
+
"\xc9", "\xca", "\xcb",
|
27
|
+
"\xcd", "\xce", "\xcf",
|
28
|
+
]
|
29
|
+
|
30
|
+
# image type list
|
31
|
+
def ImageSize.type_list
|
32
|
+
Type.constants
|
33
|
+
end
|
34
|
+
|
35
|
+
# receive image & make size
|
36
|
+
# argument is image String or IO
|
37
|
+
def initialize(img_data, img_type = nil)
|
38
|
+
@img_data = img_data.dup
|
39
|
+
@img_wedth = nil
|
40
|
+
@img_height = nil
|
41
|
+
|
42
|
+
if @img_data.is_a?(IO)
|
43
|
+
@img_top = @img_data.read(128)
|
44
|
+
@img_data.seek(0, 0)
|
45
|
+
# define Singleton-method definition to IO (byte, offset)
|
46
|
+
def @img_data.read_o(length = 1, offset = nil)
|
47
|
+
self.seek(offset, 0) if offset
|
48
|
+
ret = self.read(length)
|
49
|
+
raise "cannot read!!" unless ret
|
50
|
+
ret
|
51
|
+
end
|
52
|
+
elsif @img_data.is_a?(String)
|
53
|
+
@img_top = @img_data[0, 128]
|
54
|
+
# define Singleton-method definition to String (byte, offset)
|
55
|
+
def @img_data.read_o(length = 1, offset = nil)
|
56
|
+
@img_offset = 0 if !(defined?(@img_offset))
|
57
|
+
@img_offset = offset if offset
|
58
|
+
ret = self[@img_offset, length]
|
59
|
+
@img_offset += length
|
60
|
+
ret
|
61
|
+
end
|
62
|
+
else
|
63
|
+
raise "argument class error!! #{img_data.type}"
|
64
|
+
end
|
65
|
+
|
66
|
+
if img_type.nil?
|
67
|
+
@img_type = check_type()
|
68
|
+
else
|
69
|
+
match = false
|
70
|
+
Type.constants.each do |t|
|
71
|
+
match = true if img_type == t
|
72
|
+
end
|
73
|
+
raise("img_type is failed. #{img_type}\n") if match == false
|
74
|
+
@img_type = img_type
|
75
|
+
end
|
76
|
+
|
77
|
+
eval("@img_width, @img_height = measure_" + @img_type + "()") if @img_type != Type::OTHER
|
78
|
+
end
|
79
|
+
|
80
|
+
# get parameter
|
81
|
+
def get_type; @img_type; end
|
82
|
+
def get_height
|
83
|
+
if @img_type == Type::OTHER then nil else @img_height end
|
84
|
+
end
|
85
|
+
def get_width
|
86
|
+
if @img_type == Type::OTHER then nil else @img_width end
|
87
|
+
end
|
88
|
+
|
89
|
+
def check_type()
|
90
|
+
if @img_top =~ /^GIF8[7,9]a/ then Type::GIF
|
91
|
+
elsif @img_top[0, 8] == "\x89PNG\x0d\x0a\x1a\x0a" then Type::PNG
|
92
|
+
elsif @img_top[0, 2] == "\xFF\xD8" then Type::JPEG
|
93
|
+
elsif @img_top[0, 2] == 'BM' then Type::BMP
|
94
|
+
elsif @img_top =~ /^P[1-7]/ then Type::PPM
|
95
|
+
elsif @img_top =~ /\#define\s+\S+\s+\d+/ then Type::XBM
|
96
|
+
elsif @img_top[0, 4] == "MM\x00\x2a" then Type::TIFF
|
97
|
+
elsif @img_top[0, 4] == "II\x2a\x00" then Type::TIFF
|
98
|
+
elsif @img_top =~ /\/\* XPM \*\// then Type::XPM
|
99
|
+
elsif @img_top[0, 4] == "8BPS" then Type::PSD
|
100
|
+
elsif @img_top[1, 2] == "WS" then Type::SWF
|
101
|
+
elsif @img_top[0] == 10 then Type::PCX
|
102
|
+
else Type::OTHER
|
103
|
+
end
|
104
|
+
end
|
105
|
+
private(:check_type)
|
106
|
+
|
107
|
+
def measure_GIF()
|
108
|
+
@img_data.read_o(6)
|
109
|
+
@img_data.read_o(4).unpack('vv')
|
110
|
+
end
|
111
|
+
private(:measure_GIF)
|
112
|
+
|
113
|
+
def measure_PNG()
|
114
|
+
@img_data.read_o(12)
|
115
|
+
raise "This file is not PNG." unless @img_data.read_o(4) == "IHDR"
|
116
|
+
@img_data.read_o(8).unpack('NN')
|
117
|
+
end
|
118
|
+
private(:measure_PNG)
|
119
|
+
|
120
|
+
def measure_JPEG()
|
121
|
+
c_marker = "\xFF" # Section marker.
|
122
|
+
@img_data.read_o(2)
|
123
|
+
while(true)
|
124
|
+
marker, code, length = @img_data.read_o(4).unpack('aan')
|
125
|
+
raise "JPEG marker not found!" if marker != c_marker
|
126
|
+
|
127
|
+
if JpegCodeCheck.include?(code)
|
128
|
+
height, width = @img_data.read_o(5).unpack('xnn')
|
129
|
+
return([width, height])
|
130
|
+
end
|
131
|
+
@img_data.read_o(length - 2)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
private(:measure_JPEG)
|
135
|
+
|
136
|
+
def measure_BMP()
|
137
|
+
@img_data.read_o(26).unpack("x18VV");
|
138
|
+
end
|
139
|
+
private(:measure_BMP)
|
140
|
+
|
141
|
+
def measure_PPM()
|
142
|
+
header = @img_data.read_o(1024)
|
143
|
+
header.gsub!(/^\#[^\n\r]*/m, "")
|
144
|
+
header =~ /^(P[1-6])\s+?(\d+)\s+?(\d+)/m
|
145
|
+
width = $2.to_i; height = $3.to_i
|
146
|
+
case $1
|
147
|
+
when "P1", "P4" then @img_type = "PBM"
|
148
|
+
when "P2", "P5" then @img_type = "PGM"
|
149
|
+
when "P3", "P6" then @img_type = "PPM"
|
150
|
+
# when "P7"
|
151
|
+
# @img_type = "XV"
|
152
|
+
# header =~ /IMGINFO:(\d+)x(\d+)/m
|
153
|
+
# width = $1.to_i; height = $2.to_i
|
154
|
+
end
|
155
|
+
[width, height]
|
156
|
+
end
|
157
|
+
private(:measure_PPM)
|
158
|
+
|
159
|
+
alias :measure_PGM :measure_PPM
|
160
|
+
private(:measure_PGM)
|
161
|
+
alias :measure_PBM :measure_PPM
|
162
|
+
private(:measure_PBM)
|
163
|
+
|
164
|
+
def measure_XBM()
|
165
|
+
@img_data.read_o(1024) =~ /^\#define\s*\S*\s*(\d+)\s*\n\#define\s*\S*\s*(\d+)/mi
|
166
|
+
[$1.to_i, $2.to_i]
|
167
|
+
end
|
168
|
+
private(:measure_XBM)
|
169
|
+
|
170
|
+
def measure_XPM()
|
171
|
+
width = height = nil
|
172
|
+
while(line = @img_data.read_o(1024))
|
173
|
+
if line =~ /"\s*(\d+)\s+(\d+)(\s+\d+\s+\d+){1,2}\s*"/m
|
174
|
+
width = $1.to_i; height = $2.to_i
|
175
|
+
break
|
176
|
+
end
|
177
|
+
end
|
178
|
+
[width, height]
|
179
|
+
end
|
180
|
+
private(:measure_XPM)
|
181
|
+
|
182
|
+
def measure_PSD()
|
183
|
+
@img_data.read_o(26).unpack("x14NN")
|
184
|
+
end
|
185
|
+
private(:measure_PSD)
|
186
|
+
|
187
|
+
def measure_TIFF()
|
188
|
+
endian = if (@img_data.read_o(4) =~ /II\x2a\x00/o) then 'v' else 'n' end
|
189
|
+
# 'v' little-endian 'n' default to big-endian
|
190
|
+
|
191
|
+
packspec = [
|
192
|
+
nil, # nothing (shouldn't happen)
|
193
|
+
'C', # BYTE (8-bit unsigned integer)
|
194
|
+
nil, # ASCII
|
195
|
+
endian, # SHORT (16-bit unsigned integer)
|
196
|
+
endian.upcase, # LONG (32-bit unsigned integer)
|
197
|
+
nil, # RATIONAL
|
198
|
+
'c', # SBYTE (8-bit signed integer)
|
199
|
+
nil, # UNDEFINED
|
200
|
+
endian, # SSHORT (16-bit unsigned integer)
|
201
|
+
endian.upcase, # SLONG (32-bit unsigned integer)
|
202
|
+
]
|
203
|
+
|
204
|
+
offset = @img_data.read_o(4).unpack(endian.upcase)[0] # Get offset to IFD
|
205
|
+
|
206
|
+
ifd = @img_data.read_o(2, offset)
|
207
|
+
num_dirent = ifd.unpack(endian)[0] # Make it useful
|
208
|
+
offset += 2
|
209
|
+
num_dirent = offset + (num_dirent * 12); # Calc. maximum offset of IFD
|
210
|
+
|
211
|
+
ifd = width = height = nil
|
212
|
+
while(width.nil? || height.nil?)
|
213
|
+
ifd = @img_data.read_o(12, offset) # Get first directory entry
|
214
|
+
break if (ifd.nil? || (offset > num_dirent))
|
215
|
+
offset += 12
|
216
|
+
tag = ifd.unpack(endian)[0] # ...and decode its tag
|
217
|
+
type = ifd[2, 2].unpack(endian)[0] # ...and the data type
|
218
|
+
|
219
|
+
# Check the type for sanity.
|
220
|
+
next if (type > packspec.size + 0) || (packspec[type].nil?)
|
221
|
+
if tag == 0x0100 # Decode the value
|
222
|
+
width = ifd[8, 4].unpack(packspec[type])[0]
|
223
|
+
elsif tag == 0x0101 # Decode the value
|
224
|
+
height = ifd[8, 4].unpack(packspec[type])[0]
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
raise "#{if width.nil? then 'width not defined.' end} #{if height.nil? then 'height not defined.' end}" if width.nil? || height.nil?
|
229
|
+
[width, height]
|
230
|
+
end
|
231
|
+
private(:measure_TIFF)
|
232
|
+
|
233
|
+
def measure_PCX()
|
234
|
+
header = @img_data.read_o(128)
|
235
|
+
head_part = header.unpack('C4S4')
|
236
|
+
width = head_part[6] - head_part[4] + 1
|
237
|
+
height = head_part[7] - head_part[5] + 1
|
238
|
+
[width, height]
|
239
|
+
end
|
240
|
+
private(:measure_PCX)
|
241
|
+
|
242
|
+
def measure_SWF()
|
243
|
+
header = @img_data.read_o(9)
|
244
|
+
|
245
|
+
sig1 = header[0,1]
|
246
|
+
sig2 = header[1,1]
|
247
|
+
sig3 = header[2,1]
|
248
|
+
|
249
|
+
if !((sig1 == 'F' || sig1 == 'C') && sig2 == 'W' && sig3 == 'S')
|
250
|
+
raise("This file is not SWF.")
|
251
|
+
end
|
252
|
+
|
253
|
+
bit_length = Integer("0b#{header.unpack('@8B5')}")
|
254
|
+
header << @img_data.read_o(bit_length*4/8+1)
|
255
|
+
str = header.unpack("@8B#{5+bit_length*4}")[0]
|
256
|
+
last = 5
|
257
|
+
x_min = Integer("0b#{str[last,bit_length]}")
|
258
|
+
x_max = Integer("0b#{str[(last += bit_length),bit_length]}")
|
259
|
+
y_min = Integer("0b#{str[(last += bit_length),bit_length]}")
|
260
|
+
y_max = Integer("0b#{str[(last += bit_length),bit_length]}")
|
261
|
+
width = (x_max - x_min)/20
|
262
|
+
height = (y_max - y_min)/20
|
263
|
+
[width, height]
|
264
|
+
end
|
265
|
+
private(:measure_PCX)
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
if __FILE__ == $0
|
270
|
+
print "TypeList: #{ImageSize.type.inspect}\n"
|
271
|
+
|
272
|
+
Dir.glob("*").each do |file|
|
273
|
+
print "#{file} (string)\n"
|
274
|
+
open(file, "rb") do |fh|
|
275
|
+
img = ImageSize.new(fh.read)
|
276
|
+
print <<-EOF
|
277
|
+
type: #{img.get_type.inspect}
|
278
|
+
width: #{img.get_width.inspect}
|
279
|
+
height: #{img.get_height.inspect}
|
280
|
+
EOF
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
data/scripts/txt2html
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'redcloth'
|
5
|
+
require 'syntax/convertors/html'
|
6
|
+
require 'erb'
|
7
|
+
require File.dirname(__FILE__) + '/../lib/image_size/version.rb'
|
8
|
+
|
9
|
+
version = Imagesize::VERSION::STRING
|
10
|
+
download = 'http://rubyforge.org/projects/imagesize'
|
11
|
+
|
12
|
+
class Fixnum
|
13
|
+
def ordinal
|
14
|
+
# teens
|
15
|
+
return 'th' if (10..19).include?(self % 100)
|
16
|
+
# others
|
17
|
+
case self % 10
|
18
|
+
when 1: return 'st'
|
19
|
+
when 2: return 'nd'
|
20
|
+
when 3: return 'rd'
|
21
|
+
else return 'th'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Time
|
27
|
+
def pretty
|
28
|
+
return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def convert_syntax(syntax, source)
|
33
|
+
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
34
|
+
end
|
35
|
+
|
36
|
+
if ARGV.length >= 1
|
37
|
+
src, template = ARGV
|
38
|
+
template ||= File.dirname(__FILE__) + '/../website/template.rhtml'
|
39
|
+
|
40
|
+
else
|
41
|
+
puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
|
42
|
+
exit!
|
43
|
+
end
|
44
|
+
|
45
|
+
template = ERB.new(File.open(template).read)
|
46
|
+
|
47
|
+
title = nil
|
48
|
+
body = nil
|
49
|
+
File.open(src) do |fsrc|
|
50
|
+
title_text = fsrc.readline
|
51
|
+
body_text = fsrc.read
|
52
|
+
syntax_items = []
|
53
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</>!m){
|
54
|
+
ident = syntax_items.length
|
55
|
+
element, syntax, source = $1, $2, $3
|
56
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
57
|
+
"syntax-temp-#{ident}"
|
58
|
+
}
|
59
|
+
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
60
|
+
body = RedCloth.new(body_text).to_html
|
61
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
62
|
+
end
|
63
|
+
stat = File.stat(src)
|
64
|
+
created = stat.ctime
|
65
|
+
modified = stat.mtime
|
66
|
+
|
67
|
+
$stdout << template.result(binding)
|