softcover 0.8.9 → 0.9.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.
- 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
|

|
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
|
+

|
81
|
+
|
82
|
+

|
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:
|