dropsite 0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/LICENSE +21 -0
  2. data/README +25 -0
  3. data/Rakefile +33 -0
  4. data/bin/dropsite +38 -0
  5. data/dropsite.gemspec +28 -0
  6. data/lib/dropsite/dir_renderer.rb +56 -0
  7. data/lib/dropsite/plugins/simple_index/assets/css/reset.css +30 -0
  8. data/lib/dropsite/plugins/simple_index/assets/css/simple_index.css +98 -0
  9. data/lib/dropsite/plugins/simple_index/assets/images/icons/directory.png +0 -0
  10. data/lib/dropsite/plugins/simple_index/assets/images/icons/image.png +0 -0
  11. data/lib/dropsite/plugins/simple_index/assets/images/icons/pdf.png +0 -0
  12. data/lib/dropsite/plugins/simple_index/assets/images/icons/script.png +0 -0
  13. data/lib/dropsite/plugins/simple_index/assets/images/icons/text.png +0 -0
  14. data/lib/dropsite/plugins/simple_index/assets/images/icons/unknown.png +0 -0
  15. data/lib/dropsite/plugins/simple_index/assets/images/row-bg.png +0 -0
  16. data/lib/dropsite/plugins/simple_index/assets/simple_index.js +3 -0
  17. data/lib/dropsite/plugins/simple_index/simple_index.erb +37 -0
  18. data/lib/dropsite/plugins/simple_index/simple_index.rb +5 -0
  19. data/lib/dropsite/plugins.rb +5 -0
  20. data/lib/dropsite/render_helper.rb +97 -0
  21. data/lib/dropsite/site.rb +106 -0
  22. data/lib/dropsite/site_dir.rb +59 -0
  23. data/lib/dropsite/site_file.rb +41 -0
  24. data/lib/dropsite/site_item.rb +25 -0
  25. data/lib/dropsite.rb +30 -0
  26. data/test/fixtures/simple_public/file1.txt +1 -0
  27. data/test/fixtures/simple_public/file2.txt +1 -0
  28. data/test/fixtures/simple_public/pics/leaves.jpg +0 -0
  29. data/test/fixtures/simple_public/pics/people/beach.jpg +0 -0
  30. data/test/fixtures/simple_public/pics/people/concert.jpg +0 -0
  31. data/test/fixtures/simple_public/pics/sculpture.jpg +0 -0
  32. data/test/helper.rb +14 -0
  33. data/test/test_render_helper.rb +97 -0
  34. data/test/test_site.rb +41 -0
  35. data/test/test_site_dir.rb +20 -0
  36. data/test/test_site_file.rb +41 -0
  37. data/test/test_write_site.rb +102 -0
  38. 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
+ }
@@ -0,0 +1,3 @@
1
+ if (console && console.log) {
2
+ console.log("included...");
3
+ }
@@ -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>&nbsp;</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,5 @@
1
+ class SimpleIndex < Dropsite::DirRenderer
2
+ def is_default?
3
+ true
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ PLUGINS_DIR = File.join(File.dirname(__FILE__), 'plugins')
2
+
3
+ Dir.entries(PLUGINS_DIR).reject {|e| e =~ /^\./}.each do |e|
4
+ require File.join(PLUGINS_DIR, e, e)
5
+ end
@@ -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
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