carta 0.0.3.pre1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +46 -0
- data/Rakefile +1 -0
- data/bin/carta +9 -0
- data/carta.gemspec +28 -0
- data/lib/carta/cli/book.rb +20 -0
- data/lib/carta/cli/chapter.rb +47 -0
- data/lib/carta/cli/compile.rb +129 -0
- data/lib/carta/cli/html_renderer.rb +55 -0
- data/lib/carta/cli/outline_renderer.rb +32 -0
- data/lib/carta/cli.rb +69 -0
- data/lib/carta/templates/ebook/assets/cover.jpg +0 -0
- data/lib/carta/templates/ebook/assets/css/.empty_directory +0 -0
- data/lib/carta/templates/ebook/assets/fonts/.empty_directory +0 -0
- data/lib/carta/templates/ebook/layouts/epub/EPUB/content.xhtml.erb +7 -0
- data/lib/carta/templates/ebook/layouts/epub/EPUB/main.ncx.erb +30 -0
- data/lib/carta/templates/ebook/layouts/epub/EPUB/main.opf.erb +31 -0
- data/lib/carta/templates/ebook/layouts/epub/EPUB/nav.xhtml.erb +12 -0
- data/lib/carta/templates/ebook/layouts/epub/META-INF/container.xml.erb +7 -0
- data/lib/carta/templates/ebook/layouts/html/index.html.erb +11 -0
- data/lib/carta/templates/ebook/manuscript/book.yaml.tt +5 -0
- data/lib/carta/templates/ebook/manuscript/figures/.empty_directory +0 -0
- data/lib/carta/templates/new_chapter.tt +1 -0
- data/lib/carta/util.rb +18 -0
- data/lib/carta/version.rb +3 -0
- data/lib/carta.rb +10 -0
- metadata +171 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6573752786e7b5fb4b78048bd2bff5587dc1dd3e
|
4
|
+
data.tar.gz: 113b54e8aab31cf481df770a19adcc395eacd281
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 06493f69384d0dedc81f0c56ba07cf216f31a550d9000dad7593546d898b6db23ca1bb075248b63ecbb0ad1df60ae8d02e8d9a495d62f7add5e203d33c0c4451
|
7
|
+
data.tar.gz: 4559e6ab6ce87fab4d5e72a9bdd7cb1dad1bda07e08e43c44f1b5378d424dbdc836c96621b953ed7d6993bec31ca957e2aa78fe0222d6ea80e63c906c6bbbeb3
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Dylan Wreggelsworth
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# Carta
|
2
|
+
|
3
|
+
Carta is a command line tool to aid in the ebook creation workflow. Initially it will support the HTML and EPUB formats.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'carta'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install carta
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
$ carta book
|
22
|
+
Walks you through a book project creation process.
|
23
|
+
|
24
|
+
$ carta chapter [number] [name]
|
25
|
+
Will create a markdown file in the correct place with the name you specify.
|
26
|
+
numbers formatted like `1.1` will create a folder that matches the correct heirarchy and then create an H# tag with the correct level. Following these formats help generate a well formed table of contents
|
27
|
+
|
28
|
+
$ carta compile
|
29
|
+
Will generate a build folder with the compiled files in it.
|
30
|
+
|
31
|
+
## TODO
|
32
|
+
* Add partial support
|
33
|
+
* Remove html generation from the cli codebase
|
34
|
+
* Maybe switch to tilt for templates
|
35
|
+
* Improve chapter creation (not intuitive atm)
|
36
|
+
* Improve status messages
|
37
|
+
* Use thor for more of the template rendering/etc.
|
38
|
+
* Integrate SCSS/etc.
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
1. Fork it ( http://github.com/<my-github-username>/carta/fork )
|
43
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
44
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
45
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
46
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/carta
ADDED
data/carta.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'carta/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'carta'
|
8
|
+
spec.version = Carta::VERSION
|
9
|
+
spec.authors = ['Dylan Wreggelsworth']
|
10
|
+
spec.email = ['dylan@bvrgroup.us']
|
11
|
+
spec.summary = 'An ebook generator.'
|
12
|
+
spec.description = 'Generates a basic ebook project directory and renders it.'
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_runtime_dependency 'uuid', '>= 0'
|
24
|
+
spec.add_runtime_dependency 'rubyzip', '~> 1.0.0'
|
25
|
+
spec.add_runtime_dependency 'mime-types', '~> 2.1'
|
26
|
+
spec.add_runtime_dependency 'thor', '= 0.18.1'
|
27
|
+
spec.add_runtime_dependency 'redcarpet', '= 3.0.0'
|
28
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Carta::CLI
|
2
|
+
# This is our book generator
|
3
|
+
class Book
|
4
|
+
attr_reader :meta, :thor, :book_name
|
5
|
+
|
6
|
+
def initialize(thor, meta)
|
7
|
+
@thor = thor
|
8
|
+
@meta = meta
|
9
|
+
@book_name = (meta[:title].is_a? String) ? meta[:title] : meta[:title].join(' ')
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
require 'carta/cli/chapter'
|
14
|
+
thor.directory 'ebook', book_name
|
15
|
+
thor.inside book_name do
|
16
|
+
Carta::CLI::Chapter.new(thor, 0, "My First #{book_name} Chapter").run
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Carta::CLI
|
2
|
+
# A class for chapter generation
|
3
|
+
class Chapter
|
4
|
+
attr_reader :thor,
|
5
|
+
:chapter_number,
|
6
|
+
:pretty_number,
|
7
|
+
:chapter_name,
|
8
|
+
:sub_chapter_name,
|
9
|
+
:level
|
10
|
+
|
11
|
+
def initialize(thor, chapter_number, *chapter_name)
|
12
|
+
@thor = thor
|
13
|
+
@chapters = chapter_number.to_s.split('.')
|
14
|
+
@chapters[0] = Carta::Util.pad(@chapters[0])
|
15
|
+
|
16
|
+
if @chapters.length > 1
|
17
|
+
@chapters[1] = Carta::Util.pad(@chapters[1])
|
18
|
+
else
|
19
|
+
@chapters[1] = '01'
|
20
|
+
end
|
21
|
+
|
22
|
+
@chapter_name = chapter_name.join(' ')
|
23
|
+
@dasherized_name = Carta::Util.slug(@chapter_name)
|
24
|
+
@handy_chapter_name = "#{@chapters[0]}-#{@dasherized_name}"
|
25
|
+
@handy_subchapter_name = "#{@chapters[1]}-#{@dasherized_name}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
if Dir.exists?('manuscript')
|
30
|
+
target_dir = Dir.glob("manuscript/#{@chapters[0]}*")
|
31
|
+
if target_dir.empty?
|
32
|
+
path = "manuscript/#{@handy_chapter_name}/#{@handy_subchapter_name}.md"
|
33
|
+
else
|
34
|
+
path = "#{target_dir[0]}/#{@handy_subchapter_name}.md"
|
35
|
+
end
|
36
|
+
thor.create_file path do
|
37
|
+
level = @chapters[2].nil? ? '#' : '#' * (@chapters[2].to_i + 1)
|
38
|
+
contents = "#{level} #{chapter_name}"
|
39
|
+
contents << "\nLorem ipsum dolor sit amet, consectetur adipisicing elit."
|
40
|
+
end
|
41
|
+
else
|
42
|
+
thor.say('Please create a book first.',:red)
|
43
|
+
thor.help
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'thor/rake_compat'
|
3
|
+
require 'mime-types'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'zip'
|
6
|
+
require 'carta/cli/html_renderer'
|
7
|
+
require 'pry'
|
8
|
+
|
9
|
+
|
10
|
+
module Carta
|
11
|
+
class CLI::Compile
|
12
|
+
attr_reader :thor,
|
13
|
+
:book,
|
14
|
+
:PROJECT_DIR,
|
15
|
+
:LAYOUT_DIR,
|
16
|
+
:MANUSCRIPT_DIR,
|
17
|
+
:FIGURE_DIR,
|
18
|
+
:ASSET_DIR,
|
19
|
+
:BUILD_DIR,
|
20
|
+
:ASSET_FILES
|
21
|
+
|
22
|
+
def initialize(thor)
|
23
|
+
if Dir.exists?('manuscript')
|
24
|
+
@thor = thor
|
25
|
+
@PROJECT_DIR = Dir.pwd
|
26
|
+
@BUILD_DIR = "build"
|
27
|
+
@LAYOUT_DIR = "#{@PROJECT_DIR}/layouts"
|
28
|
+
@MANUSCRIPT_DIR = "#{@PROJECT_DIR}/manuscript"
|
29
|
+
@FIGURE_DIR = "#{@MANUSCRIPT_DIR}/figures"
|
30
|
+
@ASSET_DIR = "#{@PROJECT_DIR}/assets"
|
31
|
+
@ASSET_FILES = 'css,otf,ttf,jpeg,jpg,png,svg,gif'
|
32
|
+
@book = YAML.load_file("#{@MANUSCRIPT_DIR}/book.yaml")
|
33
|
+
else
|
34
|
+
thor.error 'No book found to compile!'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def run
|
39
|
+
generate_html if Dir.exists?('manuscript')
|
40
|
+
end
|
41
|
+
|
42
|
+
# Generates our HTML from markdown files and creates an outline
|
43
|
+
def generate_html
|
44
|
+
html_renderer = Carta::CLI::HTMLRenderer.new(@PROJECT_DIR)
|
45
|
+
# puts @MANUSCRIPT_DIR
|
46
|
+
book['html'] = html_renderer.manuscript_html
|
47
|
+
book['outline'] = html_renderer.outline
|
48
|
+
book['toc_html'] = html_renderer.toc_html
|
49
|
+
|
50
|
+
generate_manifest
|
51
|
+
end
|
52
|
+
|
53
|
+
# Runs through our ERBs
|
54
|
+
def render_layouts
|
55
|
+
FileList.new("#{@LAYOUT_DIR}/epub/**/*.erb").each do |layout|
|
56
|
+
filename = layout.pathmap("%{^#{@LAYOUT_DIR},#{@BUILD_DIR}}X")
|
57
|
+
path = filename.pathmap('%d')
|
58
|
+
|
59
|
+
FileUtils.mkpath(path) unless File.exists? path
|
60
|
+
|
61
|
+
template = ERB.new(File.read(layout), nil, '-')
|
62
|
+
File.open(filename, 'w+') do |handle|
|
63
|
+
handle.write template.result(binding)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def generate_manifest
|
69
|
+
files = FileList.new("#{@LAYOUT_DIR}/epub/EPUB/*.erb")
|
70
|
+
.pathmap("%{^#{@LAYOUT_DIR}/epub/EPUB/,}X")
|
71
|
+
.exclude('**/*.opf*')
|
72
|
+
.exclude('content.xhtml', 'nav.xhtml')
|
73
|
+
.exclude('**/*.ncx*')
|
74
|
+
.add("#{@FIGURE_DIR}/**/*.{#{@ASSET_FILES}}",
|
75
|
+
"#{@ASSET_DIR}/**/*.{#{@ASSET_FILES}}",
|
76
|
+
"#{@MANUSCRIPT_DIR}/cover.{#{@ASSET_FILES}}")
|
77
|
+
.pathmap("%{^#{@ASSET_DIR}/,}p")
|
78
|
+
.pathmap("%{^#{@FIGURE_DIR},figures}p")
|
79
|
+
|
80
|
+
book['manifest'] = []
|
81
|
+
|
82
|
+
files.each do |file|
|
83
|
+
media_type = MIME::Types.type_for(file).first.content_type
|
84
|
+
if file.include? 'cover'
|
85
|
+
book['cover'] = { filename: file, media_type: media_type }
|
86
|
+
else
|
87
|
+
book['manifest'] << { filename: file, media_type: media_type }
|
88
|
+
end
|
89
|
+
end
|
90
|
+
copy_files
|
91
|
+
render_layouts
|
92
|
+
generate_epub
|
93
|
+
end
|
94
|
+
|
95
|
+
def copy_files
|
96
|
+
assets = FileList.new("#{@FIGURE_DIR}/**/*.{#{@ASSET_FILES}}",
|
97
|
+
"#{@ASSET_DIR}/**/*.{#{@ASSET_FILES}}",
|
98
|
+
"#{@MANUSCRIPT_DIR}/cover.{#{@ASSET_FILES}}")
|
99
|
+
|
100
|
+
dest = assets.pathmap("%{^#{@ASSET_DIR},#{@BUILD_DIR}/epub/EPUB}p")
|
101
|
+
.pathmap("%{^#{@FIGURE_DIR},#{@BUILD_DIR}/epub/EPUB/figures}p")
|
102
|
+
|
103
|
+
assets.each_with_index do |file, index|
|
104
|
+
thor.copy_file file, dest[index]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def generate_epub
|
109
|
+
files = FileList.new("#{@BUILD_DIR}/epub/**/*")
|
110
|
+
zip_path = files.pathmap("%{^#{@BUILD_DIR}/epub/,}p")
|
111
|
+
.exclude('EPUB', 'META-INF', 'mimetype')
|
112
|
+
files = files.exclude("#{@BUILD_DIR}/epub/EPUB", "#{@BUILD_DIR}/epub/META-INF")
|
113
|
+
zip = Zip::OutputStream.new("#{@BUILD_DIR}/#{book['title']}.epub")
|
114
|
+
zip.put_next_entry('mimetype', nil, nil, Zip::Entry::STORED, Zlib::NO_COMPRESSION)
|
115
|
+
zip.write "application/epub+zip"
|
116
|
+
zip_list = {}
|
117
|
+
zip_path.each_with_index do |value, i|
|
118
|
+
zip_list[value] = files[i]
|
119
|
+
end
|
120
|
+
zip_list.keys.each do |key|
|
121
|
+
# puts "#{key}: #{zip_list[key]}"
|
122
|
+
zip.put_next_entry key, nil, nil, Zip::Entry::DEFLATED, Zlib::BEST_COMPRESSION
|
123
|
+
zip.write IO.read(zip_list[key])
|
124
|
+
end
|
125
|
+
zip.close
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'carta/cli/outline_renderer'
|
2
|
+
|
3
|
+
module Carta
|
4
|
+
class CLI::HTMLRenderer
|
5
|
+
attr_accessor :markdown,
|
6
|
+
:manuscript_html,
|
7
|
+
:toc_html,
|
8
|
+
:outline
|
9
|
+
|
10
|
+
def initialize(path)
|
11
|
+
@markdown = ''
|
12
|
+
@toc_html = ''
|
13
|
+
@manuscript_html = ''
|
14
|
+
@outline = nil
|
15
|
+
load_markdown(path)
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_markdown(path)
|
19
|
+
FileList.new("#{path}/manuscript/**/*.md").sort.each do |md_file|
|
20
|
+
IO.readlines(md_file).each { |line| markdown << line }
|
21
|
+
markdown << "\n\n"
|
22
|
+
end
|
23
|
+
render_manuscript
|
24
|
+
end
|
25
|
+
|
26
|
+
def render_manuscript
|
27
|
+
renderer = OutlineRenderer.new
|
28
|
+
r = Redcarpet::Markdown.new(renderer)
|
29
|
+
manuscript_html << r.render(markdown)
|
30
|
+
@outline = renderer.outline
|
31
|
+
render_outline
|
32
|
+
end
|
33
|
+
|
34
|
+
def render_outline(html_class='toc')
|
35
|
+
final_class = "class='#{html_class}'"
|
36
|
+
outline.each_with_index do |data, i|
|
37
|
+
level, text, link, *children = data
|
38
|
+
toc_html << "<ol #{final_class}>" if i == 0
|
39
|
+
toc_html << "\n <li><a href='content.xhtml##{link}'>#{text}</a>"
|
40
|
+
|
41
|
+
if children.empty?
|
42
|
+
toc_html << '</li>'
|
43
|
+
else
|
44
|
+
children.each_with_index do |child, j|
|
45
|
+
level, text, link = child
|
46
|
+
toc_html << "\n <ol>" if j == 0
|
47
|
+
toc_html << "\n <li><a href='content.xhtml##{link}'>#{text}</a></li>"
|
48
|
+
toc_html << "\n </ol>\n </li>" if j == children.length - 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
toc_html << "\n</ol>" if i == outline.length - 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Custom Renderer for Redcarpet
|
2
|
+
class OutlineRenderer < Redcarpet::Render::HTML
|
3
|
+
attr_accessor :outline
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@outline = []
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
# Required by Redcarpet to change behavior of the the renderer
|
11
|
+
def header(text, header_level)
|
12
|
+
prior_level = 1
|
13
|
+
text_slug = sluggize(text)
|
14
|
+
value = [header_level, text, text_slug]
|
15
|
+
if header_level <= 2
|
16
|
+
(prior_level < header_level) ? outline.last << value : outline << value
|
17
|
+
with_id = true
|
18
|
+
elsif header_level > 2
|
19
|
+
with_id = false
|
20
|
+
end
|
21
|
+
render_line(header_level, text, text_slug, with_id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def render_line(header_level, text, text_slug, with_id = false)
|
25
|
+
id = "id='#{text_slug}'" if with_id
|
26
|
+
"<h#{header_level} #{id}>#{text}</h#{header_level}>"
|
27
|
+
end
|
28
|
+
|
29
|
+
def sluggize(text)
|
30
|
+
text.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
|
31
|
+
end
|
32
|
+
end
|
data/lib/carta/cli.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'uuid'
|
2
|
+
require 'carta/cli/book'
|
3
|
+
require 'carta/cli/chapter'
|
4
|
+
|
5
|
+
module Carta::CLI
|
6
|
+
# The class from which it all begins
|
7
|
+
class Base < Thor
|
8
|
+
include Thor::Actions
|
9
|
+
attr_reader :meta,
|
10
|
+
:BUILD_PATH,
|
11
|
+
:LAYOUT_PATH,
|
12
|
+
:MANU_PATH,
|
13
|
+
:ASSET_PATH
|
14
|
+
|
15
|
+
# def initialize(*args)
|
16
|
+
# @BUILD_PATH = 'build'
|
17
|
+
# @LAYOUT_PATH = 'layouts'
|
18
|
+
# @MANU_PATH = 'manuscript'
|
19
|
+
# @ASSET_PATH = 'assets'
|
20
|
+
# end
|
21
|
+
|
22
|
+
def self.source_root
|
23
|
+
File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
|
24
|
+
end
|
25
|
+
|
26
|
+
# desc 'book', 'Create a book with the given name'
|
27
|
+
desc 'book', 'Generate a book with an optional [NAME].'
|
28
|
+
def book(*name)
|
29
|
+
name = name.empty? ? '' : name.join(' ')
|
30
|
+
|
31
|
+
say("\nThis utility will walk you through creating an ebook project.")
|
32
|
+
say("\nPress ^C at any time to quit.")
|
33
|
+
|
34
|
+
require 'carta/cli/book'
|
35
|
+
|
36
|
+
default_name = name.empty? ? '' : "(#{name})"
|
37
|
+
|
38
|
+
ask_title = ask "Title:#{default_name}"
|
39
|
+
ask_license = ask 'License: (MIT)'
|
40
|
+
ask_lang = ask 'Language: (en-US)'
|
41
|
+
ask_author = ask 'Author(s): (Anonymous)'
|
42
|
+
ask_uuid = ask 'uuid:'
|
43
|
+
|
44
|
+
@meta = {
|
45
|
+
title: ask_title.empty? ? name : ask_title,
|
46
|
+
subtitle: ask('Subtitle: (blank)'),
|
47
|
+
authors: ask_author.empty? ? 'Anonymous' : ask_author,
|
48
|
+
language: ask_lang.empty? ? 'en-US' : ask_lang,
|
49
|
+
license: ask_license.empty? ? 'MIT' : ask_license,
|
50
|
+
uid: ask_uuid.empty? ? UUID.new.generate : ask_uuid
|
51
|
+
}
|
52
|
+
Carta::CLI::Book.new(self, meta).run
|
53
|
+
end
|
54
|
+
|
55
|
+
desc 'chapter [number] [name]',
|
56
|
+
'Create a chapter with the given name or number.'
|
57
|
+
def chapter(number, *name)
|
58
|
+
number, name = '00', [number].concat(name) unless /\d+/.match number
|
59
|
+
require 'carta/cli/chapter'
|
60
|
+
Carta::CLI::Chapter.new(self, number, name).run
|
61
|
+
end
|
62
|
+
|
63
|
+
desc 'compile', 'Create the final ebook'
|
64
|
+
def compile
|
65
|
+
require 'carta/cli/compile'
|
66
|
+
Carta::CLI::Compile.new(self).run
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
Binary file
|
File without changes
|
File without changes
|
@@ -0,0 +1,30 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<ncx xmlns:ncx="http://www.daisy.org/z3986/2005/ncx/" xmlns="http://www.daisy.org/z3986/2005/ncx/"
|
3
|
+
version="2005-1" xml:lang="en">
|
4
|
+
<head>
|
5
|
+
<meta name="dtb:uid" content="<%= book['uid'] %>"/>
|
6
|
+
</head>
|
7
|
+
<docTitle>
|
8
|
+
<text><%= book['title'] %></text>
|
9
|
+
</docTitle>
|
10
|
+
<navMap>
|
11
|
+
<%- book['outline'].each_with_index do |item, i| -%>
|
12
|
+
<navPoint id="#<%= item[2] %>">
|
13
|
+
<navLabel>
|
14
|
+
<text><%= i+1 -%>. <%= item[1] %></text>
|
15
|
+
</navLabel>
|
16
|
+
<content src="content.xhtml#<%= item[2] %>"/>
|
17
|
+
<%- if item.length > 3
|
18
|
+
for j in (3..(item.length - 3)) -%>
|
19
|
+
<navPoint id="#<%= item[j][2] %>">
|
20
|
+
<navLabel>
|
21
|
+
<text><%= "#{i+1}.#{j-2}" %> <%= item[j][1] %></text>
|
22
|
+
</navLabel>
|
23
|
+
<content src="content.xhtml#<%= item[j][2] %>"/>
|
24
|
+
</navPoint>
|
25
|
+
<%- end -%>
|
26
|
+
<%- end -%>
|
27
|
+
</navPoint>
|
28
|
+
<%- end -%>
|
29
|
+
</navMap>
|
30
|
+
</ncx>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<package xmlns="http://www.idpf.org/2007/opf"
|
3
|
+
version="3.0"
|
4
|
+
unique-identifier="uid"
|
5
|
+
xml:lang="<%= book['language'] %>"
|
6
|
+
prefix="cc: http://creativecommons.org/ns#">
|
7
|
+
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
|
8
|
+
<dc:identifier id="uid"><%= book['uid'] %></dc:identifier>
|
9
|
+
<dc:title><%= book['title'] %></dc:title>
|
10
|
+
<dc:creator><%= book['authors'] %></dc:creator>
|
11
|
+
<dc:language><%= book['language'] %></dc:language>
|
12
|
+
<dc:rights><%= book['license'] %></dc:rights>
|
13
|
+
<meta property="dcterms:modified"><%= DateTime.now.strftime('%Y-%m-%dT%TZ') %></meta>
|
14
|
+
<!-- cover meta element included for 2.0 reading system compatibility: -->
|
15
|
+
<meta name="cover" content="cover"/>
|
16
|
+
</metadata>
|
17
|
+
<manifest>
|
18
|
+
<%- book['manifest'].each do |item| -%>
|
19
|
+
<item id="<%= File.basename(item[:filename],'.*') %>" href="<%= item[:filename].gsub('EPUB/','') %>" media-type="<%= item[:media_type] %>" />
|
20
|
+
<%- end -%>
|
21
|
+
<item id="cover" href="<%= book['cover'][:filename] %>" media-type="<%= book['cover'][:media_type] %>" properties="cover-image" />
|
22
|
+
<item id="content" href="content.xhtml" media-type="application/xhtml+xml"/>
|
23
|
+
<item id="toc" properties="nav" href="nav.xhtml" media-type="application/xhtml+xml"/>
|
24
|
+
<!-- ncx included for 2.0 reading system compatibility: -->
|
25
|
+
<item id="ncx" href="main.ncx" media-type="application/x-dtbncx+xml" />
|
26
|
+
</manifest>
|
27
|
+
<spine toc='ncx'>
|
28
|
+
<itemref linear='yes' idref="toc" />
|
29
|
+
<itemref linear='yes' idref="content" />
|
30
|
+
</spine>
|
31
|
+
</package>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<html xmlns="http://www.w3.org/1999/xhtml"
|
2
|
+
xmlns:epub="http://www.idpf.org/2007/ops">
|
3
|
+
<head></head>
|
4
|
+
<body>
|
5
|
+
<section>
|
6
|
+
<nav epub:type="toc">
|
7
|
+
<h1><%= book['title'].gsub(/\w+/) {|word| word.capitalize} %></h1>
|
8
|
+
<%= book['toc_html'] %>
|
9
|
+
</nav>
|
10
|
+
</section>
|
11
|
+
</body>
|
12
|
+
</html>
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= level %> <%= chapter_name %>
|
data/lib/carta/util.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Carta::Util
|
2
|
+
# Takes a string and prepares it for use as a filename
|
3
|
+
# or URL.
|
4
|
+
# "Hello World!" -> "hello-world"
|
5
|
+
def self.slug(string)
|
6
|
+
string.downcase
|
7
|
+
.strip
|
8
|
+
.gsub(' ', '-')
|
9
|
+
.gsub(/[^0-9A-z.\-]/, '')
|
10
|
+
end
|
11
|
+
|
12
|
+
# Pads at number so that it's 2 digits wide with leading
|
13
|
+
# zeros if needed.
|
14
|
+
# 1 -> 01
|
15
|
+
def self.pad(number)
|
16
|
+
sprintf('%02d', number.to_s)
|
17
|
+
end
|
18
|
+
end
|
data/lib/carta.rb
ADDED
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: carta
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3.pre1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dylan Wreggelsworth
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-05 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: uuid
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubyzip
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.0.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mime-types
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.1'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: thor
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.18.1
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.18.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: redcarpet
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 3.0.0
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 3.0.0
|
111
|
+
description: Generates a basic ebook project directory and renders it.
|
112
|
+
email:
|
113
|
+
- dylan@bvrgroup.us
|
114
|
+
executables:
|
115
|
+
- carta
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- Gemfile
|
121
|
+
- LICENSE.txt
|
122
|
+
- README.md
|
123
|
+
- Rakefile
|
124
|
+
- bin/carta
|
125
|
+
- carta.gemspec
|
126
|
+
- lib/carta.rb
|
127
|
+
- lib/carta/cli.rb
|
128
|
+
- lib/carta/cli/book.rb
|
129
|
+
- lib/carta/cli/chapter.rb
|
130
|
+
- lib/carta/cli/compile.rb
|
131
|
+
- lib/carta/cli/html_renderer.rb
|
132
|
+
- lib/carta/cli/outline_renderer.rb
|
133
|
+
- lib/carta/templates/ebook/assets/cover.jpg
|
134
|
+
- lib/carta/templates/ebook/assets/css/.empty_directory
|
135
|
+
- lib/carta/templates/ebook/assets/fonts/.empty_directory
|
136
|
+
- lib/carta/templates/ebook/layouts/epub/EPUB/content.xhtml.erb
|
137
|
+
- lib/carta/templates/ebook/layouts/epub/EPUB/main.ncx.erb
|
138
|
+
- lib/carta/templates/ebook/layouts/epub/EPUB/main.opf.erb
|
139
|
+
- lib/carta/templates/ebook/layouts/epub/EPUB/nav.xhtml.erb
|
140
|
+
- lib/carta/templates/ebook/layouts/epub/META-INF/container.xml.erb
|
141
|
+
- lib/carta/templates/ebook/layouts/html/index.html.erb
|
142
|
+
- lib/carta/templates/ebook/manuscript/book.yaml.tt
|
143
|
+
- lib/carta/templates/ebook/manuscript/figures/.empty_directory
|
144
|
+
- lib/carta/templates/new_chapter.tt
|
145
|
+
- lib/carta/util.rb
|
146
|
+
- lib/carta/version.rb
|
147
|
+
homepage: ''
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
metadata: {}
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">"
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: 1.3.1
|
165
|
+
requirements: []
|
166
|
+
rubyforge_project:
|
167
|
+
rubygems_version: 2.2.0
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: An ebook generator.
|
171
|
+
test_files: []
|