dropsite 0.2

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.
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