softcover 1.1.22 → 1.1.23
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/article_template/latex_gitignore +2 -0
- data/lib/softcover/article_template/markdown_gitignore +2 -0
- data/lib/softcover/book_manifest.rb +2 -2
- data/lib/softcover/book_template/latex_gitignore +2 -0
- data/lib/softcover/book_template/markdown_gitignore +1 -0
- data/lib/softcover/builders/epub.rb +35 -14
- data/lib/softcover/builders/html.rb +5 -3
- data/lib/softcover/commands/check.rb +3 -3
- data/lib/softcover/utils.rb +14 -4
- data/lib/softcover/version.rb +1 -1
- data/spec/builders/epub_spec.rb +9 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0525db14fac2a0c8d3e36fe1730e11aadea0f260
|
4
|
+
data.tar.gz: 6ac3cade0c04ae7cb4c970a4fe13012d4fb70b29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c575083b8d00e0262bec7b18d37d9d7d079618409a20bd745081c922bf2fdaef6a402cfc4b0bac1085869be71e665e60fad265c34fb5e56f7680fd4d2d01d247
|
7
|
+
data.tar.gz: c0aa8dc1442c3f738fba7aa99534a7701f146dfd0c538c38a9363fc8aa7bbe305072414620bd4c5cb1b2619367082645845bb342bb2890f18df9403f1c116732
|
@@ -31,7 +31,7 @@ class Softcover::BookManifest < OpenStruct
|
|
31
31
|
include Softcover::Utils
|
32
32
|
|
33
33
|
def fragment_name
|
34
|
-
"#{slug}_fragment
|
34
|
+
"#{slug}_fragment.#{html_extension}"
|
35
35
|
end
|
36
36
|
|
37
37
|
def fragment_path
|
@@ -281,7 +281,7 @@ class Softcover::BookManifest < OpenStruct
|
|
281
281
|
|
282
282
|
# Returns the name of the HTML file containing the full book.
|
283
283
|
def full_html_file
|
284
|
-
path("html/#{slug}
|
284
|
+
path("html/#{slug}.#{html_extension}")
|
285
285
|
end
|
286
286
|
|
287
287
|
# Returns chapters for the PDF.
|
@@ -25,6 +25,15 @@ module Softcover
|
|
25
25
|
!options[:amazon] && cover_img
|
26
26
|
end
|
27
27
|
|
28
|
+
def cover_filename
|
29
|
+
xhtml("cover.#{html_extension}")
|
30
|
+
end
|
31
|
+
|
32
|
+
# Transforms foo.html to foo.xhtml
|
33
|
+
def xhtml(filename)
|
34
|
+
filename.sub('.html', '.xhtml')
|
35
|
+
end
|
36
|
+
|
28
37
|
def cover_img_path
|
29
38
|
path("#{images_dir}/#{cover_img}")
|
30
39
|
end
|
@@ -33,6 +42,11 @@ module Softcover
|
|
33
42
|
path('epub/OEBPS/images')
|
34
43
|
end
|
35
44
|
|
45
|
+
def nav_filename
|
46
|
+
xhtml("nav.#{html_extension}")
|
47
|
+
end
|
48
|
+
|
49
|
+
|
36
50
|
def escape(string)
|
37
51
|
CGI.escape_html(string)
|
38
52
|
end
|
@@ -42,7 +56,7 @@ module Softcover
|
|
42
56
|
toc_chapters, manifest_chapters, images)
|
43
57
|
if cover_id
|
44
58
|
cover_meta = %(<meta name="cover" content="#{cover_id}"/>)
|
45
|
-
cover_html =
|
59
|
+
cover_html = %(<item id="cover" href="#{cover_filename}" media-type="application/xhtml+xml"/>)
|
46
60
|
cover_ref = '<itemref idref="cover" linear="no" />'
|
47
61
|
else
|
48
62
|
cover_meta = cover_html = cover_ref = ''
|
@@ -61,7 +75,7 @@ module Softcover
|
|
61
75
|
#{cover_meta}
|
62
76
|
</metadata>
|
63
77
|
<manifest>
|
64
|
-
<item href="
|
78
|
+
<item href="#{nav_filename}" id="nav" media-type="application/xhtml+xml" properties="nav"/>
|
65
79
|
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
|
66
80
|
<item id="page-template.xpgt" href="styles/page-template.xpgt" media-type="application/vnd.adobe-page-template+xml"/>
|
67
81
|
<item id="pygments.css" href="styles/pygments.css" media-type="text/css"/>
|
@@ -160,6 +174,7 @@ module Softcover
|
|
160
174
|
# All the HTML is generated, so this clears out any unused files.
|
161
175
|
def remove_html
|
162
176
|
FileUtils.rm(Dir.glob(path('epub/OEBPS/*.html')))
|
177
|
+
FileUtils.rm(Dir.glob(path('epub/OEBPS/*.xhtml')))
|
163
178
|
end
|
164
179
|
|
165
180
|
# Removes images in case they are stale.
|
@@ -215,14 +230,18 @@ module Softcover
|
|
215
230
|
mkdir images_dir
|
216
231
|
mkdir texmath_dir
|
217
232
|
|
218
|
-
File.write(path(
|
233
|
+
File.write(path("epub/OEBPS/#{cover_filename}"), cover_page) if cover?(options)
|
219
234
|
|
220
235
|
pngs = []
|
221
236
|
chapters.each_with_index do |chapter, i|
|
222
|
-
target_filename = path("epub/OEBPS/#{chapter.fragment_name}")
|
237
|
+
target_filename = path("epub/OEBPS/#{xhtml(chapter.fragment_name)}")
|
223
238
|
File.open(target_filename, 'w') do |f|
|
224
239
|
content = File.read(path("html/#{chapter.fragment_name}"))
|
225
240
|
doc = strip_attributes(Nokogiri::HTML(content))
|
241
|
+
# Use xhtml in references.
|
242
|
+
doc.css('a.hyperref').each do |ref_node|
|
243
|
+
ref_node['href'] = ref_node['href'].sub('.html', xhtml('.html'))
|
244
|
+
end
|
226
245
|
body = doc.at_css('body')
|
227
246
|
if body.nil?
|
228
247
|
$stderr.puts "\nError: Document not built due to empty chapter"
|
@@ -262,9 +281,10 @@ module Softcover
|
|
262
281
|
# SHAs of their contents, which arranges both for unique filenames
|
263
282
|
# and for automatic disk caching.
|
264
283
|
def html_with_math(chapter, images_dir, texmath_dir, pngs, options={})
|
265
|
-
content = File.read(File.join("html",
|
284
|
+
content = File.read(File.join("html",
|
285
|
+
"#{chapter.slug}.#{html_extension}"))
|
266
286
|
pagejs = "#{File.dirname(__FILE__)}/utils/page.js"
|
267
|
-
url = "file://#{Dir.pwd}/html/#{chapter.slug}
|
287
|
+
url = "file://#{Dir.pwd}/html/#{chapter.slug}.#{html_extension}"
|
268
288
|
cmd = "#{phantomjs} #{pagejs} #{url}"
|
269
289
|
silence { silence_stream(STDERR) { system cmd } }
|
270
290
|
# Sometimes in tests the phantomjs_source.html file is missing.
|
@@ -323,7 +343,8 @@ module Softcover
|
|
323
343
|
end
|
324
344
|
# Make references relative.
|
325
345
|
source.css('a.hyperref').each do |ref_node|
|
326
|
-
ref_node['href'] = ref_node['href'].sub('.html',
|
346
|
+
ref_node['href'] = ref_node['href'].sub('.html',
|
347
|
+
xhtml('_fragment.html'))
|
327
348
|
end
|
328
349
|
source.at_css('div#book').children.to_xhtml
|
329
350
|
end
|
@@ -446,7 +467,7 @@ module Softcover
|
|
446
467
|
# Writes the navigation file.
|
447
468
|
# This is required by the EPUB standard.
|
448
469
|
def write_nav
|
449
|
-
File.write(
|
470
|
+
File.write("epub/OEBPS/#{nav_filename}", nav_html)
|
450
471
|
end
|
451
472
|
|
452
473
|
def container_xml
|
@@ -470,7 +491,7 @@ module Softcover
|
|
470
491
|
# Returns the content configuration file.
|
471
492
|
def content_opf(options={})
|
472
493
|
man_ch = chapters.map do |chapter|
|
473
|
-
%(<item id="#{chapter.slug}" href="#{chapter.fragment_name}" media-type="application/xhtml+xml"/>)
|
494
|
+
%(<item id="#{chapter.slug}" href="#{xhtml(chapter.fragment_name)}" media-type="application/xhtml+xml"/>)
|
474
495
|
end
|
475
496
|
toc_ch = chapters.map do |chapter|
|
476
497
|
%(<itemref idref="#{chapter.slug}"/>)
|
@@ -523,14 +544,14 @@ module Softcover
|
|
523
544
|
section_names_and_ids(article).each_with_index do |(name, id), n|
|
524
545
|
chapter_nav << %(<navPoint id="#{id}" playOrder="#{n+1}">)
|
525
546
|
chapter_nav << %( <navLabel><text>#{escape(name)}</text></navLabel>)
|
526
|
-
chapter_nav << %( <content src="#{article.fragment_name}##{id}"/>)
|
547
|
+
chapter_nav << %( <content src="#{xhtml(article.fragment_name)}##{id}"/>)
|
527
548
|
chapter_nav << %(</navPoint>)
|
528
549
|
end
|
529
550
|
else
|
530
551
|
chapters.each_with_index do |chapter, n|
|
531
552
|
chapter_nav << %(<navPoint id="#{chapter.slug}" playOrder="#{n+1}">)
|
532
553
|
chapter_nav << %( <navLabel><text>#{chapter_name(n)}</text></navLabel>)
|
533
|
-
chapter_nav << %( <content src="#{chapter.fragment_name}"/>)
|
554
|
+
chapter_nav << %( <content src="#{xhtml(chapter.fragment_name)}"/>)
|
534
555
|
chapter_nav << %(</navPoint>)
|
535
556
|
end
|
536
557
|
end
|
@@ -547,7 +568,7 @@ module Softcover
|
|
547
568
|
if article?
|
548
569
|
article = chapters.first
|
549
570
|
nav_list = section_names_and_ids(article).map do |name, id|
|
550
|
-
%(<li> <a href="#{article.fragment_name}##{id}">#{name}</a></li>)
|
571
|
+
%(<li> <a href="#{xhtml(article.fragment_name)}##{id}">#{name}</a></li>)
|
551
572
|
end
|
552
573
|
else
|
553
574
|
nav_list = manifest.chapters.map do |chapter|
|
@@ -560,14 +581,14 @@ module Softcover
|
|
560
581
|
|
561
582
|
# Returns a navigation link for the chapter.
|
562
583
|
def nav_link(chapter)
|
563
|
-
%(<a href="#{chapter.fragment_name}">#{chapter.html_title}</a>)
|
584
|
+
%(<a href="#{xhtml(chapter.fragment_name)}">#{chapter.html_title}</a>)
|
564
585
|
end
|
565
586
|
|
566
587
|
# Returns a list of the section names and CSS ids.
|
567
588
|
# Form is [['Beginning', 'sec-beginning'], ['Next', 'sec-next']]
|
568
589
|
def section_names_and_ids(article)
|
569
590
|
# Grab section names and ids from the article.
|
570
|
-
filename = File.join('epub', 'OEBPS', article.fragment_name)
|
591
|
+
filename = File.join('epub', 'OEBPS', xhtml(article.fragment_name))
|
571
592
|
doc = Nokogiri::HTML(File.read(filename))
|
572
593
|
names = doc.css('div.section>h2').map do |s|
|
573
594
|
s.children.children.last.content
|
@@ -127,7 +127,7 @@ module Softcover
|
|
127
127
|
# The resulting file is a self-contained HTML document suitable
|
128
128
|
# for viewing in isolation.
|
129
129
|
def write_full_html_file(basename, file_content, options)
|
130
|
-
html_filename = File.join('html', basename
|
130
|
+
html_filename = File.join('html', "#{basename}.#{html_extension}")
|
131
131
|
File.open(html_filename, 'w') do |f|
|
132
132
|
f.write(file_content)
|
133
133
|
end
|
@@ -221,7 +221,8 @@ module Softcover
|
|
221
221
|
|
222
222
|
# Writes the chapter fragment HTML (omitting, e.g., <html> tags, etc.)
|
223
223
|
def write_fragment_file(chapter)
|
224
|
-
html_filename = File.join('html',
|
224
|
+
html_filename = File.join('html',
|
225
|
+
"#{chapter.slug}_fragment.#{html_extension}")
|
225
226
|
File.open(html_filename, 'w') do |f|
|
226
227
|
chapter.nodes.each do |node|
|
227
228
|
f.write(node.to_xhtml)
|
@@ -232,7 +233,7 @@ module Softcover
|
|
232
233
|
|
233
234
|
# Writes the chapter as a complete, self-contained HTML document.
|
234
235
|
def write_complete_file(chapter, erb_file, n)
|
235
|
-
html_filename = File.join('html', chapter.slug
|
236
|
+
html_filename = File.join('html', "#{chapter.slug}.#{html_extension}")
|
236
237
|
# Make references absolute.
|
237
238
|
chapter.nodes.each do |node|
|
238
239
|
node.css('a.hyperref').each do |ref_node|
|
@@ -255,6 +256,7 @@ module Softcover
|
|
255
256
|
# This also arranges to clear out unused HTML files, as happens when,
|
256
257
|
# e.g., the name of a LaTeX chapter file changes.
|
257
258
|
FileUtils.rm(Dir.glob(path('html/*.html')))
|
259
|
+
FileUtils.rm(Dir.glob(path('html/*.xhtml')))
|
258
260
|
end
|
259
261
|
end
|
260
262
|
end
|
@@ -87,9 +87,9 @@ module Softcover
|
|
87
87
|
"Install zip (e.g., apt-get install zip)"
|
88
88
|
when :epubcheck
|
89
89
|
url = 'https://github.com/IDPF/epubcheck/releases/'
|
90
|
-
url += 'download/
|
91
|
-
message = "EpubCheck
|
92
|
-
message += " ∟ Unzip and place epubcheck-
|
90
|
+
url += 'download/v4.0.1/epubcheck-4.0.1.zip'
|
91
|
+
message = "EpubCheck 4.0.1 (#{url})\n"
|
92
|
+
message += " ∟ Unzip and place epubcheck-4.0.1/ in a directory on your path"
|
93
93
|
when :inkscape
|
94
94
|
message = "Inkscape (http://inkscape.org/)"
|
95
95
|
else
|
data/lib/softcover/utils.rb
CHANGED
@@ -41,6 +41,10 @@ module Softcover::Utils
|
|
41
41
|
Softcover::Config['api_key'].present?
|
42
42
|
end
|
43
43
|
|
44
|
+
def html_extension
|
45
|
+
'html'
|
46
|
+
end
|
47
|
+
|
44
48
|
UNITS = %W(B KB MB GB TB).freeze
|
45
49
|
|
46
50
|
def as_size(number)
|
@@ -238,6 +242,13 @@ module Softcover::Utils
|
|
238
242
|
lines.reject { |line| line =~ skip }.join("\n")
|
239
243
|
end
|
240
244
|
|
245
|
+
# Returns first location on the path for a given file.
|
246
|
+
def first_path(file)
|
247
|
+
possible_paths = ENV['PATH'].split(File::PATH_SEPARATOR).
|
248
|
+
collect { |x| File.join(x, file) }
|
249
|
+
possible_paths.find { |f| File.file?(f) }
|
250
|
+
end
|
251
|
+
|
241
252
|
# Returns the filename of a dependency given a label.
|
242
253
|
def dependency_filename(label)
|
243
254
|
case label
|
@@ -249,10 +260,9 @@ module Softcover::Utils
|
|
249
260
|
get_filename(:'ebook-convert')
|
250
261
|
when :epubcheck
|
251
262
|
# Finds EpubCheck anywhere on the path.
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
possible_paths.select { |f| File.file?(f) }.first || ""
|
263
|
+
version_3 = path('epubcheck-3.0/epubcheck-3.0.jar')
|
264
|
+
version_4 = path('epubcheck-4.0.1/epubcheck.jar')
|
265
|
+
first_path(version_4) || first_path(version_3) || ""
|
256
266
|
when :inkscape
|
257
267
|
default = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
|
258
268
|
filename_or_default(:inkscape, default)
|
data/lib/softcover/version.rb
CHANGED
data/spec/builders/epub_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe Softcover::Builders::Epub do
|
4
4
|
before(:all) do
|
5
5
|
generate_book
|
6
|
-
@file_to_be_removed = path('html/should_be_removed.
|
6
|
+
@file_to_be_removed = path('html/should_be_removed.xhtml')
|
7
7
|
File.write(@file_to_be_removed, '')
|
8
8
|
silence { `softcover build:epub` }
|
9
9
|
@builder = Softcover::Builders::Epub.new
|
@@ -118,9 +118,9 @@ describe Softcover::Builders::Epub do
|
|
118
118
|
it { should exist }
|
119
119
|
|
120
120
|
it "should contain the right filenames in the right order" do
|
121
|
-
filenames = %w[frontmatter_fragment.
|
122
|
-
another_chapter_fragment.
|
123
|
-
yet_another_chapter_fragment.
|
121
|
+
filenames = %w[frontmatter_fragment.xhtml a_chapter_fragment.xhtml
|
122
|
+
another_chapter_fragment.xhtml
|
123
|
+
yet_another_chapter_fragment.xhtml]
|
124
124
|
source_files = doc.css('content').map { |node| node['src'] }
|
125
125
|
expect(source_files).to eql(filenames)
|
126
126
|
end
|
@@ -150,11 +150,11 @@ describe Softcover::Builders::Epub do
|
|
150
150
|
|
151
151
|
it "should create the HTML files" do
|
152
152
|
has_math = false
|
153
|
-
expect(path('epub/OEBPS/cover.
|
153
|
+
expect(path('epub/OEBPS/cover.xhtml')).to exist
|
154
154
|
builder.manifest.chapters.each_with_index do |chapter, i|
|
155
155
|
content = File.read(path("html/#{chapter.slug}_fragment.html"))
|
156
156
|
has_math ||= builder.math?(content)
|
157
|
-
fragment = path("epub/OEBPS/#{chapter.slug}_fragment.
|
157
|
+
fragment = path("epub/OEBPS/#{chapter.slug}_fragment.xhtml")
|
158
158
|
expect(fragment).to exist
|
159
159
|
end
|
160
160
|
# Make sure at least one template file has math.
|
@@ -162,7 +162,7 @@ describe Softcover::Builders::Epub do
|
|
162
162
|
end
|
163
163
|
|
164
164
|
describe "cover file" do
|
165
|
-
subject(:cover_file) { File.read(path('epub/OEBPS/cover.
|
165
|
+
subject(:cover_file) { File.read(path('epub/OEBPS/cover.xhtml')) }
|
166
166
|
it "should have the right cover image" do
|
167
167
|
expect(cover_file).to include 'cover.jpg'
|
168
168
|
end
|
@@ -263,7 +263,7 @@ describe Softcover::EpubUtils do
|
|
263
263
|
end
|
264
264
|
end
|
265
265
|
|
266
|
-
context "nav.
|
266
|
+
context "nav.xhtml template" do
|
267
267
|
let(:nav_list) { [] }
|
268
268
|
let(:template) do
|
269
269
|
dummy_class.new.nav_html_template(title, nav_list)
|
@@ -278,7 +278,7 @@ end
|
|
278
278
|
describe "article validation" do
|
279
279
|
before(:all) do
|
280
280
|
generate_book(markdown: true, article: true)
|
281
|
-
@file_to_be_removed = path('html/should_be_removed.
|
281
|
+
@file_to_be_removed = path('html/should_be_removed.xhtml')
|
282
282
|
File.write(@file_to_be_removed, '')
|
283
283
|
silence { `softcover build:epub` }
|
284
284
|
@builder = Softcover::Builders::Epub.new
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: softcover
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Hartl
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-01-
|
12
|
+
date: 2016-01-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: polytexnic
|