directory_listing 0.0.7 → 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.
@@ -0,0 +1,166 @@
1
+ require 'sinatra/base'
2
+
3
+ require 'truncate'
4
+ require 'filesize'
5
+ require 'pathname'
6
+
7
+ # = Easy, CSS-styled, Apache-like directory listings for Sinatra.
8
+ #
9
+ # == Usage
10
+ #
11
+ # list() will return HTML, so the following is a complete Sinatra
12
+ # app that will provide a directory listing of whatever path you navigate to
13
+ # and let you view any file that is served directly:
14
+ #
15
+ # require 'sinatra'
16
+ # require 'sinatra/directory_listing'
17
+ #
18
+ # get '*' do |path|
19
+ # if File.exist?(File.join(settings.public_folder, path))
20
+ # if File.directory?(File.join(settings.public_folder, path))
21
+ # list()
22
+ # else
23
+ # send_file File.join(settings.public_folder, path)
24
+ # end
25
+ # else
26
+ # not_found
27
+ # end
28
+ # end
29
+ #
30
+ # not_found do
31
+ # 'Try again.'
32
+ # end
33
+ #
34
+ # == Options
35
+ #
36
+ # stylesheet # a stylesheet that will be added to the <head> of the generated directory listing
37
+ # readme # an HTML string that will be appended at the footer of the generated directory listing
38
+ # should_list_invisibles # whether the directory listing should include invisibles (dotfiles) - "yes" or "no"
39
+ # last_modified_format # format for last modified date (http://www.ruby-doc.org/core-2.0/Time.html) - defaults to "%Y-%m-%d %H:%M:%S"
40
+ # filename_truncate_length # (integer) length to truncate file names to - defaults to 40
41
+ #
42
+ # == Styling
43
+ #
44
+ # It's pretty easy to figure out how to style directory_listing by looking at the source, but here are some gotchas:
45
+ #
46
+ # Every item listed is a <td> element in a table. Directories will have a class of "dir" and regular files will have a class of "file".
47
+ #
48
+ # You can style the "File" column with this CSS:
49
+ #
50
+ # table tr > td:first-child {
51
+ # text-align: left;
52
+ # }
53
+ #
54
+ # Second column:
55
+ # table tr > td:first-child + td {
56
+ # text-align: left;
57
+ # }
58
+ #
59
+ # Third column:
60
+ # table tr > td:first-child + td + td {
61
+ # text-align: left;
62
+ # }
63
+
64
+
65
+ module Sinatra
66
+ module Directory_listing
67
+
68
+ private
69
+
70
+ def m_time(file)
71
+ file = File.join(settings.public_folder, request.fullpath)
72
+ time = "\t<td>#{File.mtime(file).strftime $last_modified_format}</td>"
73
+ end
74
+
75
+ def size(file)
76
+ dir = request.path
77
+ if File.directory?(File.join(dir, file))
78
+ "\t<td>-</td>"
79
+ else
80
+ file = File.join(settings.public_folder, request.fullpath)
81
+ size = Filesize.from("#{File.stat(file).size} B").pretty
82
+ "\t<td>#{size}</td>"
83
+ end
84
+ end
85
+
86
+ def name(file)
87
+ tfile = file.truncate($filename_truncate_length, '...')
88
+ if (Pathname.new(request.path).cleanpath).eql?((Pathname.new(settings.public_folder)).cleanpath)
89
+ link = file
90
+ else
91
+ link = File.join(request.fullpath, file)
92
+ end
93
+
94
+ html = ""
95
+ if File.directory?(File.join(settings.public_folder, link))
96
+ html << "\t<td class='dir'><a href='#{link}'>#{tfile}</a></td>"
97
+ else
98
+ html << "\t<td class='file'><a href='#{link}'>#{tfile}</a></td>"
99
+ end
100
+ "#{html}"
101
+ end
102
+
103
+ def wrap(file)
104
+ wrapped = ""
105
+ if $should_list_invisibles == "yes"
106
+ wrapped << "\n\t<tr>
107
+ #{name(file)}
108
+ #{m_time(file)}
109
+ #{size(file)}\n\t</tr>"
110
+ else
111
+ if file[0] != "."
112
+ wrapped << "\n\t<tr>
113
+ #{name(file)}
114
+ #{m_time(file)}
115
+ #{size(file)}\n\t</tr>"
116
+ end
117
+ end
118
+ "#{wrapped}"
119
+ end
120
+
121
+ def list(o={})
122
+ options = {
123
+ :should_list_invisibles => "no",
124
+ :last_modified_format => "%Y-%m-%d %H:%M:%S",
125
+ :filename_truncate_length => 40,
126
+ :stylesheet => "",
127
+ :readme => ""
128
+ }.merge(o)
129
+
130
+ $should_list_invisibles = options[:should_list_invisibles]
131
+ $last_modified_format = options[:last_modified_format]
132
+ $filename_truncate_length = options[:filename_truncate_length]
133
+
134
+ html = "<html>\n<head>\n"
135
+ html << "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>\n"
136
+ if options[:stylesheet]
137
+ html << "<link rel=\"stylesheet\" type=\"text/css\" href=\"/#{options[:stylesheet].sub(/^[\/]*/,"")}\">\n"
138
+ end
139
+ html << "</head>\n<body>\n"
140
+ html << "<h1>Index of #{request.path}</h1>\n"
141
+ if request.path != "/"
142
+ html << "<a href='#{Pathname.new(request.path).parent}'>&larr; Parent directory</a><br><br>"
143
+ else
144
+ html << "<a>Root directory</a><br><br>"
145
+ end
146
+ html << "<table>\n"
147
+ html << "\t<tr>\n\t\t<th>File</th>\n\t\t<th>Last modified</th>\n\t\t<th>Size</th>\n\t</tr>\n"
148
+ files = Array.new
149
+ Dir.foreach(File.join(settings.public_folder, request.path), &files.method(:push))
150
+ if files == [".", ".."]
151
+ html << "\t<tr>\n\t\t<th>No files.</th>\n\t\t<th>-</th>\n\t\t<th>-</th>\n\t</tr>"
152
+ else
153
+ files.sort.each do |file|
154
+ html << wrap(file)
155
+ end
156
+ end
157
+ html << "\n</table>\n"
158
+ html << "<br>\n#{options[:readme]}\n" if options[:readme]
159
+ html << "</body>\n</html>\n"
160
+ "#{html}"
161
+ end
162
+
163
+ end
164
+
165
+ helpers Directory_listing
166
+ end
metadata CHANGED
@@ -1,78 +1,75 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: directory_listing
3
- version: !ruby/object:Gem::Version
4
- version: 0.0.7
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.1.0
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Richard Myers
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-26 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
12
+
13
+ date: 2013-06-27 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
15
16
  name: filesize
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: 0.0.2
22
- type: :runtime
23
17
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
18
+ requirement: &id001 !ruby/object:Gem::Requirement
25
19
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
29
23
  version: 0.0.2
30
- - !ruby/object:Gem::Dependency
31
- name: truncate
32
- requirement: !ruby/object:Gem::Requirement
33
- none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: 0.0.4
38
24
  type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: truncate
39
28
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
29
+ requirement: &id002 !ruby/object:Gem::Requirement
41
30
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
45
34
  version: 0.0.4
46
- description: A gem to use with Sinatra for generating easy, CSS-styled, Apache-like
47
- directory listings.
35
+ type: :runtime
36
+ version_requirements: *id002
37
+ description: A Sinatra extension for generating easy, CSS-styled, Apache-like directory listings.
48
38
  email: rick.myers@me.com
49
39
  executables: []
40
+
50
41
  extensions: []
42
+
51
43
  extra_rdoc_files: []
52
- files:
53
- - lib/directory_listing.rb
44
+
45
+ files:
46
+ - lib/sinatra/directory_listing.rb
54
47
  homepage: https://rubygems.org/gems/directory_listing
55
48
  licenses: []
49
+
56
50
  post_install_message:
57
51
  rdoc_options: []
58
- require_paths:
52
+
53
+ require_paths:
59
54
  - lib
60
- required_ruby_version: !ruby/object:Gem::Requirement
55
+ required_ruby_version: !ruby/object:Gem::Requirement
61
56
  none: false
62
- requirements:
63
- - - ! '>='
64
- - !ruby/object:Gem::Version
65
- version: '0'
66
- required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
62
  none: false
68
- requirements:
69
- - - ! '>='
70
- - !ruby/object:Gem::Version
71
- version: '0'
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
72
67
  requirements: []
68
+
73
69
  rubyforge_project:
74
- rubygems_version: 1.8.24
70
+ rubygems_version: 1.8.23
75
71
  signing_key:
76
72
  specification_version: 3
77
73
  summary: Easy, CSS-styled, Apache-like directory listings for Sinatra.
78
74
  test_files: []
75
+
@@ -1,181 +0,0 @@
1
- require 'truncate'
2
- require 'filesize'
3
- require 'pathname'
4
-
5
- # = Easy, CSS-styled, Apache-like directory listings for Sinatra.
6
- #
7
- # == Usage
8
- #
9
- # Directory_listing.list will return HTML, so the following is a complete Sinatra
10
- # app that will provide a directory listing of whatever path you navigate to
11
- # and let you view any file that is served directly:
12
- #
13
- # require 'directory_listing'
14
- #
15
- # get '*' do |path|
16
- # if File.exist?(File.join(settings.public_folder, path))
17
- # if File.directory?(File.join(settings.public_folder, path))
18
- # "#{Directory_listing.list(
19
- # :directory => path,
20
- # :sinatra_public => settings.public_folder
21
- # )}"
22
- # else
23
- # send_file File.join(settings.public_folder, path)
24
- # end
25
- # else
26
- # not_found
27
- # end
28
- # end
29
- #
30
- # not_found do
31
- # 'Try again.'
32
- # end
33
- #
34
- # Any option key may be omitted except for :directory and :sinatra_public. Explanations of options are below.
35
- #
36
- # == Options
37
- #
38
- # directory # the directory to list
39
- # sinatra_public # sinatra's public folder - your public folder (and the default) is likely "settings.public_folder"
40
- # stylesheet # a stylesheet that will be added to the <head> of the generated directory listing
41
- # readme # an HTML string that will be appended at the footer of the generated directory listing
42
- # should_list_invisibles # whether the directory listing should include invisibles (dotfiles) - "yes" or "no"
43
- # last_modified_format # format for last modified date (http://www.ruby-doc.org/core-2.0/Time.html) - defaults to "%Y-%m-%d %H:%M:%S"
44
- # filename_truncate_length # (integer) length to truncate file names to - defaults to 40
45
- #
46
- # == Styling
47
- #
48
- # It's pretty easy to figure out how to style directory_listing by looking at the source, but here are some gotchas:
49
- #
50
- # Every item listed is a <td> element in a table. Directories will have a class of "dir" and regular files will have a class of "file".
51
- #
52
- # You can style the "File" column with this CSS:
53
- #
54
- # table tr > td:first-child {
55
- # text-align: left;
56
- # }
57
- #
58
- # Second column:
59
- # table tr > td:first-child + td {
60
- # text-align: left;
61
- # }
62
- #
63
- # Third column:
64
- # table tr > td:first-child + td + td {
65
- # text-align: left;
66
- # }
67
-
68
- module Directory_listing
69
- @@options = {}
70
-
71
- def self.options=(value)
72
- @@options = value
73
- end
74
-
75
- def self.options()
76
- @@options
77
- end
78
-
79
- def self.list(options)
80
- options = @@options.merge options
81
- raise(ArgumentError, ":directory is required") unless options[:directory]
82
- raise(ArgumentError, ":sinatra_public is required") unless options[:sinatra_public]
83
- pub = options[:sinatra_public]
84
- dir = File.join(pub, options[:directory])
85
-
86
- if options[:should_list_invisibles]
87
- $should_list_invisibles = options[:should_list_invisibles]
88
- else
89
- $should_list_invisibles = "no"
90
- end
91
- if options[:last_modified_format]
92
- $last_modified_format = options[:last_modified_format]
93
- else
94
- $last_modified_format = "%Y-%m-%d %H:%M:%S"
95
- end
96
- if options[:filename_truncate_length]
97
- $filename_truncate_length = options[:filename_truncate_length]
98
- else
99
- $filename_truncate_length = 40
100
- end
101
-
102
- html = "<html>\n<head>\n"
103
- html << "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>\n"
104
- if options[:stylesheet]
105
- html << "<link rel=\"stylesheet\" type=\"text/css\" href=\"/#{options[:stylesheet].sub(/^[\/]*/,"")}\">\n"
106
- end
107
- html << "</head>\n<body>\n"
108
- html << "<h1>Index of #{options[:directory]}</h1>\n"
109
- if options[:directory] != "/"
110
- html << "<a href='#{Pathname.new(options[:directory]).parent}'>&larr; Parent directory</a><br><br>"
111
- else
112
- html << "<a>Root directory</a><br><br>"
113
- end
114
- html << "<table>\n"
115
- html << "\t<tr>\n\t\t<th>File</th>\n\t\t<th>Last modified</th>\n\t\t<th>Size</th>\n\t</tr>\n"
116
- files = Array.new
117
- Dir.foreach(dir, &files.method(:push))
118
- if files == [".", ".."]
119
- html << "\t<tr>\n\t\t<th>No files.</th>\n\t\t<th>-</th>\n\t\t<th>-</th>\n\t</tr>"
120
- else
121
- files.sort.each do |file|
122
- html << wrap(file, dir, pub)
123
- end
124
- end
125
- html << "\n</table>\n"
126
- html << "<br>\n#{options[:readme]}\n" if options[:readme]
127
- html << "</body>\n</html>\n"
128
- "#{html}"
129
- end
130
-
131
- private
132
-
133
- def self.m_time(file, dir)
134
- time = "\t<td>#{File.mtime(File.join(dir, file)).strftime $last_modified_format}</td>"
135
- end
136
-
137
- def self.size(file, dir)
138
- if File.directory?(File.join(dir, file))
139
- "\t<td>-</td>"
140
- else
141
- size = Filesize.from("#{File.stat(File.join(dir, file)).size} B").pretty
142
- "\t<td>#{size}</td>"
143
- end
144
- end
145
-
146
- def self.name(file, dir, pub)
147
- tfile = file.truncate($filename_truncate_length, '...')
148
- if (Pathname.new(dir).cleanpath).eql?((Pathname.new(pub)).cleanpath)
149
- link = file
150
- else
151
- link = File.join(dir.split("/").last, file)
152
- end
153
-
154
- html = ""
155
- if File.directory?(File.join(dir, file))
156
- html << "\t<td class='dir'><a href='#{link}'>#{tfile}</a></td>"
157
- else
158
- html << "\t<td class='file'><a href='#{link}'>#{tfile}</a></td>"
159
- end
160
- "#{html}"
161
- end
162
-
163
- def self.wrap(file, dir, pub)
164
- wrapped = ""
165
- if $should_list_invisibles == "yes"
166
- wrapped << "\n\t<tr>
167
- #{name(file, dir, pub)}
168
- #{m_time(file, dir)}
169
- #{size(file, dir)}\n\t</tr>"
170
- else
171
- if file[0] != "."
172
- wrapped << "\n\t<tr>
173
- #{name(file, dir, pub)}
174
- #{m_time(file, dir)}
175
- #{size(file, dir)}\n\t</tr>"
176
- end
177
- end
178
- "#{wrapped}"
179
- end
180
-
181
- end