├── .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(/<, '<<') 62 | end 63 | 64 | def copy_images 65 | imgs = File.join @odir, 'images' 66 | FileUtils.mkdir_p imgs 67 | 68 | FileUtils.cp File.join(IMAGE_DIR, 'ruby.png'), imgs 69 | end 70 | 71 | def emit_meta_inf 72 | meta_inf = File.join @odir, 'META-INF' 73 | FileUtils.mkdir_p meta_inf 74 | 75 | FileUtils.cp File.join(TEMPLATE_DIR, 'container.xml'), meta_inf 76 | end 77 | 78 | def emit_mimetype 79 | File.open(File.join(@odir, 'mimetype'), 'wb') do |f| 80 | f.write 'application/epub+zip' 81 | end 82 | end 83 | 84 | def emit_cover 85 | template = ERB.new File.read(File.join(TEMPLATE_DIR, 'cover.html.erb')), 86 | nil, '<>' 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 |