softcover 0.8.9 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/softcover/book_manifest.rb +17 -5
- data/lib/softcover/builder.rb +29 -1
- data/lib/softcover/builders/epub.rb +5 -11
- data/lib/softcover/builders/html.rb +5 -3
- data/lib/softcover/builders/mobi.rb +6 -13
- data/lib/softcover/builders/pdf.rb +23 -4
- data/lib/softcover/builders/preview.rb +1 -3
- data/lib/softcover/cli.rb +24 -3
- data/lib/softcover/commands/build.rb +29 -6
- data/lib/softcover/commands/check.rb +103 -0
- data/lib/softcover/commands/deployment.rb +0 -7
- data/lib/softcover/commands/epub_validator.rb +2 -8
- data/lib/softcover/sanitizer.rb +5 -1
- data/lib/softcover/template/.softcover-build +6 -0
- data/lib/softcover/template/chapters/a_chapter.md +10 -11
- data/lib/softcover/template/chapters/a_chapter.tex +13 -21
- data/lib/softcover/template/chapters/another_chapter.md +3 -1
- data/lib/softcover/template/config/lang.yml +14 -0
- data/lib/softcover/template/config/preamble.tex +8 -0
- data/lib/softcover/template/epub/OEBPS/styles/custom_epub.css +7 -0
- data/lib/softcover/template/images/cover-web.png +0 -0
- data/lib/softcover/template/images/cover.pdf +0 -0
- data/lib/softcover/template/images/cover.png +0 -0
- data/lib/softcover/template/latex_styles/custom_pdf.sty +6 -4
- data/lib/softcover/template/latex_styles/language_customization.sty +11 -0
- data/lib/softcover/template/latex_styles/softcover.sty +10 -7
- data/lib/softcover/utils.rb +65 -6
- data/lib/softcover/version.rb +1 -1
- data/lib/softcover.rb +1 -0
- data/softcover.gemspec +10 -10
- data/spec/builders/mobi_spec.rb +5 -3
- data/spec/builders/pdf_spec.rb +19 -0
- data/spec/cli_spec.rb +27 -0
- data/spec/commands/build_spec.rb +9 -0
- data/spec/commands/check_spec.rb +57 -0
- metadata +49 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5cde257d853b87404d19decb7190ed774b6f68c2
|
4
|
+
data.tar.gz: 4a22997a284fa6f364c61aeee24344942a485a94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b5aacf11aa98f5bf6683574c138a51bb9e3b39c205001f628d5a10a82831eca40c8505561e559d7c4292f7b60cb362d95fb1d81f2e1e3495ee73b7bb4e697ae
|
7
|
+
data.tar.gz: 2d56e4ec07a2eb1c4e70bdd6cfc3349d989b813fb0d950d8e6a6cb7a87876d89dbdefc0feada9ce5b37282ca3da99cbc7753b80dacd11b4daf12dddec73e650b
|
@@ -35,9 +35,15 @@ class Softcover::BookManifest < OpenStruct
|
|
35
35
|
|
36
36
|
# Returns a chapter heading for use in the navigation menu.
|
37
37
|
def menu_heading
|
38
|
-
raw_html = Polytexnic::Pipeline.new(title
|
38
|
+
raw_html = Polytexnic::Pipeline.new(title,
|
39
|
+
language_labels: language_labels).
|
40
|
+
to_html
|
39
41
|
html = Nokogiri::HTML(raw_html).at_css('p').inner_html
|
40
|
-
chapter_number.zero?
|
42
|
+
if chapter_number.zero?
|
43
|
+
html
|
44
|
+
else
|
45
|
+
"#{chapter_label(chapter_number)}: #{html}"
|
46
|
+
end
|
41
47
|
end
|
42
48
|
|
43
49
|
def to_hash
|
@@ -103,7 +109,7 @@ class Softcover::BookManifest < OpenStruct
|
|
103
109
|
if base_contents.match(/frontmatter/)
|
104
110
|
@frontmatter = true
|
105
111
|
chapters.push Chapter.new(slug: 'frontmatter',
|
106
|
-
title:
|
112
|
+
title: language_labels["frontmatter"],
|
107
113
|
sections: nil,
|
108
114
|
chapter_number: 0)
|
109
115
|
end
|
@@ -139,7 +145,11 @@ class Softcover::BookManifest < OpenStruct
|
|
139
145
|
template_dir = File.join(File.dirname(__FILE__), 'template')
|
140
146
|
files = [File.join(Softcover::Directories::CONFIG, 'marketing.yml'),
|
141
147
|
path('images/cover-web.png'),
|
142
|
-
path('latex_styles/custom_pdf.sty')
|
148
|
+
path('latex_styles/custom_pdf.sty'),
|
149
|
+
path('config/preamble.tex'),
|
150
|
+
path('config/lang.yml'),
|
151
|
+
path('epub/OEBPS/styles/custom_epub.css')
|
152
|
+
]
|
143
153
|
files.each do |file|
|
144
154
|
unless File.exist?(file)
|
145
155
|
puts "Copying missing file '#{file}' from template"
|
@@ -346,7 +356,9 @@ class Softcover::BookManifest < OpenStruct
|
|
346
356
|
chapter_file_paths do |chapter_path|
|
347
357
|
next if chapter_path =~ /frontmatter/
|
348
358
|
unless File.exist?(chapter_path)
|
349
|
-
|
359
|
+
$stderr.puts "ERROR -- document not built"
|
360
|
+
$stderr.puts "Chapter file '#{chapter_path}'' not found"
|
361
|
+
exit 1
|
350
362
|
end
|
351
363
|
end
|
352
364
|
end
|
data/lib/softcover/builder.rb
CHANGED
@@ -10,6 +10,7 @@ module Softcover
|
|
10
10
|
@built_files = []
|
11
11
|
ensure_style_file_locations
|
12
12
|
write_polytexnic_commands_file
|
13
|
+
write_language_customization_file
|
13
14
|
end
|
14
15
|
|
15
16
|
def build!(options={})
|
@@ -51,8 +52,35 @@ module Softcover
|
|
51
52
|
|
52
53
|
# Writes out the PolyTeXnic commands from polytexnic.
|
53
54
|
def write_polytexnic_commands_file
|
54
|
-
styles_dir = File.join(Dir.pwd, Softcover::Directories::STYLES)
|
55
55
|
Polytexnic.write_polytexnic_style_file(styles_dir)
|
56
56
|
end
|
57
|
+
|
58
|
+
def write_language_customization_file
|
59
|
+
filename = File.join(styles_dir, 'language_customization.sty')
|
60
|
+
contents = listing_customization
|
61
|
+
File.write(filename, contents)
|
62
|
+
end
|
63
|
+
|
64
|
+
def styles_dir
|
65
|
+
File.join(Dir.pwd, Softcover::Directories::STYLES)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def listing_customization
|
70
|
+
listing = language_labels["listing"].downcase
|
71
|
+
box = language_labels["aside"]
|
72
|
+
<<-EOS
|
73
|
+
% Aside box label
|
74
|
+
\\renewcommand{\\boxlabel}{#{box}}
|
75
|
+
|
76
|
+
% Codelisting captions
|
77
|
+
\\usepackage[hypcap=false]{caption}
|
78
|
+
\\DeclareCaptionFormat{#{listing}}{\\hspace{-0.2em}\\colorbox[gray]{.85}{\\hspace{0.1em}\\parbox{0.997\\textwidth}{#1#2#3}}\\vspace{-1.3\\baselineskip}}
|
79
|
+
\\captionsetup[#{listing}]{format=#{listing},labelfont=bf,skip=16pt,font={rm,normalsize}}
|
80
|
+
\\DeclareCaptionType{#{listing}}
|
81
|
+
\\newcommand{\\codecaption}[1]{\\captionof{#{listing}}{#1}}
|
82
|
+
EOS
|
83
|
+
end
|
84
|
+
|
57
85
|
end
|
58
86
|
end
|
@@ -177,20 +177,12 @@ module Softcover
|
|
177
177
|
|
178
178
|
# Returns the PhantomJS executable (if available).
|
179
179
|
def phantomjs
|
180
|
-
|
181
|
-
message = "Install PhantomJS (http://phantomjs.org/)"
|
182
|
-
@phantomjs ||= executable(filename, message)
|
180
|
+
@phantomjs ||= executable(dependency_filename(:phantomjs))
|
183
181
|
end
|
184
182
|
|
185
183
|
# Returns the Inkscape executable (if available).
|
186
184
|
def inkscape
|
187
|
-
|
188
|
-
if filename.empty?
|
189
|
-
filename = '/Applications/Inkscape.app/Contents/Resources/bin/' +
|
190
|
-
'inkscape'
|
191
|
-
end
|
192
|
-
message = "Install Inkscape (http://inkscape.org/)"
|
193
|
-
@inkscape ||= executable(filename, message)
|
185
|
+
@inkscape ||= executable(dependency_filename(:inkscape))
|
194
186
|
end
|
195
187
|
|
196
188
|
# Strip attributes that are invalid in EPUB documents.
|
@@ -342,6 +334,7 @@ module Softcover
|
|
342
334
|
<item id="softcover.css" href="styles/softcover.css" media-type="text/css"/>
|
343
335
|
<item id="epub.css" href="styles/epub.css" media-type="text/css"/>
|
344
336
|
<item id="custom.css" href="styles/custom.css" media-type="text/css"/>
|
337
|
+
<item id="custom_epub.css" href="styles/custom_epub.css" media-type="text/css"/>
|
345
338
|
<item id="cover" href="cover.html" media-type="application/xhtml+xml"/>
|
346
339
|
#{man_ch.join("\n")}
|
347
340
|
#{images.join("\n")}
|
@@ -401,7 +394,7 @@ module Softcover
|
|
401
394
|
end
|
402
395
|
|
403
396
|
def chapter_name(n)
|
404
|
-
n == 0 ? "
|
397
|
+
n == 0 ? language_labels["frontmatter"] : chapter_label(n)
|
405
398
|
end
|
406
399
|
|
407
400
|
# Returns the nav HTML content.
|
@@ -440,6 +433,7 @@ module Softcover
|
|
440
433
|
<link rel="stylesheet" href="styles/softcover.css" type="text/css" />
|
441
434
|
<link rel="stylesheet" href="styles/epub.css" type="text/css" />
|
442
435
|
<link rel="stylesheet" href="styles/custom.css" type="text/css"/>
|
436
|
+
<link rel="stylesheet" href="styles/custom_epub.css" type="text/css"/>
|
443
437
|
<link rel="stylesheet" type="application/vnd.adobe-page-template+xml" href="styles/page-template.xpgt" />
|
444
438
|
</head>
|
445
439
|
|
@@ -99,7 +99,8 @@ module Softcover
|
|
99
99
|
File.write(chapter.cache_filename, digest(markdown))
|
100
100
|
p = Polytexnic::Pipeline.new(markdown,
|
101
101
|
source: :markdown,
|
102
|
-
custom_commands: Softcover.custom_styles
|
102
|
+
custom_commands: Softcover.custom_styles,
|
103
|
+
language_labels: language_labels)
|
103
104
|
p.polytex
|
104
105
|
end
|
105
106
|
|
@@ -112,8 +113,9 @@ module Softcover
|
|
112
113
|
polytex.gsub!(/(^\s*\\include{(.*?)})/) do
|
113
114
|
File.read($2 + '.tex') + "\n"
|
114
115
|
end
|
115
|
-
|
116
|
-
|
116
|
+
Polytexnic::Pipeline.new(polytex,
|
117
|
+
custom_commands: Softcover.custom_styles,
|
118
|
+
language_labels: language_labels).to_html
|
117
119
|
end
|
118
120
|
|
119
121
|
# Writes the full HTML file for the book.
|
@@ -12,7 +12,7 @@ module Softcover
|
|
12
12
|
else
|
13
13
|
system(command)
|
14
14
|
end
|
15
|
-
|
15
|
+
if options[:calibre]
|
16
16
|
FileUtils.mv("ebooks/#{filename}.azw3", "ebooks/#{filename}.mobi")
|
17
17
|
puts "MOBI saved to ebooks/#{filename}.mobi" unless silent
|
18
18
|
end
|
@@ -25,28 +25,21 @@ module Softcover
|
|
25
25
|
|
26
26
|
# Returns the command for making a MOBI, based on the options.
|
27
27
|
def mobi_command(filename, options={})
|
28
|
-
if options[:
|
29
|
-
"#{kindlegen} ebooks/#{filename}.epub"
|
30
|
-
else
|
28
|
+
if options[:calibre]
|
31
29
|
"#{calibre} ebooks/#{filename}.epub ebooks/#{filename}.azw3"
|
30
|
+
else
|
31
|
+
"#{kindlegen} ebooks/#{filename}.epub"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
37
|
def calibre
|
38
|
-
|
39
|
-
url = 'http://calibre-ebook.com/'
|
40
|
-
message = "Install Calibre (#{url}) and enable command line tools"
|
41
|
-
message += " (http://manual.calibre-ebook.com/cli/cli-index.html)"
|
42
|
-
@calibre ||= executable(filename, message)
|
38
|
+
@calibre ||= executable(dependency_filename(:calibre))
|
43
39
|
end
|
44
40
|
|
45
41
|
def kindlegen
|
46
|
-
|
47
|
-
url = 'http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211'
|
48
|
-
message = "Install kindlegen (#{url})"
|
49
|
-
@kindlegen ||= executable(filename, message)
|
42
|
+
@kindlegen ||= executable(dependency_filename(:kindlegen))
|
50
43
|
end
|
51
44
|
end
|
52
45
|
end
|
@@ -5,6 +5,7 @@ module Softcover
|
|
5
5
|
include Softcover::Utils
|
6
6
|
|
7
7
|
def build!(options={})
|
8
|
+
make_png_from_gif
|
8
9
|
if manifest.markdown?
|
9
10
|
# Build the HTML to produce PolyTeX as a side-effect,
|
10
11
|
# then update the manifest to reduce PDF generation
|
@@ -29,7 +30,9 @@ module Softcover
|
|
29
30
|
polytex_filenames = manifest.pdf_chapter_filenames << book_filename
|
30
31
|
polytex_filenames.each do |filename|
|
31
32
|
polytex = File.read(filename)
|
32
|
-
latex = Polytexnic::Pipeline.new(polytex
|
33
|
+
latex = Polytexnic::Pipeline.new(polytex,
|
34
|
+
language_labels: language_labels).
|
35
|
+
to_latex
|
33
36
|
if filename == book_filename
|
34
37
|
latex.gsub!(/\\include{(.*?)}/) do
|
35
38
|
"\\include{#{Softcover::Utils.tmpify(manifest, $1)}.tmp}"
|
@@ -67,9 +70,25 @@ module Softcover
|
|
67
70
|
# The `xelatex` program is roughly equivalent to the more standard
|
68
71
|
# `pdflatex`, but has better support for Unicode.
|
69
72
|
def xelatex
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
+
@xelatex ||= executable(dependency_filename(:latex))
|
74
|
+
end
|
75
|
+
|
76
|
+
# Make a PNG for each GIF in the images/ directory.
|
77
|
+
def make_png_from_gif
|
78
|
+
gif_pattern = File.join('images', '**', '*.gif')
|
79
|
+
gif_files = Dir.glob(gif_pattern).reject { |f| File.directory?(f) }
|
80
|
+
gif_files.each do |gif|
|
81
|
+
dir = File.dirname(gif)
|
82
|
+
ext = File.extname(gif)
|
83
|
+
img = File.basename(gif, ext)
|
84
|
+
png = File.join(dir, "#{img}.png")
|
85
|
+
system "#{convert} #{gif} #{png}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns the executable to ImageMagick's `convert` program.
|
90
|
+
def convert
|
91
|
+
@convert ||= executable(dependency_filename(:convert))
|
73
92
|
end
|
74
93
|
|
75
94
|
# Returns the command to build the PDF (once).
|
@@ -25,9 +25,7 @@ module Softcover
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def ghostscript
|
28
|
-
|
29
|
-
message = "Install GhostScript (should come with LaTeX)"
|
30
|
-
@ghostscript ||= executable(filename, message)
|
28
|
+
@ghostscript ||= executable(dependency_filename(:ghostscript))
|
31
29
|
end
|
32
30
|
end
|
33
31
|
end
|
data/lib/softcover/cli.rb
CHANGED
@@ -42,9 +42,9 @@ module Softcover
|
|
42
42
|
desc: "Find overfull hboxes",
|
43
43
|
type: :boolean
|
44
44
|
elsif format == 'mobi'
|
45
|
-
method_option :
|
46
|
-
|
47
|
-
|
45
|
+
method_option :calibre, aliases: '-c',
|
46
|
+
desc: "Use Calibre to build the MOBI",
|
47
|
+
type: :boolean
|
48
48
|
end
|
49
49
|
method_option :quiet, aliases: '-q',
|
50
50
|
desc: "Quiet output", type: :boolean
|
@@ -67,6 +67,27 @@ module Softcover
|
|
67
67
|
Softcover::Commands::Build.preview(options)
|
68
68
|
end
|
69
69
|
|
70
|
+
# ===============================================
|
71
|
+
# Clean
|
72
|
+
# ===============================================
|
73
|
+
desc "clean", "Clean unneeded files"
|
74
|
+
def clean
|
75
|
+
rm(Dir.glob('*.aux'))
|
76
|
+
rm(Dir.glob('*.toc'))
|
77
|
+
rm(Dir.glob('*.out'))
|
78
|
+
rm(Dir.glob('*.tmp.*'))
|
79
|
+
rm(Dir.glob(path('tmp/*')))
|
80
|
+
rm('.highlight_cache')
|
81
|
+
end
|
82
|
+
|
83
|
+
# ===============================================
|
84
|
+
# Check
|
85
|
+
# ===============================================
|
86
|
+
desc "check", "Check dependencies"
|
87
|
+
def check
|
88
|
+
Softcover::Commands::Check.check_dependencies!
|
89
|
+
end
|
90
|
+
|
70
91
|
# ===============================================
|
71
92
|
# Server
|
72
93
|
# ===============================================
|
@@ -2,6 +2,7 @@ module Softcover
|
|
2
2
|
module Commands
|
3
3
|
module Build
|
4
4
|
include Softcover::Output
|
5
|
+
include Softcover::Utils
|
5
6
|
extend self
|
6
7
|
|
7
8
|
# Builds the book for the given format.
|
@@ -17,13 +18,17 @@ module Softcover
|
|
17
18
|
# Builds the book for all formats.
|
18
19
|
def all_formats(options={})
|
19
20
|
building_message('all formats', options)
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
if custom?
|
22
|
+
build_custom_formats!
|
23
|
+
else
|
24
|
+
Softcover::BUILD_ALL_FORMATS.each do |format|
|
25
|
+
if format == 'mobi'
|
26
|
+
building_message('EPUB & MOBI', options)
|
27
|
+
else
|
28
|
+
building_message(format.upcase, options)
|
29
|
+
end
|
30
|
+
builder_for(format).build!(options)
|
25
31
|
end
|
26
|
-
builder_for(format).build!(options)
|
27
32
|
end
|
28
33
|
end
|
29
34
|
|
@@ -38,6 +43,24 @@ module Softcover
|
|
38
43
|
"Softcover::Builders::#{format.titleize}".constantize.new
|
39
44
|
end
|
40
45
|
|
46
|
+
def custom?
|
47
|
+
File.exist?(build_config) && !custom_commands.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_custom_formats!
|
51
|
+
execute custom_commands
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns custom commands (if any).
|
55
|
+
def custom_commands
|
56
|
+
commands(File.readlines(build_config).map(&:strip))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the filename for configuring `softcover build`.
|
60
|
+
def build_config
|
61
|
+
'.softcover-build'
|
62
|
+
end
|
63
|
+
|
41
64
|
private
|
42
65
|
|
43
66
|
# Shows a message when building a particular format.
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Softcover
|
2
|
+
module Commands
|
3
|
+
module Check
|
4
|
+
extend self
|
5
|
+
extend Softcover::Utils
|
6
|
+
|
7
|
+
def check_dependencies!
|
8
|
+
puts "Checking Softcover dependencies..."
|
9
|
+
simulate_work(1)
|
10
|
+
missing_dependencies = []
|
11
|
+
dependencies.each do |label, name|
|
12
|
+
printf "%-30s", "Checking for #{name}..."
|
13
|
+
simulate_work(0.15)
|
14
|
+
if present?(label)
|
15
|
+
puts "Found"
|
16
|
+
else
|
17
|
+
missing_dependencies << label
|
18
|
+
puts "Missing"
|
19
|
+
end
|
20
|
+
simulate_work(0.1)
|
21
|
+
end
|
22
|
+
simulate_work(0.25)
|
23
|
+
if missing_dependencies.empty?
|
24
|
+
puts "All dependencies satisfied."
|
25
|
+
else
|
26
|
+
puts "Missing dependencies:"
|
27
|
+
missing_dependencies.each do |dependency|
|
28
|
+
puts " • " + missing_dependency_message(dependency)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def dependencies
|
34
|
+
[[:latex, 'LaTeX'],
|
35
|
+
[:ghostscript, 'GhostScript'],
|
36
|
+
[:convert, 'ImageMagick'],
|
37
|
+
[:node, 'Node.js'],
|
38
|
+
[:phantomjs, 'PhantomJS'],
|
39
|
+
[:inkscape, 'Inkscape'],
|
40
|
+
[:calibre, 'Calibre'],
|
41
|
+
[:kindlegen, 'KindleGen'],
|
42
|
+
[:java, 'Java'],
|
43
|
+
[:epubcheck, 'EpubCheck'],
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
def dependency_labels
|
48
|
+
dependencies.map(&:first)
|
49
|
+
end
|
50
|
+
|
51
|
+
def dependency_names
|
52
|
+
dependencies.map { |e| e[1] }
|
53
|
+
end
|
54
|
+
|
55
|
+
def missing_dependency_message(label)
|
56
|
+
case label
|
57
|
+
when :latex
|
58
|
+
message = "LaTeX (http://latex-project.org/ftp.html)\n"
|
59
|
+
message += " ∟ Huge download—start it now!"
|
60
|
+
when :convert
|
61
|
+
"ImageMagick (http://www.imagemagick.org/script/binary-releases.php)"
|
62
|
+
when :node
|
63
|
+
"NodeJS (http://nodejs.org/)"
|
64
|
+
when :phantomjs
|
65
|
+
"PhantomJS (http://phantomjs.org/)"
|
66
|
+
when :kindlegen
|
67
|
+
url = 'http://www.amazon.com/gp/feature.html?ie=UTF8&docId=1000765211'
|
68
|
+
"KindleGen (#{url})"
|
69
|
+
when :calibre
|
70
|
+
url = 'http://calibre-ebook.com/'
|
71
|
+
message = "Calibre (#{url})\n"
|
72
|
+
message += " ∟ Enable Calibre command-line tools"
|
73
|
+
message += " (http://manual.calibre-ebook.com/cli/cli-index.html)"
|
74
|
+
when :java
|
75
|
+
url = 'http://www.java.com/en/download/help/index_installing.xml'
|
76
|
+
"Java (#{url})"
|
77
|
+
when :ghostscript
|
78
|
+
"GhostScript (should come with LaTeX)"
|
79
|
+
when :epubcheck
|
80
|
+
url = 'https://github.com/IDPF/epubcheck/releases/'
|
81
|
+
url += 'download/v3.0/epubcheck-3.0.zip'
|
82
|
+
message = "EpubCheck 3.0 (#{url})\n"
|
83
|
+
message += " ∟ Unzip EpubCheck into your home directory"
|
84
|
+
when :inkscape
|
85
|
+
message = "Inkscape (http://inkscape.org/)"
|
86
|
+
else
|
87
|
+
raise "Unknown label #{label}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def present?(label)
|
92
|
+
File.exist?(dependency_filename(label))
|
93
|
+
end
|
94
|
+
|
95
|
+
# Simulate working for given time.
|
96
|
+
# `softcover check` is more satisfying if it looks like it's doing work.
|
97
|
+
def simulate_work(time)
|
98
|
+
sleep time unless Softcover::test?
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -30,13 +30,6 @@ module Softcover
|
|
30
30
|
def deploy_config
|
31
31
|
'.softcover-deploy'
|
32
32
|
end
|
33
|
-
|
34
|
-
# Returns the commands from the given lines.
|
35
|
-
# We skip comments and blank lines.
|
36
|
-
def commands(lines)
|
37
|
-
skip = /(^\s*#|^\s*$)/
|
38
|
-
lines.reject { |line| line =~ skip }.join("\n")
|
39
|
-
end
|
40
33
|
end
|
41
34
|
end
|
42
35
|
end
|
@@ -14,17 +14,11 @@ module Softcover
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def java
|
17
|
-
|
18
|
-
url = 'http://www.java.com/en/download/help/index_installing.xml'
|
19
|
-
message = "Install Java (#{url})"
|
20
|
-
@java ||= executable(filename, message)
|
17
|
+
@java ||= executable(dependency_filename(:java))
|
21
18
|
end
|
22
19
|
|
23
20
|
def epubcheck
|
24
|
-
|
25
|
-
url = 'https://github.com/IDPF/epubcheck/releases/download/v3.0/epubcheck-3.0.zip'
|
26
|
-
message = "Download EpubCheck 3.0 (#{url}) and unzip it in your home directory"
|
27
|
-
@epubcheck ||= executable(filename, message).inspect
|
21
|
+
@epubcheck ||= executable(dependency_filename(:epubcheck)).inspect
|
28
22
|
end
|
29
23
|
end
|
30
24
|
end
|
data/lib/softcover/sanitizer.rb
CHANGED
@@ -29,7 +29,11 @@ module Softcover
|
|
29
29
|
'img' => %w{id class src alt},
|
30
30
|
'em' => %w{id class},
|
31
31
|
'code' => %w{id class},
|
32
|
-
'strong' => %w{id class}
|
32
|
+
'strong' => %w{id class},
|
33
|
+
'table' => %w{id class},
|
34
|
+
'tbody' => %w{id class},
|
35
|
+
'tr' => %w{id class},
|
36
|
+
'td' => %w{id class}
|
33
37
|
},
|
34
38
|
protocols: {
|
35
39
|
'a' => {'href' => [:relative, 'http', 'https', 'mailto']},
|
@@ -75,6 +75,12 @@ Softcover supports the inclusion of images, like this:
|
|
75
75
|
|
76
76
|
![Some dude.](images/2011_michael_hartl.png)
|
77
77
|
|
78
|
+
Using \LaTeX\ labels, you can also include a caption (as in Figure~\ref{fig:captioned_image}) or just a figure number (as in Figure~\ref{fig:figure_number}).
|
79
|
+
|
80
|
+
![Some dude.\label{fig:captioned_image}](images/2011_michael_hartl.png)
|
81
|
+
|
82
|
+
![\label{fig:figure_number}](images/2011_michael_hartl.png)
|
83
|
+
|
78
84
|
### Tables
|
79
85
|
|
80
86
|
Softcover supports raw tables via a simple table syntax:
|
@@ -88,6 +94,7 @@ Softcover supports raw tables via a simple table syntax:
|
|
88
94
|
| `PATCH` | /users/1 | `update` | update user with id `1` |
|
89
95
|
| `DELETE` | /users/1 | `destroy` | delete user with id `1` |
|
90
96
|
|
97
|
+
See [*The Softcover Book*](http://manual.softcover.io/book/softcover_markdown#sec-embedded_tabular_and_tables) to learn how to make more complicated tables.
|
91
98
|
|
92
99
|
## Command-line interface
|
93
100
|
|
@@ -102,17 +109,9 @@ Commands:
|
|
102
109
|
softcover build:mobi # Build MOBI
|
103
110
|
softcover build:pdf # Build PDF
|
104
111
|
softcover build:preview # Build book preview in all formats
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
softcover help [COMMAND] # Describe available commands...
|
109
|
-
softcover login # Log into Softcover account
|
110
|
-
softcover logout # Log out of Softcover account
|
111
|
-
softcover new <name> # Generate new book directory structure.
|
112
|
-
softcover open # Open book on Softcover website (OS X)
|
113
|
-
softcover publish # Publish your book on Softcover
|
114
|
-
softcover publish:screencasts # Publish screencasts
|
115
|
-
softcover server # Run local server
|
112
|
+
.
|
113
|
+
.
|
114
|
+
.
|
116
115
|
```
|
117
116
|
|
118
117
|
\noindent You can run `softcover help <command>` to get additional help on a given command:
|