dropsite 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README +25 -0
- data/Rakefile +33 -0
- data/bin/dropsite +38 -0
- data/dropsite.gemspec +28 -0
- data/lib/dropsite/dir_renderer.rb +56 -0
- data/lib/dropsite/plugins/simple_index/assets/css/reset.css +30 -0
- data/lib/dropsite/plugins/simple_index/assets/css/simple_index.css +98 -0
- data/lib/dropsite/plugins/simple_index/assets/images/icons/directory.png +0 -0
- data/lib/dropsite/plugins/simple_index/assets/images/icons/image.png +0 -0
- data/lib/dropsite/plugins/simple_index/assets/images/icons/pdf.png +0 -0
- data/lib/dropsite/plugins/simple_index/assets/images/icons/script.png +0 -0
- data/lib/dropsite/plugins/simple_index/assets/images/icons/text.png +0 -0
- data/lib/dropsite/plugins/simple_index/assets/images/icons/unknown.png +0 -0
- data/lib/dropsite/plugins/simple_index/assets/images/row-bg.png +0 -0
- data/lib/dropsite/plugins/simple_index/assets/simple_index.js +3 -0
- data/lib/dropsite/plugins/simple_index/simple_index.erb +37 -0
- data/lib/dropsite/plugins/simple_index/simple_index.rb +5 -0
- data/lib/dropsite/plugins.rb +5 -0
- data/lib/dropsite/render_helper.rb +97 -0
- data/lib/dropsite/site.rb +106 -0
- data/lib/dropsite/site_dir.rb +59 -0
- data/lib/dropsite/site_file.rb +41 -0
- data/lib/dropsite/site_item.rb +25 -0
- data/lib/dropsite.rb +30 -0
- data/test/fixtures/simple_public/file1.txt +1 -0
- data/test/fixtures/simple_public/file2.txt +1 -0
- data/test/fixtures/simple_public/pics/leaves.jpg +0 -0
- data/test/fixtures/simple_public/pics/people/beach.jpg +0 -0
- data/test/fixtures/simple_public/pics/people/concert.jpg +0 -0
- data/test/fixtures/simple_public/pics/sculpture.jpg +0 -0
- data/test/helper.rb +14 -0
- data/test/test_render_helper.rb +97 -0
- data/test/test_site.rb +41 -0
- data/test/test_site_dir.rb +20 -0
- data/test/test_site_file.rb +41 -0
- data/test/test_write_site.rb +102 -0
- metadata +107 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
(The MIT License)
|
2
|
+
|
3
|
+
Copyright (c) 2010 Aaron Royer
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
dropsite
|
2
|
+
gem install dropsite
|
3
|
+
|
4
|
+
Dropsite creates a site of interlinked file index pages in the Public directory
|
5
|
+
of your Dropbox. The site created is minimally invasive to your Public
|
6
|
+
directory by only creating one top-level HTML page and one folder, leaving your
|
7
|
+
directories unjunked.
|
8
|
+
|
9
|
+
BE WARNED: while this seems to work fine, it is presently considered
|
10
|
+
experimental.
|
11
|
+
|
12
|
+
To create the site:
|
13
|
+
$ dropsite
|
14
|
+
|
15
|
+
This deletes "index.html" and the directory "dropsite" in your Dropbox Public
|
16
|
+
directory if they exist, creates "index.html" as the top-level index, and puts
|
17
|
+
the rest of the index pages and assets in the "dropsite" directory.
|
18
|
+
|
19
|
+
To specify a different Dropbox directory:
|
20
|
+
$ dropsite --dropbox-home ~/Somewhere/Else
|
21
|
+
|
22
|
+
You can also use this if you just want to test this elsewhere before turning
|
23
|
+
it loose on your precious files.
|
24
|
+
|
25
|
+
MIT licensed - see LICENSE
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << 'lib'
|
7
|
+
t.pattern = 'test/**/test_*.rb'
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => [:test]
|
11
|
+
|
12
|
+
begin
|
13
|
+
require 'rcov/rcovtask'
|
14
|
+
Rcov::RcovTask.new do |t|
|
15
|
+
t.libs << 'test'
|
16
|
+
t.test_files = FileList['test/**/test_*.rb']
|
17
|
+
t.verbose = true
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
end
|
21
|
+
|
22
|
+
Rake::RDocTask.new do |rdoc|
|
23
|
+
rdoc.rdoc_dir = 'rdoc'
|
24
|
+
rdoc.title = 'dropsite'
|
25
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
26
|
+
rdoc.rdoc_files.include('README*')
|
27
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Build gem package"
|
31
|
+
task :package => 'dropsite.gemspec' do
|
32
|
+
sh "gem build dropsite.gemspec"
|
33
|
+
end
|
data/bin/dropsite
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
# TODO: take this out later
|
6
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
7
|
+
require 'dropsite'
|
8
|
+
include Dropsite
|
9
|
+
|
10
|
+
options = {
|
11
|
+
:quiet => false
|
12
|
+
}
|
13
|
+
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.on('-d', '--dropbox-home [PATH]', 'Specify Dropbox directory') {|path| options[:dropbox_home] = path }
|
16
|
+
opts.on('-q', '--quiet', 'Suppress site processing output') {|| options[:quiet] = true }
|
17
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
18
|
+
puts opts
|
19
|
+
exit
|
20
|
+
end
|
21
|
+
opts.on_tail('--version', 'Show version') do
|
22
|
+
puts "Dropsite version: #{Dropsite::VERSION}"
|
23
|
+
exit
|
24
|
+
end
|
25
|
+
end.parse!
|
26
|
+
|
27
|
+
options[:dropbox_home] = Dropsite.find_dropbox_dir if not options[:dropbox_home]
|
28
|
+
|
29
|
+
if !options[:dropbox_home] || !File.exist?(options[:dropbox_home])
|
30
|
+
$stderr.puts 'Dropbox home directory cannot be found or does not exist'
|
31
|
+
$stderr.puts 'Set valid directory with --dropbox-home DIRECTORY'
|
32
|
+
exit 1
|
33
|
+
end
|
34
|
+
|
35
|
+
options[:public_dir] = File.join(options[:dropbox_home], 'Public')
|
36
|
+
|
37
|
+
site = Dropsite::Site.new(options)
|
38
|
+
site.process
|
data/dropsite.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'dropsite'
|
3
|
+
s.version = '0.2'
|
4
|
+
s.platform = Gem::Platform::RUBY
|
5
|
+
|
6
|
+
s.description = "creates index pages in your Dropbox public directory"
|
7
|
+
s.summary = "Dropsite creates a site of interlinked file index pages in " +
|
8
|
+
"the Public directory of your Dropbox. The site created is minimally " +
|
9
|
+
"invasive to your Public directory by only creating one top-level " +
|
10
|
+
"HTML page and one folder, leaving your directories unjunked." +
|
11
|
+
"\nBE WARNED: while I _think_ this probably works fine, it is " +
|
12
|
+
"presently considered experimental."
|
13
|
+
|
14
|
+
s.authors = ["Aaron Royer"]
|
15
|
+
s.email = "aaronroyer@gmail.com"
|
16
|
+
|
17
|
+
s.files = Dir['{bin/*,lib/**/*,test/**/*}'] +
|
18
|
+
%w(README LICENSE dropsite.gemspec Rakefile)
|
19
|
+
|
20
|
+
s.executables << 'dropsite'
|
21
|
+
|
22
|
+
s.test_files = s.files.select {|path| path =~ /^test\/test_.*\.rb/}
|
23
|
+
|
24
|
+
s.has_rdoc = true
|
25
|
+
s.homepage = "https://rubygems.org/gems/dropsite"
|
26
|
+
s.rdoc_options = ["--line-numbers", "--inline-source"]
|
27
|
+
s.require_paths = %w[lib]
|
28
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Dropsite
|
4
|
+
class DirRenderer
|
5
|
+
TEMPLATE_EXTENSIONS = ['.erb']
|
6
|
+
|
7
|
+
@@renderers = []
|
8
|
+
|
9
|
+
def self.inherited(subclass)
|
10
|
+
renderer = subclass.new
|
11
|
+
|
12
|
+
plugin_dir = File.dirname(caller[0].split(':')[0])
|
13
|
+
template_file = Dir.entries(plugin_dir).find {|e| TEMPLATE_EXTENSIONS.include? File.extname(e)}
|
14
|
+
renderer.template_path = template_file ? File.join(plugin_dir, template_file) : nil
|
15
|
+
renderer.assets_dir = File.join(plugin_dir, 'assets')
|
16
|
+
@@renderers << renderer
|
17
|
+
end
|
18
|
+
|
19
|
+
def DirRenderer.renderers
|
20
|
+
@@renderers
|
21
|
+
end
|
22
|
+
|
23
|
+
# Find the first renderer that can render the given SiteDir. Non-default (user) plugins
|
24
|
+
# are searched first.
|
25
|
+
def DirRenderer.find_renderer(site_dir)
|
26
|
+
@@renderers.partition {|r| !r.is_default? }.flatten.find {|r| r.can_render?(site_dir)}
|
27
|
+
end
|
28
|
+
|
29
|
+
def DirRenderer.find_renderer_and_render(site_dir)
|
30
|
+
DirRenderer.find_renderer(site_dir).render(site_dir)
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_accessor :template_path, :assets_dir
|
34
|
+
|
35
|
+
# Overridden in subclass if you don't want to just find and use a template
|
36
|
+
def render(site_dir)
|
37
|
+
site_dir.rendered_by = self.class
|
38
|
+
|
39
|
+
if File.extname(template_path) == '.erb'
|
40
|
+
@template = @template || ERB.new(IO.read(template_path))
|
41
|
+
@template.result(site_dir.get_binding)
|
42
|
+
else
|
43
|
+
raise "Don't know how to render: #{template_path}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Overriden in subclass or this won't do jack
|
48
|
+
def can_render?(site_dir)
|
49
|
+
is_default?
|
50
|
+
end
|
51
|
+
|
52
|
+
def is_default?
|
53
|
+
false
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td {
|
2
|
+
margin:0;
|
3
|
+
padding:0;
|
4
|
+
}
|
5
|
+
table {
|
6
|
+
border-collapse:collapse;
|
7
|
+
border-spacing:0;
|
8
|
+
}
|
9
|
+
fieldset,img {
|
10
|
+
border:0;
|
11
|
+
}
|
12
|
+
address,caption,cite,code,dfn,em,strong,th,var {
|
13
|
+
font-style:normal;
|
14
|
+
font-weight:normal;
|
15
|
+
}
|
16
|
+
ol,ul {
|
17
|
+
list-style:none;
|
18
|
+
}
|
19
|
+
caption,th {
|
20
|
+
text-align:left;
|
21
|
+
}
|
22
|
+
h1,h2,h3,h4,h5,h6 {
|
23
|
+
font-size:100%;
|
24
|
+
font-weight:normal;
|
25
|
+
}
|
26
|
+
q:before,q:after {
|
27
|
+
content:'';
|
28
|
+
}
|
29
|
+
abbr,acronym { border:0;
|
30
|
+
}
|
@@ -0,0 +1,98 @@
|
|
1
|
+
body {
|
2
|
+
background-color: white;
|
3
|
+
color: #484848;
|
4
|
+
font: 13.34px Helvetica, Arial, freesans, clean, sans-serif;
|
5
|
+
font-size: 90%;
|
6
|
+
text-align: center;
|
7
|
+
}
|
8
|
+
|
9
|
+
#content {
|
10
|
+
width: 920px;
|
11
|
+
margin-left: auto;
|
12
|
+
margin-right: auto;
|
13
|
+
text-align: left;
|
14
|
+
}
|
15
|
+
|
16
|
+
#breadcrumbs {
|
17
|
+
margin-top: 20px;
|
18
|
+
font-size: 140%;
|
19
|
+
}
|
20
|
+
|
21
|
+
#breadcrumbs .sep {
|
22
|
+
margin-left: 5px;
|
23
|
+
margin-right: 10px;
|
24
|
+
}
|
25
|
+
|
26
|
+
#breadcrumbs .root-link, #breadcrumbs .parent-dir-link {
|
27
|
+
text-decoration: none;
|
28
|
+
}
|
29
|
+
|
30
|
+
#breadcrumbs .root-link:hover, .parent-dir-link:hover {
|
31
|
+
text-decoration: underline;
|
32
|
+
}
|
33
|
+
|
34
|
+
#breadcrumbs .root-link {
|
35
|
+
color: #4183C4;
|
36
|
+
font-weight: bold;
|
37
|
+
}
|
38
|
+
|
39
|
+
#breadcrumbs .parent-dir-link {
|
40
|
+
color: #4183C4;
|
41
|
+
}
|
42
|
+
|
43
|
+
#breadcrumbs .current-dir {
|
44
|
+
color: #000000;
|
45
|
+
}
|
46
|
+
|
47
|
+
#file-list {
|
48
|
+
margin-top: 10px;
|
49
|
+
width: 100%;
|
50
|
+
}
|
51
|
+
|
52
|
+
#file-list .header {
|
53
|
+
background-color: #eaeaea;
|
54
|
+
border: 1px solid #e1e1e1;
|
55
|
+
color: #999999;
|
56
|
+
height: 28px;
|
57
|
+
}
|
58
|
+
|
59
|
+
.entry {
|
60
|
+
height: 28px;
|
61
|
+
border: 1px solid #e1e1e1;
|
62
|
+
border-top: none;
|
63
|
+
background-image: url(../images/row-bg.png);
|
64
|
+
font-family: Monaco, 'Courier New', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
65
|
+
}
|
66
|
+
|
67
|
+
.entry td {
|
68
|
+
vertical-align: middle;
|
69
|
+
}
|
70
|
+
|
71
|
+
.entry td a {
|
72
|
+
color: #4183C4;
|
73
|
+
text-decoration: none;
|
74
|
+
}
|
75
|
+
|
76
|
+
.entry td a:hover {
|
77
|
+
text-decoration: underline;
|
78
|
+
}
|
79
|
+
|
80
|
+
.entry .icon {
|
81
|
+
width: 28px;
|
82
|
+
padding-left: 12px;
|
83
|
+
padding-top: 4px;
|
84
|
+
}
|
85
|
+
|
86
|
+
.entry .link {
|
87
|
+
min-width: 300px;
|
88
|
+
}
|
89
|
+
|
90
|
+
.entry .type {
|
91
|
+
padding-right: 10px;
|
92
|
+
min-width: 120px;
|
93
|
+
}
|
94
|
+
|
95
|
+
.entry .size {
|
96
|
+
padding-right: 10px;
|
97
|
+
min-width: 70px;
|
98
|
+
}
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
2
|
+
"http://www.w3.org/TR/html4/strict.dtd">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
6
|
+
<title>My Dropbox Files<%= " - #{name}" if !root? %></title>
|
7
|
+
<%= stylesheet_link_tag 'reset' %>
|
8
|
+
<%= stylesheet_link_tag 'simple_index' %>
|
9
|
+
<%= javascript_include_tag 'simple_index' %>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<div id="content">
|
13
|
+
<div id="breadcrumbs">
|
14
|
+
<a class="root-link" href="<%= back_link('root') %>">my files</a>
|
15
|
+
<% each_parent_directory_link_tag(false, {:class => 'parent-dir-link'}) do |tag| %>
|
16
|
+
<span class="sep">/</span><%= tag %>
|
17
|
+
<% end %>
|
18
|
+
<% if !root? %>
|
19
|
+
<span class="sep">/</span><span class="current-dir"><%= name %></span>
|
20
|
+
<% end %>
|
21
|
+
</div>
|
22
|
+
<table id="file-list">
|
23
|
+
<tr class="header">
|
24
|
+
<th> </th><th>name</th><th>type</th><th>size</th>
|
25
|
+
</tr>
|
26
|
+
<% @entries.sort.each do |entry| %>
|
27
|
+
<tr class="entry">
|
28
|
+
<td class="icon"><%= image_tag "icons/#{entry.file_type}.png" %></td>
|
29
|
+
<td class="link"><a href="<%= entry.link %>"><%= entry.name %></a></td>
|
30
|
+
<td class="type"><%= entry.file_type %></td>
|
31
|
+
<td class="size"><%= entry.size %></td>
|
32
|
+
</tr>
|
33
|
+
<% end %>
|
34
|
+
</table>
|
35
|
+
</div>
|
36
|
+
</body>
|
37
|
+
</html>
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Dropsite
|
2
|
+
|
3
|
+
# Helper methods, accessible in templates, to be included in renderable items
|
4
|
+
module RenderHelper
|
5
|
+
attr_accessor :rendered_by
|
6
|
+
|
7
|
+
def link
|
8
|
+
# TODO: URL escape links
|
9
|
+
if top_level? && (!is_a? SiteDir)
|
10
|
+
name
|
11
|
+
else
|
12
|
+
if is_a? SiteDir # TODO: do a dynamic renderable test?
|
13
|
+
top_level? ? "dropsite/#{@path}.html" : "#{@path}.html".sub(/^\//, '')
|
14
|
+
else
|
15
|
+
# Builds a link back up to the file in Public root since the pages
|
16
|
+
# are built in a parallel directory structure
|
17
|
+
dirs_up = @path.split(File::SEPARATOR).size - 1
|
18
|
+
(['..'] * dirs_up).join('/') + "/#{@path}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def stylesheet_link_tag(stylesheet_name)
|
24
|
+
stylesheet_name = "#{stylesheet_name}.css" if not stylesheet_name =~ /\.css$/
|
25
|
+
%{<link rel="stylesheet" href="#{assets_link_base}css/#{stylesheet_name}" type="text/css" media="screen">}
|
26
|
+
end
|
27
|
+
|
28
|
+
def javascript_include_tag(javascript_file_name)
|
29
|
+
javascript_file_name = "#{javascript_file_name}.js" if not javascript_file_name =~ /\.js$/
|
30
|
+
%{<script type="text/javascript" src="#{assets_link_base}js/#{javascript_file_name}"></script>}
|
31
|
+
end
|
32
|
+
|
33
|
+
def image_tag(image_file_name)
|
34
|
+
%{<img src="#{assets_link_base}images/#{image_file_name}" />}
|
35
|
+
end
|
36
|
+
|
37
|
+
def parent_directory_link_tag(levels_up=1, options={})
|
38
|
+
%{<a href="#{back_link(levels_up)}"#{tag_attributes(options)}>#{parent_dir_name(levels_up)}</a>}
|
39
|
+
end
|
40
|
+
|
41
|
+
def each_parent_directory_link_tag(*args)
|
42
|
+
include_root = true
|
43
|
+
include_root = args[0] if args.size > 0 && (!args[0].is_a? Hash)
|
44
|
+
options = args.find {|arg| arg.is_a? Hash}
|
45
|
+
options = {} if !options
|
46
|
+
|
47
|
+
levels_up = path.split('/').size
|
48
|
+
levels_up = levels_up - 1 if !include_root
|
49
|
+
levels_up.downto(1).each do |level_up|
|
50
|
+
yield parent_directory_link_tag(level_up, options)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def assets_link_base
|
55
|
+
if root?
|
56
|
+
"dropsite/dropsite-assets/#{Dropsite.underscorize(rendered_by)}/"
|
57
|
+
else
|
58
|
+
# Work our way BACK up the path - crazy, right? Gotta do it though.
|
59
|
+
dirs_up = path.split(File::SEPARATOR).size - 1
|
60
|
+
(['..'] * dirs_up).join('/') + "#{'/' if dirs_up > 0}dropsite-assets/#{Dropsite.underscorize(rendered_by)}/"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get a link to a parent page
|
65
|
+
def back_link(levels_up=1)
|
66
|
+
# TODO: factor this out a bit between parent_dir_name
|
67
|
+
if levels_up.is_a?(Integer) && levels_up > 0 && levels_up < path.split('/').size
|
68
|
+
dir_name = path.split('/')[(levels_up + 1) * -1]
|
69
|
+
dir_name = 'index' if dir_name.empty?
|
70
|
+
(['..'] * (levels_up)).join('/') + "/#{dir_name}.html"
|
71
|
+
else
|
72
|
+
# Give the root index if we're confused
|
73
|
+
root? ? '' : (['..'] * (path.split('/').size)).join('/') + '/index.html'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def parent_dir_name(levels_up=1)
|
78
|
+
if levels_up.is_a?(Integer) && levels_up > 0 && levels_up < path.split('/').size
|
79
|
+
dir_name = path.split('/')[(levels_up + 1) * -1]
|
80
|
+
dir_name.empty? ? 'index' : dir_name
|
81
|
+
else
|
82
|
+
# TODO: make this configurable
|
83
|
+
'my files'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def get_binding
|
88
|
+
binding
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
|
93
|
+
def tag_attributes(options)
|
94
|
+
options.empty? ? '' : ' ' + options.keys.map {|k| %{#{k.to_s}="#{options[k].to_s}"} }.join
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Dropsite
|
4
|
+
VERSION = '0.2'
|
5
|
+
|
6
|
+
# Main site builder class. Some inspiration here from Jekyll (github.com/mojombo/jekyll).
|
7
|
+
class Site
|
8
|
+
attr_reader :site_tree, :public_dir
|
9
|
+
|
10
|
+
def initialize(config)
|
11
|
+
if config.is_a? String
|
12
|
+
@public_dir = config
|
13
|
+
@excludes = []
|
14
|
+
@quiet = false
|
15
|
+
else
|
16
|
+
@config = config.clone
|
17
|
+
@public_dir = config[:public_dir]
|
18
|
+
@excludes = config[:excludes] || []
|
19
|
+
@quiet = config[:quiet] || false
|
20
|
+
end
|
21
|
+
|
22
|
+
@site_tree = nil
|
23
|
+
@site_files_dir = File.join(@public_dir, 'dropsite')
|
24
|
+
end
|
25
|
+
|
26
|
+
def process
|
27
|
+
clean
|
28
|
+
read
|
29
|
+
render
|
30
|
+
write
|
31
|
+
end
|
32
|
+
|
33
|
+
# Cleans up files previously generated by Dropsite (or at least ones)
|
34
|
+
# that look like they are. By default this will be an index.html
|
35
|
+
# file and dropsite directory in the Public directory root.
|
36
|
+
def clean
|
37
|
+
if File.exist?(@site_files_dir)
|
38
|
+
notice "Deleting existing site files dir at #{@site_files_dir}"
|
39
|
+
FileUtils.rm_rf(@site_files_dir)
|
40
|
+
end
|
41
|
+
|
42
|
+
index_file = File.join(@public_dir, 'index.html')
|
43
|
+
if File.exist?(index_file)
|
44
|
+
notice "Deleting existing top-level index at #{index_file}"
|
45
|
+
File.delete(index_file)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def read
|
50
|
+
@site_tree = read_directory
|
51
|
+
end
|
52
|
+
|
53
|
+
def render
|
54
|
+
@site_tree.render
|
55
|
+
end
|
56
|
+
|
57
|
+
def write
|
58
|
+
notice "Creating site files dir at #{@site_files_dir}"
|
59
|
+
Dir.mkdir(@site_files_dir)
|
60
|
+
@site_tree.write
|
61
|
+
|
62
|
+
site_assets_dir = File.join(@site_files_dir, 'dropsite-assets')
|
63
|
+
Dir.mkdir(site_assets_dir)
|
64
|
+
DirRenderer.renderers.each do |r|
|
65
|
+
if File.exist? r.assets_dir
|
66
|
+
FileUtils.cp_r(r.assets_dir, File.join(site_assets_dir, Dropsite.underscorize(r.class.to_s)))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def notice(message)
|
72
|
+
return if @quiet
|
73
|
+
warn "#{File.basename($0)}: #{message}"
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
|
78
|
+
def read_directory(dir='')
|
79
|
+
base = File.join(@public_dir, dir)
|
80
|
+
entries = filter_entries(Dir.entries(base))
|
81
|
+
|
82
|
+
dir_entries = []
|
83
|
+
|
84
|
+
entries.each do |f|
|
85
|
+
f_abs = File.join(base, f)
|
86
|
+
f_rel = File.join(dir, f).sub(/^\//, '')
|
87
|
+
if File.directory?(f_abs)
|
88
|
+
dir_entries << read_directory(f_rel)
|
89
|
+
elsif !File.symlink?(f_abs)
|
90
|
+
# Ignore a top level Icon file, used for a custom directory icon on OS X
|
91
|
+
# TODO: find out how to do this specifically for the Icon file... there is a
|
92
|
+
# weird character at the end of the folder icon file name
|
93
|
+
next if RUBY_PLATFORM =~ /darwin/ && f_rel =~ /^Icon/ && f_rel.size == 5 && dir == ''
|
94
|
+
dir_entries << SiteFile.new(f_rel, f_abs, self)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
SiteDir.new(dir, dir_entries, self)
|
98
|
+
end
|
99
|
+
|
100
|
+
def filter_entries(entries)
|
101
|
+
entries.reject do |e|
|
102
|
+
['.', '_', '#'].include?(e[0..0]) || e[-1..-1] == '~' || @excludes.include?(e)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Dropsite
|
2
|
+
class SiteDir < SiteItem
|
3
|
+
attr_accessor :entries
|
4
|
+
|
5
|
+
def initialize(path, entries, site)
|
6
|
+
@path = path == '/' ? '' : path
|
7
|
+
@entries = entries
|
8
|
+
@site = site
|
9
|
+
@content = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def render
|
13
|
+
@content = Dropsite::DirRenderer.find_renderer_and_render(self)
|
14
|
+
dirs.each {|dir| dir.render}
|
15
|
+
end
|
16
|
+
|
17
|
+
def write
|
18
|
+
if root?
|
19
|
+
# The root site directory was created in Site
|
20
|
+
index_file = File.join(@site.public_dir, 'index.html')
|
21
|
+
notice "Writing top level index file at #{index_file}"
|
22
|
+
File.open(index_file, 'w') {|f| f.puts @content}
|
23
|
+
else
|
24
|
+
# Sub-directories all need to be created here
|
25
|
+
pieces = @path.sub(/^\//, '').split('/')
|
26
|
+
dir_name = File.join(@site.public_dir, 'dropsite', *pieces)
|
27
|
+
index_file = dir_name + '.html'
|
28
|
+
notice "Writing index file at #{index_file}"
|
29
|
+
File.open(index_file, 'w') {|f| f.puts @content}
|
30
|
+
Dir.mkdir(dir_name)
|
31
|
+
end
|
32
|
+
dirs.sort.each{|dir| dir.write}
|
33
|
+
end
|
34
|
+
|
35
|
+
def files
|
36
|
+
@entries.find_all {|e| e.is_a? SiteFile}
|
37
|
+
end
|
38
|
+
|
39
|
+
def dirs
|
40
|
+
@entries.find_all {|e| e.is_a? SiteDir}
|
41
|
+
end
|
42
|
+
|
43
|
+
def root?
|
44
|
+
@path == ''
|
45
|
+
end
|
46
|
+
|
47
|
+
def file_type
|
48
|
+
'directory'
|
49
|
+
end
|
50
|
+
|
51
|
+
def size
|
52
|
+
''
|
53
|
+
end
|
54
|
+
|
55
|
+
def to_s
|
56
|
+
"SiteDir(#{is_root? ? 'root' : @path})"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Dropsite
|
2
|
+
class SiteFile < SiteItem
|
3
|
+
EXTENSIONS = {
|
4
|
+
'image' => %w[jpg jpeg gif png],
|
5
|
+
'text' => %w[txt],
|
6
|
+
'pdf' => %w[pdf]
|
7
|
+
}
|
8
|
+
|
9
|
+
attr_accessor :size_in_bytes
|
10
|
+
|
11
|
+
def initialize(rel_path, abs_path=nil, site=nil)
|
12
|
+
@path = rel_path
|
13
|
+
@size_in_bytes = File.size(abs_path) if abs_path
|
14
|
+
@site = site
|
15
|
+
end
|
16
|
+
|
17
|
+
def file_type
|
18
|
+
if File.extname(name).empty?
|
19
|
+
'unknown'
|
20
|
+
else
|
21
|
+
ext = File.extname(name).sub(/^\./, '')
|
22
|
+
EXTENSIONS.each {|k, v| return k if v.include? ext}
|
23
|
+
return 'unknown'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Human readable file size
|
28
|
+
def size
|
29
|
+
return '' if !@size_in_bytes
|
30
|
+
return '0 B' if @size_in_bytes == 0
|
31
|
+
units = %w{B KB MB GB TB}
|
32
|
+
e = (Math.log(@size_in_bytes)/Math.log(1024)).floor
|
33
|
+
s = "%.1f" % (@size_in_bytes.to_f / 1024 ** e)
|
34
|
+
s.sub(/\.?0*$/, " #{units[e]}")
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_s
|
38
|
+
"SiteFile(#{@path})"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Dropsite
|
2
|
+
class SiteItem
|
3
|
+
include Enumerable, RenderHelper
|
4
|
+
|
5
|
+
attr_accessor :path
|
6
|
+
|
7
|
+
def name
|
8
|
+
File.basename @path
|
9
|
+
end
|
10
|
+
|
11
|
+
def top_level?
|
12
|
+
@path.sub(/^\//, '') == name
|
13
|
+
end
|
14
|
+
|
15
|
+
def <=>(other)
|
16
|
+
name <=> other.name
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def notice(message)
|
22
|
+
@site.notice(message) if @site
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/dropsite.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module Dropsite
|
3
|
+
|
4
|
+
# Attempts to find the Dropbox directory (not the Public directory, the Dropbox base
|
5
|
+
# directory) on this box. Returns nil if an existing directory could not be found.
|
6
|
+
def find_dropbox_dir
|
7
|
+
return ENV['DROPBOX_HOME'] if ENV['DROPBOX_HOME']
|
8
|
+
|
9
|
+
path = case RUBY_PLATFORM
|
10
|
+
when /darwin/, /linux/, /freebsd/
|
11
|
+
File.join(ENV['HOME'], 'Dropbox')
|
12
|
+
when /win32/, /mingw/
|
13
|
+
File.join(ENV['USERPROFILE'], 'My Documents', 'My Dropbox')
|
14
|
+
end
|
15
|
+
|
16
|
+
File.exist?(path) ? path : nil
|
17
|
+
end
|
18
|
+
|
19
|
+
# Convert a camel-cased string into a lowercase, underscore separated string
|
20
|
+
def underscorize(camel_cased_word)
|
21
|
+
camel_cased_word.to_s.gsub(/::/, '/').
|
22
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
23
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
24
|
+
tr("-", "_").downcase
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
%w[dir_renderer render_helper plugins site site_item site_dir site_file].each do |lib|
|
29
|
+
require File.join('dropsite', lib)
|
30
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
here is some content
|
@@ -0,0 +1 @@
|
|
1
|
+
here is some content
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/test/helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'redgreen' unless ENV['TM_MODE']
|
6
|
+
rescue LoadError
|
7
|
+
end
|
8
|
+
|
9
|
+
FILE_DIR = File.dirname(__FILE__)
|
10
|
+
|
11
|
+
require File.join(FILE_DIR, *%w[.. lib dropsite])
|
12
|
+
include Dropsite
|
13
|
+
|
14
|
+
FIXTURES_DIR = File.join(FILE_DIR, 'fixtures')
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
require 'nokogiri'
|
3
|
+
|
4
|
+
# Tests for RenderHelper mixin using SiteItem, which mixes it in
|
5
|
+
class TestRenderHelper < Test::Unit::TestCase
|
6
|
+
def test_back_link
|
7
|
+
assert_equal '../index.html', SiteDir.new('pics', [], '/tmp').back_link(1)
|
8
|
+
assert_equal '../index.html', SiteDir.new('pics', [], '/tmp').back_link
|
9
|
+
assert_equal '../pics.html', SiteDir.new('pics/people', [], '/tmp').back_link(1)
|
10
|
+
assert_equal '../../index.html', SiteDir.new('pics/people', [], '/tmp').back_link(2)
|
11
|
+
assert_equal '../people.html', SiteDir.new('pics/people/friends', [], '/tmp').back_link(1)
|
12
|
+
assert_equal '../../pics.html', SiteDir.new('pics/people/friends', [], '/tmp').back_link(2)
|
13
|
+
assert_equal '../../../index.html', SiteDir.new('pics/people/friends', [], '/tmp').back_link(3)
|
14
|
+
|
15
|
+
# Test too many levels up and non-Integer arg
|
16
|
+
assert_equal '../index.html', SiteDir.new('pics', [], '/tmp').back_link(2)
|
17
|
+
assert_equal '../index.html', SiteDir.new('pics', [], '/tmp').back_link(3)
|
18
|
+
assert_equal '../index.html', SiteDir.new('pics', [], '/tmp').back_link(nil)
|
19
|
+
assert_equal '', SiteDir.new('', [], '/tmp').back_link(1)
|
20
|
+
assert_equal '', SiteDir.new('', [], '/tmp').back_link(nil)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_parent_directory_link_tag
|
24
|
+
sd = SiteDir.new('pics/people/friends', [], '/tmp')
|
25
|
+
|
26
|
+
basic_link_doc = Nokogiri::HTML(sd.parent_directory_link_tag(1))
|
27
|
+
links = basic_link_doc.css('a')
|
28
|
+
assert_equal 1, links.size
|
29
|
+
assert_equal '../people.html', links[0].attribute('href').value
|
30
|
+
assert_equal 'people', links[0].content
|
31
|
+
|
32
|
+
basic_link_doc = Nokogiri::HTML(sd.parent_directory_link_tag(2))
|
33
|
+
links = basic_link_doc.css('a')
|
34
|
+
assert_equal 1, links.size
|
35
|
+
assert_equal '../../pics.html', links[0].attribute('href').value
|
36
|
+
assert_equal 'pics', links[0].content
|
37
|
+
|
38
|
+
basic_link_doc = Nokogiri::HTML(sd.parent_directory_link_tag(3))
|
39
|
+
links = basic_link_doc.css('a')
|
40
|
+
assert_equal 1, links.size
|
41
|
+
assert_equal '../../../index.html', links[0].attribute('href').value
|
42
|
+
assert_equal 'my files', links[0].content
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_parent_directory_link_tag_with_additional_attributes
|
46
|
+
sd = SiteDir.new('pics/people/friends', [], '/tmp')
|
47
|
+
id = 'the-id'
|
48
|
+
css_class = 'the-css-class'
|
49
|
+
|
50
|
+
link_doc = Nokogiri::HTML(sd.parent_directory_link_tag(1, :class => css_class))
|
51
|
+
links = link_doc.css('a')
|
52
|
+
assert_equal 1, links.size
|
53
|
+
link = links[0]
|
54
|
+
assert_equal '../people.html', link.attribute('href').value
|
55
|
+
assert_equal 'people', link.content
|
56
|
+
assert_equal css_class, link.attribute('class').value
|
57
|
+
|
58
|
+
link_doc = Nokogiri::HTML(sd.parent_directory_link_tag(1, :id => id, :class => css_class))
|
59
|
+
links = link_doc.css('a')
|
60
|
+
assert_equal 1, links.size
|
61
|
+
link = links[0]
|
62
|
+
assert_equal '../people.html', link.attribute('href').value
|
63
|
+
assert_equal 'people', link.content
|
64
|
+
assert_equal id, link.attribute('id').value
|
65
|
+
assert_equal css_class, link.attribute('class').value
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_each_parent_directory_link_tag_with_root
|
69
|
+
links = ''
|
70
|
+
sd = SiteDir.new('pics/people/friends', [], '/tmp')
|
71
|
+
sd.each_parent_directory_link_tag {|link| links << link}
|
72
|
+
links_doc = Nokogiri::HTML(links)
|
73
|
+
links = links_doc.css('a')
|
74
|
+
assert_equal 3, links.size
|
75
|
+
|
76
|
+
root_link = links_doc.css('a').find {|a| a.content == 'my files'}
|
77
|
+
assert_equal '../../../index.html', root_link.attribute('href').value
|
78
|
+
pics_link = links_doc.css('a').find {|a| a.content == 'pics'}
|
79
|
+
assert_equal '../../pics.html', pics_link.attribute('href').value
|
80
|
+
people_link = links_doc.css('a').find {|a| a.content == 'people'}
|
81
|
+
assert_equal '../people.html', people_link.attribute('href').value
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_each_parent_directory_link_tag_without_root
|
85
|
+
links = ''
|
86
|
+
sd = SiteDir.new('pics/people/friends', [], '/tmp')
|
87
|
+
sd.each_parent_directory_link_tag(false) {|link| links << link}
|
88
|
+
links_doc = Nokogiri::HTML(links)
|
89
|
+
links = links_doc.css('a')
|
90
|
+
assert_equal 2, links.size
|
91
|
+
|
92
|
+
pics_link = links_doc.css('a').find {|a| a.content == 'pics'}
|
93
|
+
assert_equal '../../pics.html', pics_link.attribute('href').value
|
94
|
+
people_link = links_doc.css('a').find {|a| a.content == 'people'}
|
95
|
+
assert_equal '../people.html', people_link.attribute('href').value
|
96
|
+
end
|
97
|
+
end
|
data/test/test_site.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
|
3
|
+
class TestSite < Test::Unit::TestCase
|
4
|
+
def test_create_site_tree_from_simple_public_dir
|
5
|
+
site = Site.new(File.join(FIXTURES_DIR, 'simple_public'))
|
6
|
+
root = site.read
|
7
|
+
|
8
|
+
assert root.is_a? SiteDir
|
9
|
+
assert_equal '', root.path
|
10
|
+
assert_equal 2, root.files.size
|
11
|
+
assert root.files.find {|f| f.name == 'file1.txt'}
|
12
|
+
assert root.files.find {|f| f.name == 'file2.txt'}
|
13
|
+
assert_equal 1, root.dirs.size
|
14
|
+
|
15
|
+
pics_dir = root.dirs[0]
|
16
|
+
assert_equal 'pics', pics_dir.path
|
17
|
+
assert_equal 2, pics_dir.files.size
|
18
|
+
|
19
|
+
assert pics_dir.files.find {|f| f.name == 'leaves.jpg'}
|
20
|
+
assert pics_dir.files.find {|f| f.name == 'sculpture.jpg'}
|
21
|
+
assert_equal 1, pics_dir.dirs.size
|
22
|
+
|
23
|
+
people_dir = pics_dir.dirs[0]
|
24
|
+
assert_equal 2, people_dir.files.size
|
25
|
+
assert people_dir.files.find {|f| f.name == 'concert.jpg'}
|
26
|
+
assert people_dir.files.find {|f| f.name == 'beach.jpg'}
|
27
|
+
assert people_dir.dirs.empty?
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_create_site_tree_from_simple_public_dir_with_exclusions
|
31
|
+
site = Site.new(
|
32
|
+
:public_dir => File.join(FIXTURES_DIR, 'simple_public'),
|
33
|
+
:excludes => ['pics', 'file1.txt']
|
34
|
+
)
|
35
|
+
root = site.read
|
36
|
+
|
37
|
+
assert_equal 1, root.files.size
|
38
|
+
assert root.files.find {|f| f.name == 'file2.txt'}
|
39
|
+
assert root.dirs.empty?
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
|
3
|
+
class TestSiteDir < Test::Unit::TestCase
|
4
|
+
def test_name
|
5
|
+
assert_equal 'pic1.jpg', SiteDir.new('pic1.jpg', [], '/tmp').name
|
6
|
+
assert_equal 'pic1.jpg', SiteDir.new('/pics/pic1.jpg', [], '/tmp').name
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_root_name
|
10
|
+
assert_equal '', SiteDir.new('/', [], '/tmp').name
|
11
|
+
assert_equal '', SiteDir.new('', [], '/tmp').name
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_is_root
|
15
|
+
assert SiteDir.new('', [], '/tmp').root?
|
16
|
+
assert !SiteDir.new('/file.txt', [], '/tmp').root?
|
17
|
+
assert !SiteDir.new('/dir', [], '/tmp').root?
|
18
|
+
assert !SiteDir.new('/dir/file.txt', [], '/tmp').root?
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
|
3
|
+
class TestSiteFile < Test::Unit::TestCase
|
4
|
+
def test_name
|
5
|
+
assert_equal 'pic1.jpg', SiteFile.new('pic1.jpg').name
|
6
|
+
assert_equal 'pic1.jpg', SiteFile.new('/pics/pic1.jpg').name
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_type
|
10
|
+
assert_equal 'image', SiteFile.new('/pics/pic1.jpg').file_type
|
11
|
+
assert_equal 'image', SiteFile.new('/pics/pic1.gif').file_type
|
12
|
+
assert_equal 'text', SiteFile.new('/pics/pic1.txt').file_type
|
13
|
+
assert_equal 'unknown', SiteFile.new('/pics/plainoldfile').file_type
|
14
|
+
assert_equal 'unknown', SiteFile.new('/pics/file.asdf').file_type
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_top_level
|
18
|
+
assert SiteFile.new('/pic1.jpg').top_level?
|
19
|
+
assert !SiteFile.new('/pics/pic1.jpg').top_level?
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_size
|
23
|
+
sf = SiteFile.new('/pic1.jpg')
|
24
|
+
sf.size_in_bytes = 100
|
25
|
+
assert_equal '100 B', sf.size
|
26
|
+
sf.size_in_bytes = 1024
|
27
|
+
assert_equal '1 KB', sf.size
|
28
|
+
sf.size_in_bytes = 1536
|
29
|
+
assert_equal '1.5 KB', sf.size
|
30
|
+
sf.size_in_bytes = 1792
|
31
|
+
assert_equal '1.8 KB', sf.size # rounded
|
32
|
+
sf.size_in_bytes = 1048576
|
33
|
+
assert_equal '1 MB', sf.size
|
34
|
+
sf.size_in_bytes = 3879731
|
35
|
+
assert_equal '3.7 MB', sf.size
|
36
|
+
sf.size_in_bytes = 1073741824
|
37
|
+
assert_equal '1 GB', sf.size
|
38
|
+
sf.size_in_bytes = 1099511627776
|
39
|
+
assert_equal '1 TB', sf.size
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'helper')
|
2
|
+
require 'fileutils'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
class TestWriteSite < Test::Unit::TestCase
|
6
|
+
TMP_DIR = File.join(FIXTURES_DIR, 'tmp')
|
7
|
+
|
8
|
+
def setup
|
9
|
+
clean_tmp_dir
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
clean_tmp_dir
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_simple_process
|
17
|
+
FileUtils.cp_r(File.join(FIXTURES_DIR, 'simple_public'), File.join(TMP_DIR, 'simple_public'))
|
18
|
+
site = Site.new(:public_dir => File.join(TMP_DIR, 'simple_public'), :quiet => true)
|
19
|
+
site.process
|
20
|
+
|
21
|
+
# Check that all the index pages are there
|
22
|
+
|
23
|
+
index_file = File.join(site.public_dir, 'index.html')
|
24
|
+
assert File.exist?(index_file)
|
25
|
+
index_doc = Nokogiri::HTML(IO.read(index_file))
|
26
|
+
assert_equal 3, index_doc.css('.entry').size
|
27
|
+
|
28
|
+
assert_equal 'dropsite/pics.html', index_doc.css('a').find {|a| a.content == 'pics'}.attribute('href').value
|
29
|
+
|
30
|
+
site_dir = File.join(site.public_dir, 'dropsite')
|
31
|
+
assert File.exist?(site_dir)
|
32
|
+
assert File.directory?(site_dir)
|
33
|
+
|
34
|
+
pics_file = File.join(site_dir, 'pics.html')
|
35
|
+
assert File.exist?(pics_file)
|
36
|
+
pics_doc = Nokogiri::HTML(IO.read(pics_file))
|
37
|
+
assert_equal 3, pics_doc.css('.entry').size
|
38
|
+
|
39
|
+
# Make sure the the links are correct
|
40
|
+
|
41
|
+
['leaves.jpg', 'sculpture.jpg'].each do |pic|
|
42
|
+
assert_equal "../pics/#{pic}", pics_doc.css('a').find {|a| a.content == pic}.attribute('href').value
|
43
|
+
end
|
44
|
+
|
45
|
+
assert_equal 'pics/people.html', pics_doc.css('a').find {|a| a.content == 'people'}.attribute('href').value
|
46
|
+
|
47
|
+
people_file = File.join(site_dir, 'pics', 'people.html')
|
48
|
+
assert File.exist?(people_file)
|
49
|
+
people_doc = Nokogiri::HTML(IO.read(people_file))
|
50
|
+
assert_equal 2, people_doc.css('.entry').size
|
51
|
+
|
52
|
+
['beach.jpg', 'concert.jpg'].each do |pic|
|
53
|
+
assert_equal "../../pics/people/#{pic}", people_doc.css('a').find {|a| a.content == pic}.attribute('href').value
|
54
|
+
end
|
55
|
+
|
56
|
+
# Check that the assets were copied in
|
57
|
+
|
58
|
+
assets_dir = File.join(site.public_dir, 'dropsite', 'dropsite-assets')
|
59
|
+
assert File.exist?(assets_dir)
|
60
|
+
assert File.directory?(assets_dir)
|
61
|
+
simple_index_assets_dir = File.join(assets_dir, 'simple_index')
|
62
|
+
assert File.exist?(simple_index_assets_dir)
|
63
|
+
assert File.directory?(simple_index_assets_dir)
|
64
|
+
assert File.exist?(File.join(simple_index_assets_dir, 'css', 'simple_index.css'))
|
65
|
+
|
66
|
+
# Check that the assets are included correctly
|
67
|
+
|
68
|
+
assert_equal 1, index_doc.css('link').find_all {|l|
|
69
|
+
l.attribute('href').value == 'dropsite/dropsite-assets/simple_index/css/simple_index.css'
|
70
|
+
}.size
|
71
|
+
assert_equal 1, index_doc.css('script').find_all {|l|
|
72
|
+
l.attribute('src').value == 'dropsite/dropsite-assets/simple_index/js/simple_index.js'
|
73
|
+
}.size
|
74
|
+
|
75
|
+
assert_equal 1, pics_doc.css('link').find_all {|l|
|
76
|
+
l.attribute('href').value == 'dropsite-assets/simple_index/css/simple_index.css'
|
77
|
+
}.size
|
78
|
+
assert_equal 1, pics_doc.css('script').find_all {|l|
|
79
|
+
l.attribute('src').value == 'dropsite-assets/simple_index/js/simple_index.js'
|
80
|
+
}.size
|
81
|
+
|
82
|
+
assert_equal 1, people_doc.css('link').find_all {|l|
|
83
|
+
l.attribute('href').value == '../dropsite-assets/simple_index/css/simple_index.css'
|
84
|
+
}.size
|
85
|
+
assert_equal 1, people_doc.css('script').find_all {|l|
|
86
|
+
l.attribute('src').value == '../dropsite-assets/simple_index/js/simple_index.js'
|
87
|
+
}.size
|
88
|
+
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
def clean_tmp_dir
|
93
|
+
Dir.entries(TMP_DIR).reject {|e| e =~ /^\./}.each do |entry|
|
94
|
+
file = File.join(TMP_DIR, entry)
|
95
|
+
if File.directory?(file)
|
96
|
+
FileUtils.rm_rf(file)
|
97
|
+
else
|
98
|
+
File.delete(file)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dropsite
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: "0.2"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Aaron Royer
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-11 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: creates index pages in your Dropbox public directory
|
22
|
+
email: aaronroyer@gmail.com
|
23
|
+
executables:
|
24
|
+
- dropsite
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- bin/dropsite
|
31
|
+
- lib/dropsite/dir_renderer.rb
|
32
|
+
- lib/dropsite/plugins/simple_index/assets/css/reset.css
|
33
|
+
- lib/dropsite/plugins/simple_index/assets/css/simple_index.css
|
34
|
+
- lib/dropsite/plugins/simple_index/assets/images/icons/directory.png
|
35
|
+
- lib/dropsite/plugins/simple_index/assets/images/icons/image.png
|
36
|
+
- lib/dropsite/plugins/simple_index/assets/images/icons/pdf.png
|
37
|
+
- lib/dropsite/plugins/simple_index/assets/images/icons/script.png
|
38
|
+
- lib/dropsite/plugins/simple_index/assets/images/icons/text.png
|
39
|
+
- lib/dropsite/plugins/simple_index/assets/images/icons/unknown.png
|
40
|
+
- lib/dropsite/plugins/simple_index/assets/images/row-bg.png
|
41
|
+
- lib/dropsite/plugins/simple_index/assets/simple_index.js
|
42
|
+
- lib/dropsite/plugins/simple_index/simple_index.erb
|
43
|
+
- lib/dropsite/plugins/simple_index/simple_index.rb
|
44
|
+
- lib/dropsite/plugins.rb
|
45
|
+
- lib/dropsite/render_helper.rb
|
46
|
+
- lib/dropsite/site.rb
|
47
|
+
- lib/dropsite/site_dir.rb
|
48
|
+
- lib/dropsite/site_file.rb
|
49
|
+
- lib/dropsite/site_item.rb
|
50
|
+
- lib/dropsite.rb
|
51
|
+
- test/fixtures/simple_public/file1.txt
|
52
|
+
- test/fixtures/simple_public/file2.txt
|
53
|
+
- test/fixtures/simple_public/pics/leaves.jpg
|
54
|
+
- test/fixtures/simple_public/pics/people/beach.jpg
|
55
|
+
- test/fixtures/simple_public/pics/people/concert.jpg
|
56
|
+
- test/fixtures/simple_public/pics/sculpture.jpg
|
57
|
+
- test/helper.rb
|
58
|
+
- test/test_render_helper.rb
|
59
|
+
- test/test_site.rb
|
60
|
+
- test/test_site_dir.rb
|
61
|
+
- test/test_site_file.rb
|
62
|
+
- test/test_write_site.rb
|
63
|
+
- README
|
64
|
+
- LICENSE
|
65
|
+
- dropsite.gemspec
|
66
|
+
- Rakefile
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: https://rubygems.org/gems/dropsite
|
69
|
+
licenses: []
|
70
|
+
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options:
|
73
|
+
- --line-numbers
|
74
|
+
- --inline-source
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 3
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
required_rubygems_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
|
+
requirements: []
|
96
|
+
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.3.7
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: "Dropsite creates a site of interlinked file index pages in the Public directory of your Dropbox. The site created is minimally invasive to your Public directory by only creating one top-level HTML page and one folder, leaving your directories unjunked. BE WARNED: while I _think_ this probably works fine, it is presently considered experimental."
|
102
|
+
test_files:
|
103
|
+
- test/test_render_helper.rb
|
104
|
+
- test/test_site.rb
|
105
|
+
- test/test_site_dir.rb
|
106
|
+
- test/test_site_file.rb
|
107
|
+
- test/test_write_site.rb
|