bookshelf 1.0.0

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.
@@ -0,0 +1,4 @@
1
+ .DS_Store
2
+ pkg
3
+ tmp
4
+ spec/support/mybook/output/mybook.*
@@ -0,0 +1,3 @@
1
+ [submodule "lib/bookshelf/vendor/colorize"]
2
+ path = lib/bookshelf/vendor/colorize
3
+ url = git://github.com/fnando/colorize.git
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
@@ -0,0 +1,66 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bookshelf (1.0.4)
5
+ RedCloth
6
+ activesupport
7
+ coderay
8
+ eeepub-with-cover-support
9
+ i18n
10
+ nokogiri
11
+ notifier
12
+ rdiscount
13
+ thor
14
+
15
+ GEM
16
+ remote: https://rubygems.org/
17
+ specs:
18
+ RedCloth (4.2.9)
19
+ activesupport (3.2.12)
20
+ i18n (~> 0.6)
21
+ multi_json (~> 1.0)
22
+ awesome_print (1.1.0)
23
+ builder (3.2.0)
24
+ coderay (1.0.9)
25
+ diff-lcs (1.2.2)
26
+ eeepub-with-cover-support (0.8.7)
27
+ builder
28
+ rubyzip
29
+ i18n (0.6.4)
30
+ method_source (0.8.1)
31
+ multi_json (1.7.2)
32
+ nokogiri (1.5.9)
33
+ notifier (0.4.1)
34
+ pry (0.9.12)
35
+ coderay (~> 1.0.5)
36
+ method_source (~> 0.8)
37
+ slop (~> 3.4)
38
+ pry-nav (0.2.3)
39
+ pry (~> 0.9.10)
40
+ rake (10.0.4)
41
+ rdiscount (2.0.7.1)
42
+ rspec (2.13.0)
43
+ rspec-core (~> 2.13.0)
44
+ rspec-expectations (~> 2.13.0)
45
+ rspec-mocks (~> 2.13.0)
46
+ rspec-core (2.13.1)
47
+ rspec-expectations (2.13.0)
48
+ diff-lcs (>= 1.1.3, < 2.0)
49
+ rspec-mocks (2.13.0)
50
+ rubyzip (0.9.9)
51
+ slop (3.4.4)
52
+ test_notifier (1.0.1)
53
+ notifier
54
+ thor (0.18.1)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ awesome_print
61
+ bookshelf!
62
+ pry
63
+ pry-nav
64
+ rake
65
+ rspec
66
+ test_notifier
@@ -0,0 +1,162 @@
1
+ # Bookshelf
2
+
3
+ Bookshelf is a tool for the self-publishing of books. It is inspired by (and heavily based off) the excellent Kitabu gem [https://github.com/fnando/kitabu]().
4
+
5
+ ## Features
6
+ * Generate HTML, PDF, e-Pub, Mobi and Text files
7
+ * Multi book support
8
+ * Write using Markdown, Textile or plain HTML
9
+ * Book layout support
10
+ * Custom font support
11
+ * SCSS support
12
+ * Table of Contents generation
13
+
14
+ ## Installation
15
+
16
+ To install Bookshelf, you’ll need a working Ruby 1.9+ installation.
17
+ If you’re cool with it, just run the following command to install it.
18
+
19
+ gem install bookshelf
20
+
21
+ After installing Bookshelf, run the following command to check your external
22
+ dependencies.
23
+
24
+ $ bookshelf check
25
+
26
+ Prince XML: Converts HTML files into PDF files.
27
+ Installed.
28
+
29
+ KindleGen: Converts ePub e-books into .mobi files.
30
+ Installed.
31
+
32
+ html2text: Converts HTML documents into plain text.
33
+ Not installed.
34
+
35
+ There's no requirements here; just make sure you cleared the correct dependency based
36
+ on the formats you want to export to.
37
+
38
+ ## Getting Started
39
+
40
+ We first need to generate a new bookshelf project
41
+
42
+ $ bookshelf new my_bookshelf
43
+
44
+ This command creates a directory `my_bookshelf` with the following structure:
45
+
46
+ my_bookshelf
47
+ ├── assets
48
+ │ ├── fonts
49
+ │ ├── images
50
+ │ └── styles
51
+ │ ├── _fonts.scss
52
+ │ ├── epub.scss
53
+ │ └── html.scss
54
+ ├── books
55
+ ├── config
56
+ │ ├── config.yml
57
+ │ └── helper.rb
58
+ ├── output
59
+ └── templates
60
+ ├── epub
61
+ │ ├── cover.erb
62
+ │ ├── page.erb
63
+ └── html
64
+ └── layout.erb
65
+
66
+ ## Creating a new Book
67
+
68
+ To add a book create a folder under the `books` directory, named as per the title.
69
+
70
+ my_bookshelf
71
+ └── books
72
+ └── my_book
73
+
74
+ Copy the `config.yml` file from `my_bookshelf/config/config.yml` into `my_bookshelf/books/my_book`
75
+
76
+ Update `my_bookshelf/config/config.yml` to reflect the books title, author and other attributes.
77
+
78
+ ## Authoring
79
+
80
+ Now, create the content for your book by creating markdown or textile files into the `my_bookshelf/books/my_book` directory. You have two options here but both are dependent on the numeric prefix assigned to the file to determine their order.
81
+
82
+ *Option 1 - Directories for chapters:*
83
+
84
+ my_bookshelf
85
+ └── books
86
+ └── my_book
87
+ ├── 01_introduction
88
+ │ ├── 01_section_1.markdown
89
+ │ ├── 02_section_2.markdown
90
+ │ └── ...
91
+ ├── 02_chapter_1
92
+ │ ├── 01_section_1.markdown
93
+ │ ├── 02_section_2.markdown
94
+ │ └── ...
95
+ ├── 03_chapter_2
96
+ ├── 04_chapter_3
97
+ └── ...
98
+
99
+ *Option 2 - Files for chapters:*
100
+
101
+ my_bookshelf
102
+ └── books
103
+ └── my_book
104
+ ├── 01_introduction.markdown
105
+ ├── 02_chapter_1.markdown
106
+ ├── 03_chapter_2.markdown
107
+ ├── 04_chapter_3.markdown
108
+ └── ...
109
+
110
+ Note that you if the number of chapters in your book is likely to exceed 10, you should add an extra 0 to the front of the chapter directory/file names
111
+
112
+ Note that you can use any format you want at the same time. Just use one of the following extensions: `.html`, `.markdown`, `.mkdn` or `.textile`.
113
+
114
+ ## Exporting
115
+
116
+ You'll want to see your progress eventually; it's time for you to generate the book PDF. Just run the command `bookshelf export` and your book will be created in the `output` directory.
117
+
118
+ Bookshelf can generate a Table of Contents (TOC) based on your `h2-h6` tags. The `h1` tag is discarded because it's meant to be the book title.
119
+
120
+ To print the TOC, you need to print a variable called `toc`, using the eRb tag.
121
+
122
+ <%= toc %>
123
+
124
+ ## Markdown Processors
125
+
126
+ By default, RDiscount[http://github.com/rtomayko/rdiscount/tree/master] is the Markdown processor. However, you can switch to different implementations by simply installing any of the following processors:
127
+
128
+ * Maruku: https://rubygems.org/gems/maruku
129
+ * PEGMarkdown: https://rubygems.org/gems/rpeg-markdown
130
+ * BlueCloth: https://rubygems.org/gems/bluecloth
131
+ * Redcarpet: https://rubygems.org/gems/redcarpet
132
+
133
+ Note: RDiscount will always be installed as Bookshelf's dependency but only used when no
134
+ alternative library is available.
135
+
136
+ ## References
137
+
138
+ * Textile: http://hobix.com/textile
139
+ * Markdown: http://daringfireball.net/projects/markdown/syntax
140
+
141
+ ## License
142
+
143
+ (The MIT License)
144
+
145
+ Permission is hereby granted, free of charge, to any person obtaining
146
+ a copy of this software and associated documentation files (the
147
+ 'Software'), to deal in the Software without restriction, including
148
+ without limitation the rights to use, copy, modify, merge, publish,
149
+ distribute, sublicense, and/or sell copies of the Software, and to
150
+ permit persons to whom the Software is furnished to do so, subject to
151
+ the following conditions:
152
+
153
+ The above copyright notice and this permission notice shall be
154
+ included in all copies or substantial portions of the Software.
155
+
156
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
157
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
158
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
159
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
160
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
161
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
162
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- mode: ruby -*-
3
+
4
+ require "bookshelf"
5
+ Bookshelf::Cli.start
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "bookshelf/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "bookshelf"
7
+ s.version = Bookshelf::Version::STRING
8
+ s.platform = Gem::Platform::RUBY
9
+ s.required_ruby_version = ">= 1.9"
10
+ s.authors = ["Brad Crawford"]
11
+ s.email = ["brad.robert.crawford@gmail.com"]
12
+ s.homepage = "https://bitbucket.org/bradcrawford/bookshelf"
13
+ s.summary = "A framework that generates PDF and e-Pub from Markdown, Textile, and HTML files."
14
+ s.description = s.summary
15
+ s.license = "MIT"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "activesupport"
23
+ s.add_dependency "nokogiri"
24
+ s.add_dependency "RedCloth"
25
+ s.add_dependency "rdiscount"
26
+ s.add_dependency "i18n"
27
+ s.add_dependency "thor"
28
+ s.add_dependency "eeepub-with-cover-support"
29
+ s.add_dependency "notifier"
30
+
31
+ s.add_development_dependency "rspec"
32
+ s.add_development_dependency "test_notifier"
33
+ s.add_development_dependency "rake"
34
+ s.add_development_dependency "pry"
35
+ s.add_development_dependency "pry-nav"
36
+ s.add_development_dependency "awesome_print"
37
+ end
@@ -0,0 +1,64 @@
1
+ require "active_support/all"
2
+ require "digest/md5"
3
+ require "eeepub"
4
+ require "erb"
5
+ require "logger"
6
+ require "nokogiri"
7
+ require "notifier"
8
+ require "open3"
9
+ require "optparse"
10
+ require "ostruct"
11
+ require "RedCloth"
12
+ require "tempfile"
13
+ require "pathname"
14
+ require "thor"
15
+ require "thor/group"
16
+ require "yaml"
17
+ require "cgi"
18
+
19
+ %w[maruku peg_markdown bluecloth redcarpet rdiscount].each do |lib|
20
+ begin
21
+ require lib
22
+ break
23
+ rescue LoadError => e
24
+ next
25
+ end
26
+ end
27
+
28
+ Encoding.default_internal = "utf-8"
29
+ Encoding.default_external = "utf-8"
30
+
31
+ module Bookshelf
32
+ require "bookshelf/extensions/string"
33
+ require "bookshelf/extensions/redcloth"
34
+ require "bookshelf/errors"
35
+
36
+ ROOT = Pathname.new(File.dirname(__FILE__) + "/..")
37
+
38
+ autoload :Version, "bookshelf/version"
39
+ autoload :Generator, "bookshelf/generator"
40
+ autoload :TOC, "bookshelf/toc"
41
+ autoload :Cli, "bookshelf/cli"
42
+ autoload :Markdown, "bookshelf/adapters/markdown"
43
+ autoload :Parser, "bookshelf/parser"
44
+ autoload :Exporter, "bookshelf/exporter"
45
+ autoload :Syntax, "bookshelf/syntax"
46
+ autoload :Stream, "bookshelf/stream"
47
+ autoload :Dependency, "bookshelf/dependency"
48
+ autoload :Stats, "bookshelf/stats"
49
+
50
+ def self.config(book_dir = nil)
51
+ path = book_dir.join("config.yml")
52
+ content = File.read(path)
53
+ erb = ERB.new(content).result
54
+ YAML.load(erb).with_indifferent_access
55
+ end
56
+
57
+ def self.logger
58
+ @logger ||= Logger.new(File.open("/tmp/bookshelf.log", "a"))
59
+ end
60
+
61
+ def self.root_dir
62
+ @root_dir ||= Pathname.new(Dir.pwd)
63
+ end
64
+ end
@@ -0,0 +1,34 @@
1
+ module Bookshelf
2
+ class Markdown
3
+ # Supported Markdown libraries
4
+ #
5
+ MARKDOWN_LIBRARIES = %w[Maruku BlueCloth PEGMarkdown Redcarpet RDiscount]
6
+
7
+ # Retrieve preferred Markdown processor.
8
+ # You'll need one of the following libraries:
9
+ #
10
+ # # RDiscount: https://rubygems.org/gems/rdiscount
11
+ # # Maruku: https://rubygems.org/gems/maruku
12
+ # # PEGMarkdown: https://rubygems.org/gems/rpeg-markdown
13
+ # # BlueCloth: https://rubygems.org/gems/bluecloth
14
+ # # Redcarpet: https://rubygems.org/gems/redcarpet
15
+ #
16
+ # Note: RDiscount will always be installed as Bookshelf's dependency but only used when no
17
+ # alternative library is available.
18
+ #
19
+ def self.engine
20
+ @engine ||= Object.const_get(MARKDOWN_LIBRARIES.find {|lib| Object.const_defined?(lib)})
21
+ end
22
+
23
+ # Convert Markdown to HTML.
24
+ def self.to_html(content)
25
+ case engine.name
26
+ when "Redcarpet"
27
+ render = Redcarpet::Render::HTML.new(:hard_wrap => true, :xhtml => true)
28
+ Redcarpet::Markdown.new(render).render(content)
29
+ else
30
+ engine.new(content).to_html
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,125 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Bookshelf
3
+ class Cli < Thor
4
+ FORMATS = %w[pdf html epub mobi txt]
5
+ check_unknown_options!
6
+
7
+ def self.exit_on_failure?
8
+ true
9
+ end
10
+
11
+ def initialize(args = [], options = {}, config = {})
12
+ if (config[:current_task] || config[:current_command]).name == "new" && args.empty?
13
+ raise Error, "The e-Book path is required. For details run: bookshelf help new"
14
+ end
15
+
16
+ super
17
+ end
18
+
19
+ desc "new EBOOK_PATH", "Generate a new e-book structure"
20
+
21
+ def new(path)
22
+ generator = Generator.new
23
+ generator.destination_root = path
24
+ generator.invoke_all
25
+ end
26
+
27
+ desc "export [OPTIONS]", "Export e-book"
28
+ method_option :only, :type => :string, :desc => "Can be one of: #{FORMATS.join(", ")}"
29
+
30
+ def export
31
+ if options[:only] && !FORMATS.include?(options[:only])
32
+ raise Error, "The --only option need to be one of: #{FORMATS.join(", ")}"
33
+ end
34
+
35
+ book_dirs = if options[:book]
36
+ [Bookshelf.root_dir.join("books/#{options[:book]}")]
37
+ else
38
+ Dir.glob(Bookshelf.root_dir.join("books/*")).map{|book_dir| Pathname.new(book_dir) }
39
+ end
40
+
41
+ book_dirs.each do |book_dir|
42
+ Bookshelf::Exporter.run(book_dir, options)
43
+ end
44
+ end
45
+
46
+ desc "version", "Prints the Bookshelf's version information"
47
+ map %w(-v --version) => :version
48
+
49
+ def version
50
+ say "Bookshelf version #{Version::STRING}"
51
+ end
52
+
53
+ desc "check", "Check if all external dependencies are installed"
54
+
55
+ def check
56
+ result = []
57
+
58
+ result << {
59
+ :description => "Prince XML: Converts HTML files into PDF files.",
60
+ :installed => Bookshelf::Dependency.prince?
61
+ }
62
+
63
+ result << {
64
+ :description => "KindleGen: Converts ePub e-books into .mobi files.",
65
+ :installed => Bookshelf::Dependency.kindlegen?
66
+ }
67
+
68
+ result << {
69
+ :description => "html2text: Converts HTML documents into plain text.",
70
+ :installed => Bookshelf::Dependency.html2text?
71
+ }
72
+
73
+ result.each do |result|
74
+ text = color(result[:name], :blue)
75
+ text << "\n" << result[:description]
76
+ text << "\n" << (result[:installed] ? color("Installed.", :green) : color("Not installed.", :red))
77
+ text << "\n"
78
+
79
+ say(text)
80
+ end
81
+ end
82
+
83
+ desc "permalinks", "List title permalinks"
84
+
85
+ def permalinks
86
+ html = Bookshelf::Parser::HTML.new(Bookshelf.root_dir).content
87
+ toc = Bookshelf::TOC::HTML.generate(html)
88
+
89
+ toc.toc.each do |options|
90
+ level = options[:level] - 1
91
+ title = " #{options[:text]}: "
92
+ permalink = "##{options[:permalink]}"
93
+
94
+ text = "*" * level
95
+ text << color(title, :blue)
96
+ text << color(permalink, :yellow)
97
+ say(text)
98
+ end
99
+ end
100
+
101
+ desc "stats", "Display some stats about your e-book"
102
+ def stats
103
+ stats = Bookshelf::Stats.new(Bookshelf.root_dir)
104
+
105
+ say [
106
+ "Chapters: #{stats.chapters}",
107
+ "Words: #{stats.words}",
108
+ "Images: #{stats.images}",
109
+ "Links: #{stats.links}",
110
+ "Footnotes: #{stats.footnotes}",
111
+ "Code blocks: #{stats.code_blocks}"
112
+ ].join("\n")
113
+ end
114
+
115
+ private
116
+
117
+ def color(text, color)
118
+ color? ? shell.set_color(text, color) : text
119
+ end
120
+
121
+ def color?
122
+ shell.instance_of?(Thor::Shell::Color)
123
+ end
124
+ end
125
+ end