├── .autotest ├── CHANGELOG.rdoc ├── Manifest.txt ├── README.rdoc ├── Rakefile ├── lib ├── images │ └── ruby.png ├── paddle.rb ├── rdoc │ ├── discover.rb │ └── generator │ │ └── paddle.rb └── templates │ ├── classfile.html.erb │ ├── container.xml │ ├── content.opf.erb │ ├── cover.html.erb │ ├── title.html.erb │ └── toc.ncx.erb └── test └── test_paddle.rb /.autotest: -------------------------------------------------------------------------------- 1 | # -*- ruby -*- 2 | 3 | require 'autotest/restart' 4 | 5 | # Autotest.add_hook :initialize do |at| 6 | # at.extra_files << "../some/external/dependency.rb" 7 | # 8 | # at.libs << ":../some/external" 9 | # 10 | # at.add_exception 'vendor' 11 | # 12 | # at.add_mapping(/dependency.rb/) do |f, _| 13 | # at.files_matching(/test_.*rb$/) 14 | # end 15 | # 16 | # %w(TestA TestB).each do |klass| 17 | # at.extra_class_map[klass] = "test/test_misc.rb" 18 | # end 19 | # end 20 | 21 | # Autotest.add_hook :run_command do |at| 22 | # system "rake build" 23 | # end 24 | -------------------------------------------------------------------------------- /CHANGELOG.rdoc: -------------------------------------------------------------------------------- 1 | === 1.0.0 / 2010-04-11 2 | 3 | * 1 major enhancement 4 | 5 | * Birthday! 6 | 7 | -------------------------------------------------------------------------------- /Manifest.txt: -------------------------------------------------------------------------------- 1 | .autotest 2 | CHANGELOG.rdoc 3 | Manifest.txt 4 | README.rdoc 5 | Rakefile 6 | lib/images/ruby.png 7 | lib/paddle.rb 8 | lib/rdoc/discover.rb 9 | lib/rdoc/generator/paddle.rb 10 | lib/templates/classfile.html.erb 11 | lib/templates/container.xml 12 | lib/templates/content.opf.erb 13 | lib/templates/cover.html.erb 14 | lib/templates/title.html.erb 15 | lib/templates/toc.ncx.erb 16 | test/test_paddle.rb 17 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | = paddle 2 | 3 | * http://tenderlovemaking.com 4 | 5 | == DESCRIPTION: 6 | 7 | Paddle is an RDoc plugin that emits documentation suitable for use as an epub 8 | book. The epub book can then be imported to iBooks for reading on iPad! 9 | 10 | == FEATURES/PROBLEMS: 11 | 12 | * Converts RDoc to epub format 13 | * Sometimes it doesn't escape everything properly 14 | * Links aren't working yet 15 | * The tests are poor. *Very* poor. 16 | 17 | == SYNOPSIS: 18 | 19 | First, make sure to have the latest RDoc. Install paddle, then rdoc your code 20 | like this: 21 | 22 | $ rdoc -o epub -f paddle -t 'My Documentation' lib 23 | 24 | Next, convert the documentation to an epub file: 25 | 26 | $ cd epub 27 | $ zip -Xr9D mydocs.epub mimetype * 28 | 29 | Then drag "mydocs.epub" to iTunes, and sync up your iPad. 30 | 31 | == REQUIREMENTS: 32 | 33 | * RDoc 34 | 35 | == INSTALL: 36 | 37 | * sudo gem install rdoc 38 | 39 | == LICENSE: 40 | 41 | (The MIT License) 42 | 43 | Copyright (c) 2010 Aaron Patterson 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining 46 | a copy of this software and associated documentation files (the 47 | 'Software'), to deal in the Software without restriction, including 48 | without limitation the rights to use, copy, modify, merge, publish, 49 | distribute, sublicense, and/or sell copies of the Software, and to 50 | permit persons to whom the Software is furnished to do so, subject to 51 | the following conditions: 52 | 53 | The above copyright notice and this permission notice shall be 54 | included in all copies or substantial portions of the Software. 55 | 56 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 57 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 58 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 59 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 60 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 61 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 62 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 63 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # -*- ruby -*- 2 | 3 | require 'rubygems' 4 | require 'hoe' 5 | 6 | Hoe.spec 'paddle' do 7 | developer('Aaron Patterson', 'aaron@tenderlovemaking.com') 8 | self.readme_file = 'README.rdoc' 9 | self.history_file = 'CHANGELOG.rdoc' 10 | self.extra_rdoc_files = FileList['*.rdoc'] 11 | self.extra_deps << ['rdoc', '>= 2.5.3'] 12 | end 13 | 14 | # vim: syntax=ruby 15 | -------------------------------------------------------------------------------- /lib/images/ruby.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tenderlove/paddle/3dd1c8cd95fd991a91bec4457bc78eaf6d5e9c77/lib/images/ruby.png -------------------------------------------------------------------------------- /lib/paddle.rb: -------------------------------------------------------------------------------- 1 | ### 2 | # Paddle is an RDoc template that will emit iPad compatible books! 3 | module Paddle 4 | # Test Attribute 5 | attr_accessor :foo 6 | 7 | VERSION = '1.0.0' 8 | end 9 | -------------------------------------------------------------------------------- /lib/rdoc/discover.rb: -------------------------------------------------------------------------------- 1 | require 'rdoc/generator/paddle' 2 | -------------------------------------------------------------------------------- /lib/rdoc/generator/paddle.rb: -------------------------------------------------------------------------------- 1 | require 'rdoc/generator' 2 | require 'rdoc/rdoc' 3 | require 'paddle' 4 | require 'erb' 5 | require 'md5' 6 | require 'fileutils' 7 | 8 | class RDoc::Generator::Paddle 9 | RDoc::RDoc.add_generator self 10 | 11 | TEMPLATE_DIR = File.expand_path( 12 | File.join(File.dirname(__FILE__), '..', '..', 'templates')) 13 | IMAGE_DIR = File.expand_path( 14 | File.join(File.dirname(__FILE__), '..', '..', 'images')) 15 | 16 | class << self 17 | alias :for :new 18 | end 19 | 20 | def initialize options 21 | @options = options 22 | @class_dir = nil 23 | @file_dir = nil 24 | @odir = Pathname.new(options.op_dir).expand_path(Pathname.pwd) 25 | @fh = nil 26 | @files = nil 27 | end 28 | 29 | def generate top_levels 30 | @files = top_levels 31 | @classes = RDoc::TopLevel.all_classes_and_modules.reject { |x| 32 | x.name =~ /[<>]/ 33 | } 34 | 35 | FileUtils.mkdir_p(File.join(@odir, class_dir)) 36 | 37 | emit_mimetype 38 | emit_meta_inf 39 | emit_cover 40 | emit_title 41 | emit_opf 42 | emit_toc 43 | emit_classfiles 44 | copy_images 45 | end 46 | 47 | def class_dir 48 | '/doc' 49 | end 50 | 51 | def title 52 | @options.title 53 | end 54 | 55 | def identifier 56 | MD5.hexdigest title 57 | end 58 | 59 | private 60 | def h string 61 | string.strip.gsub(/
\s*<\/pre>/, '').gsub(/&/, '&').gsub(/<'
 87 | 
 88 |     File.open(File.join(@odir, class_dir, 'cover.html'), 'wb') do |f|
 89 |       f.write template.result binding
 90 |     end
 91 |   end
 92 | 
 93 |   def emit_title
 94 |     template = ERB.new File.read(File.join(TEMPLATE_DIR, 'title.html.erb')),
 95 |       nil, '<>'
 96 | 
 97 |     File.open(File.join(@odir, class_dir, 'title.html'), 'wb') do |f|
 98 |       f.write template.result binding
 99 |     end
100 |   end
101 | 
102 |   def emit_classfiles
103 |     @classes.each do |klass|
104 |       klass_methods    = []
105 |       instance_methods = []
106 | 
107 |       klass.method_list.each do |method|
108 |         next if 'private' == method.visibility.to_s
109 |         if method.type == 'class'
110 |           klass_methods << method
111 |         else
112 |           instance_methods << method
113 |         end
114 |       end
115 | 
116 |       template = ERB.new File.read(File.join(TEMPLATE_DIR, 'classfile.html.erb')),
117 |         nil, '<>'
118 | 
119 |       FileUtils.mkdir_p(File.dirname(File.join(@odir, klass.path)))
120 | 
121 |       File.open(File.join(@odir, klass.path), 'wb') do |f|
122 |         f.write template.result binding
123 |       end
124 |     end
125 |   end
126 | 
127 |   def emit_opf
128 |     template = ERB.new File.read(File.join(TEMPLATE_DIR, 'content.opf.erb')),
129 |       nil, '<>'
130 | 
131 |     File.open(File.join(@odir, 'content.opf'), 'wb') do |f|
132 |       f.write template.result binding
133 |     end
134 |   end
135 | 
136 |   def emit_toc
137 |     template = ERB.new File.read(File.join(TEMPLATE_DIR, 'toc.ncx.erb')),
138 |       nil, '<>'
139 | 
140 |     File.open(File.join(@odir, 'toc.ncx'), 'wb') do |f|
141 |       f.write template.result binding
142 |     end
143 |   end
144 | end
145 | 


--------------------------------------------------------------------------------
/lib/templates/classfile.html.erb:
--------------------------------------------------------------------------------
  1 | 
  2 | 
  3 |   
  4 |     
  5 |     
  6 |       <%= klass.name %>
  7 |     
  8 |     
 24 |   
 25 |   
 26 |     

27 | <% if klass.type == 'class' %> 28 | 29 | <%= klass.type.capitalize %> 30 | 31 | <%= klass.full_name %> 32 | 33 | <% if klass.superclass %> 34 | inherits from 35 | <% end %> 36 | <% unless String === klass.superclass %> 37 | 38 | <%= klass.superclass.name %> 39 | 40 | <% else %> 41 | <%= klass.superclass %> 42 | <% end %> 43 | 44 | <% else %> 45 | 46 | <%= klass.type.capitalize %> 47 | 48 | <%= klass.name %> 49 | 50 | 51 | <% end %> 52 |

53 | <% if klass.description && !klass.description.empty? %> 54 |
55 | <%= h klass.description %> 56 |
57 | <% end %> 58 | 59 | 60 | <% unless klass.constants.empty? %> 61 |

Constants

62 | <% klass.constants.sort_by { |x| x.name }.each do |const| %> 63 |
64 |
65 | <%= h const.name %> 66 |
67 |
<%= h const.description %>
68 |
69 | <% end %> 70 | <% end %> 71 | 72 | 73 | <% unless klass.attributes.empty? %> 74 |

Attributes

75 | <% klass.attributes.sort_by { |x| x.name }.each do |attr| %> 76 |
77 |
78 | <%= h attr.name %> 79 | <%= attr.rw %> 80 |
81 |
<%= h attr.description %>
82 |
83 | <% end %> 84 | <% end %> 85 | 86 | 87 | <% unless klass_methods.empty? %> 88 |

Public Class Methods

89 | <% klass_methods.each do |method| %> 90 |
91 |
92 | 93 | <%= h method.name %><%= h method.params %> 94 |
95 |
<%= h method.description %>
96 |
97 | <% end %> 98 | <% end %> 99 | 100 | 101 | <% unless instance_methods.empty? %> 102 |

Public Instance Methods

103 | <% instance_methods.each do |method| %> 104 |
105 |
106 | 107 | <%= h method.name %><%= h method.params %> 108 |
109 |
<%= h method.description %>
110 |
111 | <% end %> 112 | <% end %> 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /lib/templates/container.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/templates/content.opf.erb: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | <%= title %> 10 | en 11 | 12 | <%= identifier %> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | <% @classes.each do |klass| %> 21 | 22 | <% end %> 23 | 24 | 25 | 26 | 27 | <% @classes.sort_by { |x| x.full_name }.each do |klass| %> 28 | 29 | <% end %> 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /lib/templates/cover.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= title %> 7 | 8 | 13 | 14 | 15 |

<%= title %>

16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /lib/templates/title.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= title %> 7 | 8 | 13 | 14 | 15 |

<%= title %>

16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /lib/templates/toc.ncx.erb: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | <%= title %> 13 | 14 | 15 | 16 | 17 | Cover 18 | 19 | 20 | 21 | 22 | 23 | Title 24 | 25 | 26 | 27 | <% @classes.sort_by { |x| x.full_name }.each_with_index do |klass, i| %> 28 | 29 | 30 | <%= klass.full_name %> 31 | 32 | 33 | 34 | <% end %> 35 | 36 | 37 | -------------------------------------------------------------------------------- /test/test_paddle.rb: -------------------------------------------------------------------------------- 1 | require "test/unit" 2 | require 'rdoc/generator/paddle' 3 | require 'tempfile' 4 | require 'fileutils' 5 | 6 | class TestPaddle < Test::Unit::TestCase 7 | def setup 8 | @dirname = File.join(Dir.tmpdir, Time.now.to_i.to_s) 9 | p @dirname 10 | rdoc = RDoc::RDoc.new 11 | rdoc.document ['--op', @dirname, '-q', '-f', 'paddle'] 12 | end 13 | end 14 | --------------------------------------------------------------------------------