softcover 0.7.11 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.pull_requests/1387399930 +0 -0
- data/.pull_requests/1387400263 +0 -0
- data/.pull_requests/1387592428 +0 -0
- data/.pull_requests/1387944330 +0 -0
- data/.pull_requests/1388094706 +0 -0
- data/.pull_requests/1388441218 +0 -0
- data/Gemfile +1 -0
- data/lib/softcover.rb +2 -1
- data/lib/softcover/book.rb +15 -5
- data/lib/softcover/book_manifest.rb +44 -5
- data/lib/softcover/builder.rb +27 -1
- data/lib/softcover/builders/epub.rb +17 -8
- data/lib/softcover/builders/html.rb +51 -12
- data/lib/softcover/builders/pdf.rb +14 -12
- data/lib/softcover/cli.rb +1 -0
- data/lib/softcover/commands/generator.rb +5 -3
- data/lib/softcover/commands/publisher.rb +3 -0
- data/lib/softcover/commands/server.rb +2 -2
- data/lib/softcover/directories.rb +5 -0
- data/lib/softcover/server/app.rb +1 -25
- data/lib/softcover/server/views/book.html.erb +1 -0
- data/lib/softcover/template/chapters/a_chapter.tex +2 -2
- data/lib/softcover/template/{book.yml.erb → config/book.yml.erb} +0 -1
- data/lib/softcover/template/config/marketing.yml +71 -0
- data/lib/softcover/template/html/stylesheets/custom.css +15 -0
- data/lib/softcover/template/images/cover-web.png +0 -0
- data/lib/softcover/template/{custom.sty → latex_styles/custom.sty} +0 -0
- data/lib/softcover/template/{framed.sty → latex_styles/framed.sty} +0 -0
- data/lib/softcover/template/{softcover.sty → latex_styles/softcover.sty} +6 -6
- data/lib/softcover/template/{upquote.sty → latex_styles/upquote.sty} +0 -0
- data/lib/softcover/template/screencasts/.gitkeep +0 -0
- data/lib/softcover/uploader.rb +9 -3
- data/lib/softcover/utils.rb +5 -4
- data/lib/softcover/version.rb +1 -1
- data/softcover.gemspec +1 -1
- data/spec/app_spec.rb +12 -1
- data/spec/book_manifest_spec.rb +0 -1
- data/spec/book_spec.rb +24 -16
- data/spec/builders/html_spec.rb +17 -3
- data/spec/builders/pdf_spec.rb +10 -2
- data/spec/commands/generator_spec.rb +8 -2
- data/spec/webmock_helpers.rb +5 -2
- metadata +20 -10
- data/lib/softcover/template/polytexnic_commands.sty +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e55cdffedc838f8932586db5eff983d9a84dd4b
|
4
|
+
data.tar.gz: fc341b0355f009345ef895b9d57a24ed9a651412
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 050cf03897d867223e98e3ff8b49b1efffb4984e7241a5bcd73cc53b0171fc50ea5de1ab3481ed546c53054f7a677146201f8a30e62ab69752af13addb846256
|
7
|
+
data.tar.gz: a81b24fe60937288477896740a7bd5eb11b9dc50aed52728d771bdfedde29d013410fda4944c42784632dd6e13dd45324d1734793721cbea7bfa5f5731ece8be
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
data/Gemfile
CHANGED
data/lib/softcover.rb
CHANGED
@@ -4,6 +4,7 @@ require 'active_support/core_ext/string'
|
|
4
4
|
require_relative 'softcover/formats'
|
5
5
|
require_relative 'softcover/utils'
|
6
6
|
require_relative 'softcover/output'
|
7
|
+
require_relative 'softcover/directories'
|
7
8
|
|
8
9
|
profile = false
|
9
10
|
if profile
|
@@ -41,7 +42,7 @@ module Softcover
|
|
41
42
|
|
42
43
|
# Return the custom styles, if any.
|
43
44
|
def custom_styles
|
44
|
-
custom_file = 'custom.sty'
|
45
|
+
custom_file = File.join(Softcover::Directories::STYLES, 'custom.sty')
|
45
46
|
File.exist?(custom_file) ? File.read(custom_file) : ''
|
46
47
|
end
|
47
48
|
|
data/lib/softcover/book.rb
CHANGED
@@ -11,6 +11,8 @@ class Softcover::Book
|
|
11
11
|
def initialize(options={})
|
12
12
|
require "softcover/client"
|
13
13
|
@manifest = Softcover::BookManifest.new(options)
|
14
|
+
@marketing = Softcover::MarketingManifest.new
|
15
|
+
|
14
16
|
@client = Softcover::Client.new_with_book self
|
15
17
|
|
16
18
|
@screencasts_dir = DEFAULT_SCREENCASTS_DIR
|
@@ -101,8 +103,11 @@ class Softcover::Book
|
|
101
103
|
slug: slug,
|
102
104
|
subtitle: subtitle,
|
103
105
|
description: description,
|
104
|
-
|
105
|
-
|
106
|
+
chapters: chapter_attributes,
|
107
|
+
prices: prices,
|
108
|
+
faq: faq,
|
109
|
+
testimonials: testimonials,
|
110
|
+
marketing_content: marketing_content
|
106
111
|
|
107
112
|
if res['errors']
|
108
113
|
@errors = res['errors']
|
@@ -166,7 +171,7 @@ class Softcover::Book
|
|
166
171
|
files_to_upload = find_screencasts.select do |file|
|
167
172
|
next false if @processed_screencasts.include?(file)
|
168
173
|
|
169
|
-
file.ready
|
174
|
+
file.ready?
|
170
175
|
end
|
171
176
|
|
172
177
|
upload_screencasts! files_to_upload
|
@@ -174,8 +179,13 @@ class Softcover::Book
|
|
174
179
|
@processed_screencasts += files_to_upload
|
175
180
|
end
|
176
181
|
|
182
|
+
SCREENCAST_FORMATS = %w{mov ogv mp4 webm}
|
183
|
+
|
177
184
|
def find_screencasts
|
178
|
-
|
185
|
+
formats = SCREENCAST_FORMATS * ','
|
186
|
+
Dir["#{@screencasts_dir}/**/*.{#{formats},zip}"].map do |path|
|
187
|
+
BookFile.new path
|
188
|
+
end
|
179
189
|
end
|
180
190
|
|
181
191
|
def upload_screencasts!(files)
|
@@ -196,6 +206,6 @@ class Softcover::Book
|
|
196
206
|
|
197
207
|
private
|
198
208
|
def method_missing(name, *args, &block)
|
199
|
-
@manifest.send(name) || super
|
209
|
+
@manifest.send(name) || @marketing.send(name) || super
|
200
210
|
end
|
201
211
|
end
|
@@ -3,6 +3,23 @@ require 'ostruct'
|
|
3
3
|
class Softcover::BookManifest < OpenStruct
|
4
4
|
include Softcover::Utils
|
5
5
|
|
6
|
+
class Softcover::MarketingManifest < Softcover::BookManifest
|
7
|
+
|
8
|
+
YAML_PATH = File.join(Softcover::Directories::CONFIG, 'marketing.yml')
|
9
|
+
def initialize
|
10
|
+
ensure_marketing_file
|
11
|
+
marshal_load read_from_yml.symbolize_keys!
|
12
|
+
end
|
13
|
+
|
14
|
+
# Ensures the existence of 'marketing.yml'.
|
15
|
+
# We copy from the template if necessary.
|
16
|
+
def ensure_marketing_file
|
17
|
+
template = File.join(File.dirname(__FILE__), 'template', YAML_PATH)
|
18
|
+
FileUtils.cp(template, YAML_PATH) unless File.exist?(YAML_PATH)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
6
23
|
class NotFound < StandardError
|
7
24
|
def message
|
8
25
|
"Invalid book directory, no manifest file found!"
|
@@ -10,9 +27,7 @@ class Softcover::BookManifest < OpenStruct
|
|
10
27
|
end
|
11
28
|
|
12
29
|
class Chapter < OpenStruct
|
13
|
-
|
14
|
-
File.join('chapters', slug + '.tex')
|
15
|
-
end
|
30
|
+
include Softcover::Utils
|
16
31
|
|
17
32
|
def fragment_name
|
18
33
|
"#{slug}_fragment.html"
|
@@ -49,13 +64,20 @@ class Softcover::BookManifest < OpenStruct
|
|
49
64
|
def full_name
|
50
65
|
"#{slug}#{extension}"
|
51
66
|
end
|
67
|
+
|
68
|
+
# Returns the name for the cached version of the chapters.
|
69
|
+
# This is used when processing Markdown to avoid unnecessary calls to
|
70
|
+
# kramdown's to_latex method, which can get expensive.
|
71
|
+
def cache_filename
|
72
|
+
Softcover::Utils.path("tmp/#{full_name}.cache")
|
73
|
+
end
|
52
74
|
end
|
53
75
|
|
54
76
|
class Section < OpenStruct
|
55
77
|
end
|
56
78
|
|
57
79
|
TXT_PATH = 'Book.txt'
|
58
|
-
YAML_PATH =
|
80
|
+
YAML_PATH = File.join(Softcover::Directories::CONFIG, 'book.yml')
|
59
81
|
|
60
82
|
def initialize(options = {})
|
61
83
|
@source = options[:source] || :polytex
|
@@ -225,6 +247,11 @@ class Softcover::BookManifest < OpenStruct
|
|
225
247
|
end
|
226
248
|
|
227
249
|
def self.valid_directory?
|
250
|
+
# Needed for backwards compatibility
|
251
|
+
if File.exist?('book.yml') && !Dir.pwd.include?('config')
|
252
|
+
Softcover::Utils.mkdir('config')
|
253
|
+
FileUtils.mv('book.yml', 'config')
|
254
|
+
end
|
228
255
|
[YAML_PATH, TXT_PATH].any? { |f| File.exist?(f) }
|
229
256
|
end
|
230
257
|
|
@@ -274,7 +301,19 @@ class Softcover::BookManifest < OpenStruct
|
|
274
301
|
require 'softcover/config'
|
275
302
|
require 'yaml/store'
|
276
303
|
self.class.find_book_root!
|
277
|
-
|
304
|
+
ensure_book_yml
|
305
|
+
YAML.load_file(self.class::YAML_PATH)
|
306
|
+
end
|
307
|
+
|
308
|
+
# Ensures that the book.yml file is in the right directory.
|
309
|
+
# This is for backwards compatibility.
|
310
|
+
def ensure_book_yml
|
311
|
+
path = self.class::YAML_PATH
|
312
|
+
unless File.exist?(path)
|
313
|
+
base = File.basename(path)
|
314
|
+
Softcover::Utils.mkdir Softcover::Directories::CONFIG
|
315
|
+
FileUtils.mv base, Softcover::Directories::CONFIG
|
316
|
+
end
|
278
317
|
end
|
279
318
|
|
280
319
|
|
data/lib/softcover/builder.rb
CHANGED
@@ -8,6 +8,7 @@ module Softcover
|
|
8
8
|
@manifest = Softcover::BookManifest.new(verify_paths: true,
|
9
9
|
source: source)
|
10
10
|
@built_files = []
|
11
|
+
ensure_style_file_locations
|
11
12
|
write_polytexnic_commands_file
|
12
13
|
end
|
13
14
|
|
@@ -24,9 +25,34 @@ module Softcover
|
|
24
25
|
def setup; end
|
25
26
|
def verify; end
|
26
27
|
|
28
|
+
# Ensures the style files are in the right location.
|
29
|
+
# This is for backwards compatibility.
|
30
|
+
def ensure_style_file_locations
|
31
|
+
styles_dir = Softcover::Directories::STYLES
|
32
|
+
mkdir styles_dir
|
33
|
+
fix_custom_include
|
34
|
+
files = Dir.glob('*.sty')
|
35
|
+
FileUtils.mv(files, styles_dir)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Fixes the custom include.
|
39
|
+
# The template includes the custom style file as an example
|
40
|
+
# of file inclusion. Unfortunately, the location of 'custom.sty', has
|
41
|
+
# changed, which will result in older templates spontaneously breaking.
|
42
|
+
def fix_custom_include
|
43
|
+
first_chapter = File.join('chapters', 'a_chapter.tex')
|
44
|
+
if File.exist?(first_chapter)
|
45
|
+
text = File.read(first_chapter)
|
46
|
+
text.gsub!('<<(custom.sty',
|
47
|
+
"<<(#{Softcover::Directories::STYLES}/custom.sty" )
|
48
|
+
File.write(first_chapter, text)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
27
52
|
# Writes out the PolyTeXnic commands from polytexnic.
|
28
53
|
def write_polytexnic_commands_file
|
29
|
-
|
54
|
+
styles_dir = File.join(Dir.pwd, Softcover::Directories::STYLES)
|
55
|
+
Polytexnic.write_polytexnic_style_file(styles_dir)
|
30
56
|
end
|
31
57
|
end
|
32
58
|
end
|
@@ -5,7 +5,7 @@ module Softcover
|
|
5
5
|
|
6
6
|
def build!(options={})
|
7
7
|
@preview = options[:preview]
|
8
|
-
Softcover::Builders::Html.new.build!
|
8
|
+
Softcover::Builders::Html.new.build!
|
9
9
|
if manifest.markdown?
|
10
10
|
self.manifest = Softcover::BookManifest.new(source: :polytex,
|
11
11
|
origin: :markdown)
|
@@ -32,7 +32,7 @@ module Softcover
|
|
32
32
|
# Removes HTML.
|
33
33
|
# All the HTML is generated, so this clears out any unused files.
|
34
34
|
def remove_html
|
35
|
-
FileUtils.rm(Dir.glob(path('epub/OEBPS
|
35
|
+
FileUtils.rm(Dir.glob(path('epub/OEBPS/*.html')))
|
36
36
|
end
|
37
37
|
|
38
38
|
def create_directories
|
@@ -218,17 +218,24 @@ module Softcover
|
|
218
218
|
epub_styles = File.join('epub', 'OEBPS', 'styles')
|
219
219
|
|
220
220
|
FileUtils.cp(File.join(html_styles, 'pygments.css'), epub_styles)
|
221
|
+
File.write(File.join(epub_styles, 'softcover.css'),
|
222
|
+
clean_book_id(path("#{html_styles}/softcover.css")))
|
221
223
|
|
222
224
|
# Copy over the EPUB-specific CSS.
|
223
225
|
template_dir = File.join(File.dirname(__FILE__), '..', 'template')
|
224
|
-
epub_css
|
226
|
+
epub_css = File.join(template_dir, epub_styles, 'epub.css')
|
225
227
|
FileUtils.cp(epub_css, epub_styles)
|
226
228
|
|
227
|
-
#
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
229
|
+
# Copy over custom CSS.
|
230
|
+
File.write(File.join(epub_styles, 'custom.css'),
|
231
|
+
clean_book_id(path("#{html_styles}/custom.css")))
|
232
|
+
end
|
233
|
+
|
234
|
+
# Removes the '#book' CSS id.
|
235
|
+
# For some reason, EPUB books hate the #book ids in the stylesheet
|
236
|
+
# (i.e., such books fail to validate), so remove them.
|
237
|
+
def clean_book_id(filename)
|
238
|
+
File.read(filename).gsub(/#book/, '')
|
232
239
|
end
|
233
240
|
|
234
241
|
# Copies the image files from the HTML version of the document.
|
@@ -334,6 +341,7 @@ module Softcover
|
|
334
341
|
<item id="pygments.css" href="styles/pygments.css" media-type="text/css"/>
|
335
342
|
<item id="softcover.css" href="styles/softcover.css" media-type="text/css"/>
|
336
343
|
<item id="epub.css" href="styles/epub.css" media-type="text/css"/>
|
344
|
+
<item id="custom.css" href="styles/custom.css" media-type="text/css"/>
|
337
345
|
<item id="cover" href="cover.html" media-type="application/xhtml+xml"/>
|
338
346
|
#{man_ch.join("\n")}
|
339
347
|
#{images.join("\n")}
|
@@ -431,6 +439,7 @@ module Softcover
|
|
431
439
|
<link rel="stylesheet" href="styles/pygments.css" type="text/css" />
|
432
440
|
<link rel="stylesheet" href="styles/softcover.css" type="text/css" />
|
433
441
|
<link rel="stylesheet" href="styles/epub.css" type="text/css" />
|
442
|
+
<link rel="stylesheet" href="styles/custom.css" type="text/css"/>
|
434
443
|
<link rel="stylesheet" type="application/vnd.adobe-page-template+xml" href="styles/page-template.xpgt" />
|
435
444
|
</head>
|
436
445
|
|
@@ -7,9 +7,14 @@ module Softcover
|
|
7
7
|
|
8
8
|
def setup
|
9
9
|
Dir.mkdir "html" unless File.directory?("html")
|
10
|
-
|
11
|
-
|
10
|
+
html_styles = path('html/stylesheets')
|
11
|
+
unless File.directory?(html_styles)
|
12
|
+
Dir.mkdir html_styles
|
12
13
|
end
|
14
|
+
template_dir = path("#{File.dirname(__FILE__)}/../template")
|
15
|
+
custom_css = path("#{template_dir}/html/stylesheets/custom.css")
|
16
|
+
target = path("#{html_styles}/custom.css")
|
17
|
+
FileUtils.cp(custom_css, target) unless File.exist?(target)
|
13
18
|
clean!
|
14
19
|
end
|
15
20
|
|
@@ -23,7 +28,7 @@ module Softcover
|
|
23
28
|
|
24
29
|
if manifest.markdown?
|
25
30
|
unless options[:'find-overfull']
|
26
|
-
|
31
|
+
remove_unneeded_polytex_files
|
27
32
|
end
|
28
33
|
manifest.chapters.each do |chapter|
|
29
34
|
write_latex_files(chapter, options)
|
@@ -40,7 +45,8 @@ module Softcover
|
|
40
45
|
@html = converted_html(basename)
|
41
46
|
@title = basename
|
42
47
|
erb_file = File.read(File.join(File.dirname(__FILE__),
|
43
|
-
'
|
48
|
+
'..', 'server', 'views',
|
49
|
+
'book.html.erb'))
|
44
50
|
file_content = ERB.new(erb_file).result(binding)
|
45
51
|
write_full_html_file(basename, file_content)
|
46
52
|
write_chapter_html_files(Nokogiri::HTML(file_content), erb_file)
|
@@ -55,20 +61,48 @@ module Softcover
|
|
55
61
|
true
|
56
62
|
end
|
57
63
|
|
64
|
+
# Removes any PolyTeX files not corresponding to current MD chapters.
|
65
|
+
def remove_unneeded_polytex_files
|
66
|
+
files_to_keep = manifest.chapters.map do |chapter|
|
67
|
+
path("#{manifest.polytex_dir}/#{chapter.slug}.tex")
|
68
|
+
end
|
69
|
+
all_files = Dir.glob(path("#{manifest.polytex_dir}/*.tex"))
|
70
|
+
files_to_remove = all_files - files_to_keep
|
71
|
+
FileUtils.rm(files_to_remove)
|
72
|
+
end
|
73
|
+
|
58
74
|
# Writes the LaTeX files for a given Markdown chapter.
|
59
75
|
def write_latex_files(chapter, options = {})
|
60
|
-
|
76
|
+
polytex_filename = path("#{manifest.polytex_dir}/#{chapter.slug}.tex")
|
61
77
|
if chapter.source == :polytex
|
62
|
-
FileUtils.cp path("chapters/#{chapter.full_name}"),
|
78
|
+
FileUtils.cp path("chapters/#{chapter.full_name}"), polytex_filename
|
63
79
|
else
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
File.
|
80
|
+
mkdir Softcover::Directories::TMP
|
81
|
+
markdown = File.read(path("chapters/#{chapter.full_name}"))
|
82
|
+
# Only write if the Markdown file hasn't changed since the last time
|
83
|
+
# it was converted, as then the current PolyTeX file is up-to-date.
|
84
|
+
# The call to File.exist?(filename) is just in case the PolyTeX file
|
85
|
+
# corresponding to the Markdown file was removed by hand in the
|
86
|
+
# interim.
|
87
|
+
unless (File.exist?(chapter.cache_filename) &&
|
88
|
+
File.read(chapter.cache_filename) == digest(markdown) &&
|
89
|
+
File.exist?(polytex_filename))
|
90
|
+
File.write(polytex_filename, polytex(chapter, markdown))
|
91
|
+
end
|
69
92
|
end
|
70
93
|
end
|
71
94
|
|
95
|
+
# Returns the PolyTeX for the chapter.
|
96
|
+
# As a side-effect, we cache a digest of the Markdown to prevent
|
97
|
+
# unnecessary conversions.
|
98
|
+
def polytex(chapter, markdown)
|
99
|
+
File.write(chapter.cache_filename, digest(markdown))
|
100
|
+
p = Polytexnic::Pipeline.new(markdown,
|
101
|
+
source: :markdown,
|
102
|
+
custom_commands: Softcover.custom_styles)
|
103
|
+
p.polytex
|
104
|
+
end
|
105
|
+
|
72
106
|
# Returns the converted HTML.
|
73
107
|
def converted_html(basename)
|
74
108
|
polytex_filename = basename + '.tex'
|
@@ -152,7 +186,12 @@ module Softcover
|
|
152
186
|
target = target_cache[ref_id]
|
153
187
|
unless target.nil?
|
154
188
|
id = target['id']
|
155
|
-
ref_chapter =
|
189
|
+
ref_chapter = if target['data-tralics-id'].nil?
|
190
|
+
# This branch is true for chapter-star.
|
191
|
+
chapter
|
192
|
+
else
|
193
|
+
ref_map[target['data-tralics-id']]
|
194
|
+
end
|
156
195
|
ref_node['href'] = "#{ref_chapter.fragment_name}##{id}"
|
157
196
|
end
|
158
197
|
end
|
@@ -28,18 +28,16 @@ module Softcover
|
|
28
28
|
|
29
29
|
polytex_filenames = manifest.pdf_chapter_filenames << book_filename
|
30
30
|
polytex_filenames.each do |filename|
|
31
|
-
polytex = File.
|
31
|
+
polytex = File.read(filename)
|
32
32
|
latex = Polytexnic::Pipeline.new(polytex).to_latex
|
33
33
|
if filename == book_filename
|
34
34
|
latex.gsub!(/\\include{(.*?)}/) do
|
35
35
|
"\\include{#{Softcover::Utils.tmpify(manifest, $1)}.tmp}"
|
36
36
|
end
|
37
37
|
end
|
38
|
-
File.
|
39
|
-
f.write(latex)
|
40
|
-
end
|
38
|
+
File.write(Softcover::Utils.tmpify(manifest, filename), latex)
|
41
39
|
end
|
42
|
-
write_pygments_file(:latex)
|
40
|
+
write_pygments_file(:latex, Softcover::Directories::STYLES)
|
43
41
|
copy_polytexnic_sty
|
44
42
|
|
45
43
|
# Renaming the PDF in the command is necessary because `execute`
|
@@ -48,7 +46,8 @@ module Softcover
|
|
48
46
|
# is ignored.
|
49
47
|
# (The reason for using `exec` is so that LaTeX errors get emitted to
|
50
48
|
# the screen rather than just hanging the process.)
|
51
|
-
cmd = "#{pdf_cmd(book_filename, options)}
|
49
|
+
cmd = "#{pdf_cmd(book_filename, options)} " +
|
50
|
+
"; #{rename_pdf(basename, options)}"
|
52
51
|
# Here we use `system` when making a preview because the preview command
|
53
52
|
# needs to run after the main PDF build.
|
54
53
|
if options[:quiet] || options[:silent]
|
@@ -106,19 +105,22 @@ module Softcover
|
|
106
105
|
# The purpose is to match the original filename.
|
107
106
|
# For example, foo_bar.tex should produce foo_bar.pdf.
|
108
107
|
# While we're at it, we move it to the standard ebooks/ directory.
|
109
|
-
def rename_pdf(basename)
|
108
|
+
def rename_pdf(basename, options={})
|
110
109
|
tmp_pdf = basename + '.tmp.pdf'
|
111
110
|
pdf = basename + '.pdf'
|
112
111
|
mkdir('ebooks')
|
113
|
-
|
112
|
+
# Remove the intermediate tmp files unless only running once.
|
113
|
+
rm_tmp = options[:once] || Softcover.test? ? "" : "&& rm -f *.tmp.*"
|
114
|
+
"mv -f #{tmp_pdf} #{File.join('ebooks', pdf)} #{rm_tmp}"
|
114
115
|
end
|
115
116
|
|
116
|
-
# Copies the
|
117
|
+
# Copies the style file to ensure it's always fresh.
|
117
118
|
def copy_polytexnic_sty
|
118
|
-
|
119
|
+
softcover_sty = File.join(Softcover::Directories::STYLES,
|
120
|
+
'softcover.sty')
|
119
121
|
source_sty = File.join(File.dirname(__FILE__),
|
120
|
-
|
121
|
-
FileUtils.cp source_sty,
|
122
|
+
'..', 'template', softcover_sty)
|
123
|
+
FileUtils.cp source_sty, softcover_sty
|
122
124
|
end
|
123
125
|
end
|
124
126
|
end
|
data/lib/softcover/cli.rb
CHANGED
@@ -133,6 +133,7 @@ module Softcover
|
|
133
133
|
# TODO: make screencasts dir .book configurable
|
134
134
|
define_method "publish:screencasts" do |dir=
|
135
135
|
Softcover::Book::DEFAULT_SCREENCASTS_DIR|
|
136
|
+
require 'softcover/commands/publisher'
|
136
137
|
|
137
138
|
puts "Publishing screencasts in #{dir}"
|
138
139
|
Softcover::Commands::Publisher.
|
@@ -40,7 +40,8 @@ module Softcover
|
|
40
40
|
if path =~ /book\.tex/
|
41
41
|
cp_path = "#{name}.tex"
|
42
42
|
elsif path =~ /\.erb/
|
43
|
-
cp_path = File.
|
43
|
+
cp_path = File.join(File.dirname(cp_path),
|
44
|
+
File.basename(path.dup, '.erb'))
|
44
45
|
elsif path =~ /gitignore/
|
45
46
|
cp_path = '.gitignore'
|
46
47
|
end
|
@@ -77,11 +78,12 @@ module Softcover
|
|
77
78
|
File.symlink("../images", "images")
|
78
79
|
|
79
80
|
Dir.chdir "../.."
|
80
|
-
|
81
|
+
book_yml = File.join(Softcover::Directories::CONFIG, 'book')
|
82
|
+
puts "Done. Please update #{book_yml}"
|
81
83
|
end
|
82
84
|
|
83
85
|
def template_dir
|
84
|
-
File.expand_path File.join File.dirname(__FILE__), "
|
86
|
+
File.expand_path File.join File.dirname(__FILE__), "..", "template"
|
85
87
|
end
|
86
88
|
|
87
89
|
# Returns a list of all the files and directories used to build the book.
|
@@ -36,6 +36,9 @@ module Softcover::Commands::Publisher
|
|
36
36
|
def publish_screencasts!(options={})
|
37
37
|
return false unless current_book
|
38
38
|
|
39
|
+
require 'ruby-progressbar'
|
40
|
+
require 'curb'
|
41
|
+
|
39
42
|
current_book.screencasts_dir = options[:dir] ||
|
40
43
|
Softcover::Book::DEFAULT_SCREENCASTS_DIR
|
41
44
|
|
@@ -10,7 +10,7 @@ module Softcover::Commands::Server
|
|
10
10
|
def listen_for_changes
|
11
11
|
return if defined?(@no_listener) && @no_listener
|
12
12
|
server_pid = Process.pid
|
13
|
-
filter_regex = /(\.md|\.tex|custom\.sty|Book\.txt|book\.yml)$/
|
13
|
+
filter_regex = /(\.md|\.tex|custom\.sty|custom\.css|Book\.txt|book\.yml)$/
|
14
14
|
@listener = Listen.to('.')
|
15
15
|
@listener.filter(filter_regex)
|
16
16
|
|
@@ -44,7 +44,7 @@ module Softcover::Commands::Server
|
|
44
44
|
'Building...'
|
45
45
|
t = Time.now
|
46
46
|
builder = Softcover::Builders::Html.new
|
47
|
-
builder.build
|
47
|
+
builder.build
|
48
48
|
puts "Done. (#{(Time.now - t).round(2)}s)"
|
49
49
|
|
50
50
|
rescue Softcover::BookManifest::NotFound => e
|
data/lib/softcover/server/app.rb
CHANGED
@@ -5,7 +5,7 @@ require 'sinatra/async'
|
|
5
5
|
class Softcover::App < Sinatra::Base
|
6
6
|
register Sinatra::Async
|
7
7
|
|
8
|
-
set :public_folder,
|
8
|
+
set :public_folder, 'html'
|
9
9
|
set :bind, '0.0.0.0'
|
10
10
|
|
11
11
|
configure do
|
@@ -28,30 +28,6 @@ class Softcover::App < Sinatra::Base
|
|
28
28
|
coffee erb :'main.js'
|
29
29
|
end
|
30
30
|
|
31
|
-
get '/stylesheets/pygments.css' do
|
32
|
-
content_type 'text/css'
|
33
|
-
@pygments_css ||= Pygments.send(:mentos, :css, ['html', '']).
|
34
|
-
gsub!(/^/, '.highlight ')
|
35
|
-
end
|
36
|
-
|
37
|
-
# Gets the image specified by the path and content type.
|
38
|
-
get '/images/*' do |path|
|
39
|
-
split_path = path.split(/\./)
|
40
|
-
extension = split_path.pop
|
41
|
-
path = split_path * ''
|
42
|
-
# Arrange to handle both '.jpeg' and '.jpg' extensions.
|
43
|
-
if extension == 'jpeg' && !File.exist?(image_filename(path, extension))
|
44
|
-
extension = 'jpg'
|
45
|
-
end
|
46
|
-
file_path = image_filename(path, extension)
|
47
|
-
if File.exists?(file_path)
|
48
|
-
content_type extension
|
49
|
-
File.read(file_path)
|
50
|
-
else
|
51
|
-
raise Sinatra::NotFound
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
31
|
get '/assets/:path' do
|
56
32
|
extension = params[:path].split('.').last
|
57
33
|
content_type extension
|
@@ -4,6 +4,7 @@
|
|
4
4
|
<meta charset="UTF-8">
|
5
5
|
<link href="stylesheets/pygments.css" media="screen" rel="stylesheet" type="text/css" />
|
6
6
|
<link href="stylesheets/softcover.css" media="screen" rel="stylesheet" type="text/css" />
|
7
|
+
<link href="stylesheets/custom.css" media="screen" rel="stylesheet" type="text/css" />
|
7
8
|
<% if @local_server %>
|
8
9
|
<script src="/jquery/1.10.2/jquery-1.10.2.js" ></script>
|
9
10
|
<link href="assets/main.css" media="screen" rel="stylesheet" type="text/css" />
|
@@ -52,8 +52,8 @@ current\_\-user
|
|
52
52
|
|
53
53
|
\begin{codelisting}
|
54
54
|
\label{code:custom}
|
55
|
-
\codecaption{Defining custom commands. \\ \filepath{custom.sty}}
|
56
|
-
%= <<(custom.sty, lang: tex)
|
55
|
+
\codecaption{Defining custom commands. \\ \filepath{latex\_styles/custom.sty}}
|
56
|
+
%= <<(latex_styles/custom.sty, lang: tex)
|
57
57
|
\end{codelisting}
|
58
58
|
|
59
59
|
Listing~\ref{code:hyphenation} also shows how to escape the underscore character using a backslash. This is necessary because plain underscores are reserved for math environments (Section~\ref{sec:mathematics}).
|
@@ -0,0 +1,71 @@
|
|
1
|
+
---
|
2
|
+
prices:
|
3
|
+
-
|
4
|
+
code: ebooks
|
5
|
+
name: "HTML & Ebook"
|
6
|
+
description:
|
7
|
+
|
|
8
|
+
Optimized for Kindle* and iPad
|
9
|
+
Almost 9000 pages of content
|
10
|
+
Includes a free copy of 1st Edition PDF
|
11
|
+
media:
|
12
|
+
- html
|
13
|
+
- pdf
|
14
|
+
- epub
|
15
|
+
- mobi
|
16
|
+
price: 3500
|
17
|
+
|
18
|
+
-
|
19
|
+
code: screencasts
|
20
|
+
name: "HTML & Screencasts"
|
21
|
+
description:
|
22
|
+
|
|
23
|
+
Full updated for the 2nd edition
|
24
|
+
100% DRM-free digital downloads
|
25
|
+
(QuickTime and Ogg Vorbis)
|
26
|
+
Includes first edition screencasts
|
27
|
+
media:
|
28
|
+
- html
|
29
|
+
- screencasts
|
30
|
+
price: 12500
|
31
|
+
|
32
|
+
-
|
33
|
+
code: all
|
34
|
+
name: "HTML, Ebook, and Screencasts"
|
35
|
+
description:
|
36
|
+
|
|
37
|
+
Includes all 50 screencasts
|
38
|
+
eBook formats for Kindle, Nook, and PDF
|
39
|
+
Read online.
|
40
|
+
media:
|
41
|
+
- html
|
42
|
+
- pdf
|
43
|
+
- epub
|
44
|
+
- mobi
|
45
|
+
- screencasts
|
46
|
+
price: 12500
|
47
|
+
regular_price: 19900
|
48
|
+
|
49
|
+
faq:
|
50
|
+
-
|
51
|
+
question: "Question 1 text"
|
52
|
+
answer: "Answer 1 text"
|
53
|
+
|
54
|
+
-
|
55
|
+
question: "Question 2 text"
|
56
|
+
answer: "Answer 2 text"
|
57
|
+
|
58
|
+
testimonials:
|
59
|
+
-
|
60
|
+
name: "Person 1"
|
61
|
+
title: "Person 1 Title"
|
62
|
+
image: /images/testimonial_1.png
|
63
|
+
text: "Testimonial 1 text"
|
64
|
+
|
65
|
+
-
|
66
|
+
name: "Person 2"
|
67
|
+
title: "Person 2 Title"
|
68
|
+
gravatar_email: "info@softcover.io"
|
69
|
+
text: "Testimonial 2 text"
|
70
|
+
|
71
|
+
marketing_content: ''
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/* Place custom styles here, scoped by the CSS id '#book' */
|
2
|
+
/* To sync up PDF styles, edit custom.sty */
|
3
|
+
/* Google for "LaTeX style files" to learn how to use custom.sty */
|
4
|
+
|
5
|
+
/*
|
6
|
+
|
7
|
+
body #book {
|
8
|
+
background: green;
|
9
|
+
}
|
10
|
+
|
11
|
+
#book p {
|
12
|
+
color: purple;
|
13
|
+
}
|
14
|
+
|
15
|
+
*/
|
Binary file
|
File without changes
|
File without changes
|
@@ -19,7 +19,7 @@
|
|
19
19
|
\usepackage{graphicx}
|
20
20
|
\def\maxwidth#1{\ifdim\Gin@nat@width>#1 #1\else\Gin@nat@width\fi}
|
21
21
|
% Commands included by PolyTeXnic
|
22
|
-
\usepackage{polytexnic_commands}
|
22
|
+
\usepackage{latex_styles/polytexnic_commands}
|
23
23
|
% Links
|
24
24
|
\definecolor{darkblue}{rgb}{0,0.18,0.45}
|
25
25
|
\definecolor{darkgreen}{rgb}{0,0.39,0}
|
@@ -32,7 +32,7 @@
|
|
32
32
|
\hypersetup{hyperfootnotes=false}
|
33
33
|
\hypersetup{colorlinks,linkcolor=darkblue,urlcolor=blue}
|
34
34
|
% Syntax highlighting
|
35
|
-
\usepackage{pygments}
|
35
|
+
\usepackage{latex_styles/pygments}
|
36
36
|
% Change color of '@go', "general output", from gray to dark green.
|
37
37
|
\expandafter\def\csname PY@tok@go\endcsname{\def\PY@tc##1{\textcolor{darkgreen}{##1}}}
|
38
38
|
% American Mathematical Society extensions
|
@@ -71,7 +71,7 @@
|
|
71
71
|
% Use a nice font in code environments.
|
72
72
|
\usepackage[scaled=0.92]{helvet}
|
73
73
|
% Fix quotes in code environments
|
74
|
-
\usepackage{upquote}
|
74
|
+
\usepackage{latex_styles/upquote}
|
75
75
|
|
76
76
|
% Filesystem paths
|
77
77
|
\newcommand{\filepath}[1]{\texttt{\small #1}}
|
@@ -125,7 +125,7 @@
|
|
125
125
|
\usepackage{amsthm}
|
126
126
|
\theoremstyle{definition}
|
127
127
|
\newtheorem{aside}{Box}[chapter]
|
128
|
-
\usepackage{framed}
|
128
|
+
\usepackage{latex_styles/framed}
|
129
129
|
\definecolor{shadecolor}{gray}{0.97}
|
130
130
|
\definecolor{boxcolor}{gray}{0.10}
|
131
131
|
\newenvironment{shaded_aside}[2]{\begin{full_framed_shaded}\begin{aside}\label{#2} \textbf{#1}\end{aside}}{\bigskip\end{full_framed_shaded}}
|
@@ -143,6 +143,6 @@
|
|
143
143
|
\vskip0.5em}%
|
144
144
|
}
|
145
145
|
|
146
|
-
% Add custom commands
|
147
|
-
\usepackage{custom}
|
146
|
+
% Add custom commands.
|
147
|
+
\usepackage{latex_styles/custom}
|
148
148
|
|
File without changes
|
File without changes
|
data/lib/softcover/uploader.rb
CHANGED
@@ -35,9 +35,15 @@ module Softcover
|
|
35
35
|
last_chunk = 0
|
36
36
|
c.on_progress do |_, _, ul_total, ul_now|
|
37
37
|
uploaded = ul_now > size ? size : ul_now
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
x = as_size(uploaded)
|
39
|
+
y = as_size(size)
|
40
|
+
x = y if x > y
|
41
|
+
begin
|
42
|
+
bar.send(:title=, "#{path} (#{x} / #{y})")
|
43
|
+
bar.progress += ul_now - last_chunk
|
44
|
+
rescue
|
45
|
+
nil
|
46
|
+
end
|
41
47
|
last_chunk = ul_now
|
42
48
|
true
|
43
49
|
end
|
data/lib/softcover/utils.rb
CHANGED
@@ -110,7 +110,7 @@ module Softcover::Utils
|
|
110
110
|
subtitle = manifest.subtitle.nil? ? "" : "\\subtitle{#{manifest.subtitle}}"
|
111
111
|
<<-EOS
|
112
112
|
\\documentclass[14pt]{extbook}
|
113
|
-
\\usepackage{softcover}
|
113
|
+
\\usepackage{#{Softcover::Directories::STYLES}/softcover}
|
114
114
|
\\VerbatimFootnotes % Allows verbatim text in footnotes
|
115
115
|
\\title{#{manifest.title}}
|
116
116
|
#{subtitle}
|
@@ -124,16 +124,17 @@ module Softcover::Utils
|
|
124
124
|
# Returns the tmp version of a filename.
|
125
125
|
# E.g., tmpify('foo.tex') => 'foo.tmp.tex'
|
126
126
|
def tmpify(manifest, filename)
|
127
|
-
|
127
|
+
tmp = Softcover::Directories::TMP
|
128
|
+
mkdir tmp
|
128
129
|
sep = File::SEPARATOR
|
129
|
-
filename.sub(manifest.polytex_dir + sep,
|
130
|
+
filename.sub(manifest.polytex_dir + sep, tmp + sep).
|
130
131
|
sub('.tex', '.tmp.tex')
|
131
132
|
end
|
132
133
|
|
133
134
|
# Writes a Pygments style file.
|
134
135
|
# We support both :html (outputting CSS) and :latex (outputting
|
135
136
|
# a LaTeX style file).
|
136
|
-
def write_pygments_file(format, path
|
137
|
+
def write_pygments_file(format, path)
|
137
138
|
require 'pygments'
|
138
139
|
extension = case format
|
139
140
|
when :html
|
data/lib/softcover/version.rb
CHANGED
data/softcover.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
-
gem.add_dependency 'polytexnic', '~> 0.
|
21
|
+
gem.add_dependency 'polytexnic', '~> 0.8.0'
|
22
22
|
gem.add_dependency 'msgpack', '~> 0.4.2'
|
23
23
|
gem.add_dependency 'nokogiri', '~> 1.6.0'
|
24
24
|
gem.add_dependency 'thor'
|
data/spec/app_spec.rb
CHANGED
@@ -13,7 +13,7 @@ describe Softcover::App do
|
|
13
13
|
generate_book
|
14
14
|
Softcover::Builders::Html.new.build!
|
15
15
|
end
|
16
|
-
after(:all) { remove_book }
|
16
|
+
# after(:all) { remove_book }
|
17
17
|
|
18
18
|
before { chdir_to_book }
|
19
19
|
|
@@ -45,11 +45,22 @@ describe Softcover::App do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
describe 'serving files' do
|
48
|
+
|
48
49
|
it 'GET pygments.css' do
|
49
50
|
get '/stylesheets/pygments.css'
|
50
51
|
expect_server_response_of_type 'text/css'
|
51
52
|
end
|
52
53
|
|
54
|
+
it 'GET softcover.css' do
|
55
|
+
get '/stylesheets/softcover.css'
|
56
|
+
expect_server_response_of_type 'text/css'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'GET custom.css' do
|
60
|
+
get '/stylesheets/custom.css'
|
61
|
+
expect_server_response_of_type 'text/css'
|
62
|
+
end
|
63
|
+
|
53
64
|
it 'GET main.js' do
|
54
65
|
get '/main.js'
|
55
66
|
expect_server_response_of_type 'application/javascript'
|
data/spec/book_manifest_spec.rb
CHANGED
@@ -12,7 +12,6 @@ describe Softcover::BookManifest do
|
|
12
12
|
its(:title) { should eq "Title of the Book" }
|
13
13
|
its(:subtitle) { should eq "Change me" }
|
14
14
|
its(:description) { should eq "Change me." }
|
15
|
-
its(:cover) { should eq "images/cover.png" }
|
16
15
|
its(:author) { should eq "Author Name" }
|
17
16
|
end
|
18
17
|
|
data/spec/book_spec.rb
CHANGED
@@ -6,28 +6,36 @@ describe Softcover::Book do
|
|
6
6
|
before(:all) { generate_book(id: 1) }
|
7
7
|
after(:all) { remove_book }
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
describe "reading from book.yml" do
|
10
|
+
its(:filenames) { should_not include "html/test-book.html"}
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
its(:filenames) { should include "html/chapter-1_fragment.html"}
|
13
|
+
its(:filenames) { should_not include "html/chapter-1.html"}
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
its(:filenames) { should include "ebooks/test-book.mobi"}
|
16
|
+
its(:filenames) { should include "ebooks/test-book.epub"}
|
17
|
+
its(:filenames) { should include "ebooks/test-book.pdf"}
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
its(:slug) { should eq "book" }
|
20
|
+
its(:url) { should match /\/books\/(.*?)\/redirect/ }
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
it "sets chapter attributes" do
|
23
|
+
expect(subject.chapter_attributes.first[:menu_heading]).
|
24
|
+
to match /Frontmatter/
|
25
|
+
end
|
26
|
+
|
27
|
+
it "has rendered latex in menu_heading" do
|
28
|
+
expect(subject.chapter_attributes.last[:menu_heading]).
|
29
|
+
to match /<em>/
|
30
|
+
end
|
25
31
|
end
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
|
33
|
+
describe "reading from marketing.yml" do
|
34
|
+
its(:prices) { should_not be_empty }
|
35
|
+
its(:faq) { should_not be_empty }
|
36
|
+
its(:testimonials) { should_not be_empty }
|
37
|
+
its(:marketing_content) { should be_empty }
|
30
38
|
end
|
31
39
|
end
|
32
40
|
end
|
33
|
-
end
|
41
|
+
end
|
data/spec/builders/html_spec.rb
CHANGED
@@ -29,6 +29,16 @@ describe Softcover::Builders::Html do
|
|
29
29
|
it { should match('pygments.css') }
|
30
30
|
context "HTML document" do
|
31
31
|
subject(:doc) { Nokogiri::HTML(output) }
|
32
|
+
|
33
|
+
context "frontmatter" do
|
34
|
+
subject(:frontmatter) { doc.at_css('#frontmatter') }
|
35
|
+
it { should_not be_nil }
|
36
|
+
it "should link the preface to the frontmatter page" do
|
37
|
+
link = '<a href="#preface"'
|
38
|
+
expect(frontmatter.to_xhtml).to match /#{link}/
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
32
42
|
context "first chapter" do
|
33
43
|
subject(:chapter) { doc.at_css('#cha-a_chapter') }
|
34
44
|
it { should_not be_nil }
|
@@ -72,14 +82,14 @@ describe Softcover::Builders::Html do
|
|
72
82
|
end
|
73
83
|
|
74
84
|
describe "contents" do
|
75
|
-
subject(:
|
85
|
+
subject(:doc) { Nokogiri::HTML(File.open(filename)) }
|
76
86
|
|
77
87
|
it "should include the title page" do
|
78
|
-
expect(
|
88
|
+
expect(doc.at_css('div#title_page')).not_to be_nil
|
79
89
|
end
|
80
90
|
|
81
91
|
it "should include the table of contents" do
|
82
|
-
expect(
|
92
|
+
expect(doc.at_css('div#table_of_contents')).not_to be_nil
|
83
93
|
end
|
84
94
|
end
|
85
95
|
end
|
@@ -123,6 +133,10 @@ describe Softcover::Builders::Html do
|
|
123
133
|
expect(Dir.glob(path('generated_polytex/*.tex'))).not_to be_empty
|
124
134
|
end
|
125
135
|
|
136
|
+
it "should write cache files" do
|
137
|
+
expect(Dir.glob(path('tmp/*.cache'))).not_to be_empty
|
138
|
+
end
|
139
|
+
|
126
140
|
describe "master LaTeX file" do
|
127
141
|
let(:master_file) { builder.master_filename(builder.manifest) }
|
128
142
|
subject { File.read(master_file) }
|
data/spec/builders/pdf_spec.rb
CHANGED
@@ -24,6 +24,11 @@ describe Softcover::Builders::Pdf do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
it "should prepend the fontsize verbatim declaration for source code" do
|
28
|
+
fontsize = '\begin{Verbatim}[fontsize=\relsize'
|
29
|
+
expect(File.read(Dir.glob('tmp/*.tmp.tex').first)).to include fontsize
|
30
|
+
end
|
31
|
+
|
27
32
|
it "should replace the main file's \\includes with tmp files" do
|
28
33
|
contents = File.read(Softcover::Utils.tmpify(builder.manifest,
|
29
34
|
'book.tex'))
|
@@ -37,11 +42,14 @@ describe Softcover::Builders::Pdf do
|
|
37
42
|
end
|
38
43
|
|
39
44
|
it "should create a Pygments style file" do
|
40
|
-
|
45
|
+
pygments = File.join(Softcover::Directories::STYLES, 'pygments.sty')
|
46
|
+
expect(pygments).to exist
|
41
47
|
end
|
42
48
|
|
43
49
|
it "should write the correct PolyTeXnic commands file" do
|
44
|
-
|
50
|
+
styles = File.join(Softcover::Directories::STYLES,
|
51
|
+
'polytexnic_commands.sty')
|
52
|
+
expect(File.read(styles)).to match /newcommand/
|
45
53
|
end
|
46
54
|
|
47
55
|
context "after removing Book.txt" do
|
@@ -26,7 +26,7 @@ describe Softcover::Commands::Generator do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
describe "book.yml" do
|
29
|
-
subject(:yml) { YAML.load_file(File.join name, 'book.yml') }
|
29
|
+
subject(:yml) { YAML.load_file(File.join name, 'config', 'book.yml') }
|
30
30
|
|
31
31
|
it "should have the right title" do
|
32
32
|
expect(yml['title']).to eq "Title of the Book"
|
@@ -93,16 +93,22 @@ describe Softcover::Commands::Generator do
|
|
93
93
|
describe "CSS" do
|
94
94
|
|
95
95
|
let(:css_file) { 'html/stylesheets/softcover.css' }
|
96
|
+
let(:custom_css) { 'html/stylesheets/custom.css' }
|
96
97
|
|
97
98
|
it "should have the right CSS file" do
|
98
99
|
expect(css_file).to exist
|
99
100
|
end
|
101
|
+
|
102
|
+
it "should have a custom CSS file" do
|
103
|
+
expect(custom_css).to exist
|
104
|
+
end
|
100
105
|
end
|
101
106
|
|
102
107
|
describe "styles" do
|
103
108
|
|
104
109
|
it "should have a right style file" do
|
105
|
-
|
110
|
+
style = File.join(Softcover::Directories::STYLES, 'softcover.sty')
|
111
|
+
expect(style).to exist
|
106
112
|
end
|
107
113
|
end
|
108
114
|
|
data/spec/webmock_helpers.rb
CHANGED
@@ -59,8 +59,11 @@ module WebmockHelpers
|
|
59
59
|
slug: book.slug,
|
60
60
|
subtitle: book.subtitle,
|
61
61
|
description: book.description,
|
62
|
-
|
63
|
-
|
62
|
+
chapters: book.chapter_attributes,
|
63
|
+
prices: book.prices,
|
64
|
+
faq: book.faq,
|
65
|
+
testimonials: book.testimonials,
|
66
|
+
marketing_content: ''
|
64
67
|
}.to_json,
|
65
68
|
:headers => headers).
|
66
69
|
to_return(:status => 200, :body => return_body, :headers => {})
|
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: 0.
|
4
|
+
version: 0.8.0
|
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: 2013-12-
|
12
|
+
date: 2013-12-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: polytexnic
|
@@ -17,14 +17,14 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ~>
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.
|
20
|
+
version: 0.8.0
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - ~>
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.
|
27
|
+
version: 0.8.0
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: msgpack
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -374,6 +374,12 @@ files:
|
|
374
374
|
- .pull_requests/1386099285
|
375
375
|
- .pull_requests/1386115582
|
376
376
|
- .pull_requests/1386448492
|
377
|
+
- .pull_requests/1387399930
|
378
|
+
- .pull_requests/1387400263
|
379
|
+
- .pull_requests/1387592428
|
380
|
+
- .pull_requests/1387944330
|
381
|
+
- .pull_requests/1388094706
|
382
|
+
- .pull_requests/1388441218
|
377
383
|
- .rspec
|
378
384
|
- Gemfile
|
379
385
|
- LICENSE.txt
|
@@ -403,6 +409,7 @@ files:
|
|
403
409
|
- lib/softcover/commands/publisher.rb
|
404
410
|
- lib/softcover/commands/server.rb
|
405
411
|
- lib/softcover/config.rb
|
412
|
+
- lib/softcover/directories.rb
|
406
413
|
- lib/softcover/formats.rb
|
407
414
|
- lib/softcover/mathjax.rb
|
408
415
|
- lib/softcover/output.rb
|
@@ -419,7 +426,6 @@ files:
|
|
419
426
|
- lib/softcover/template/.softcover-deploy
|
420
427
|
- lib/softcover/template/Book.txt
|
421
428
|
- lib/softcover/template/README.md
|
422
|
-
- lib/softcover/template/book.yml.erb
|
423
429
|
- lib/softcover/template/chapters/a_chapter.md
|
424
430
|
- lib/softcover/template/chapters/a_chapter.tex
|
425
431
|
- lib/softcover/template/chapters/another_chapter.md
|
@@ -428,11 +434,11 @@ files:
|
|
428
434
|
- lib/softcover/template/chapters/preface.tex
|
429
435
|
- lib/softcover/template/chapters/yet_another_chapter.md
|
430
436
|
- lib/softcover/template/chapters/yet_another_chapter.tex
|
431
|
-
- lib/softcover/template/
|
437
|
+
- lib/softcover/template/config/book.yml.erb
|
438
|
+
- lib/softcover/template/config/marketing.yml
|
432
439
|
- lib/softcover/template/epub/OEBPS/styles/.gitkeep
|
433
440
|
- lib/softcover/template/epub/OEBPS/styles/epub.css
|
434
441
|
- lib/softcover/template/epub/OEBPS/styles/page-template.xpgt
|
435
|
-
- lib/softcover/template/framed.sty
|
436
442
|
- lib/softcover/template/gitignore
|
437
443
|
- lib/softcover/template/html/.gitkeep
|
438
444
|
- lib/softcover/template/html/MathJax/MathJax.js
|
@@ -973,15 +979,19 @@ files:
|
|
973
979
|
- lib/softcover/template/html/jquery/1.10.2/jquery-1.10.2.js
|
974
980
|
- lib/softcover/template/html/jquery/1.10.2/jquery-1.10.2.min.map
|
975
981
|
- lib/softcover/template/html/stylesheets/.gitkeep
|
982
|
+
- lib/softcover/template/html/stylesheets/custom.css
|
976
983
|
- lib/softcover/template/html/stylesheets/softcover.css
|
977
984
|
- lib/softcover/template/images/.gitkeep
|
978
985
|
- lib/softcover/template/images/2011_michael_hartl.png
|
986
|
+
- lib/softcover/template/images/cover-web.png
|
979
987
|
- lib/softcover/template/images/cover.pdf
|
980
988
|
- lib/softcover/template/images/cover.png
|
981
989
|
- lib/softcover/template/images/figures/.gitkeep
|
982
|
-
- lib/softcover/template/
|
983
|
-
- lib/softcover/template/
|
984
|
-
- lib/softcover/template/
|
990
|
+
- lib/softcover/template/latex_styles/custom.sty
|
991
|
+
- lib/softcover/template/latex_styles/framed.sty
|
992
|
+
- lib/softcover/template/latex_styles/softcover.sty
|
993
|
+
- lib/softcover/template/latex_styles/upquote.sty
|
994
|
+
- lib/softcover/template/screencasts/.gitkeep
|
985
995
|
- lib/softcover/uploader.rb
|
986
996
|
- lib/softcover/utils.rb
|
987
997
|
- lib/softcover/version.rb
|
@@ -1 +0,0 @@
|
|
1
|
-
% Don't edit this file; it is overwritten every time the PDF gets built.
|