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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/softcover/book_manifest.rb +17 -5
  3. data/lib/softcover/builder.rb +29 -1
  4. data/lib/softcover/builders/epub.rb +5 -11
  5. data/lib/softcover/builders/html.rb +5 -3
  6. data/lib/softcover/builders/mobi.rb +6 -13
  7. data/lib/softcover/builders/pdf.rb +23 -4
  8. data/lib/softcover/builders/preview.rb +1 -3
  9. data/lib/softcover/cli.rb +24 -3
  10. data/lib/softcover/commands/build.rb +29 -6
  11. data/lib/softcover/commands/check.rb +103 -0
  12. data/lib/softcover/commands/deployment.rb +0 -7
  13. data/lib/softcover/commands/epub_validator.rb +2 -8
  14. data/lib/softcover/sanitizer.rb +5 -1
  15. data/lib/softcover/template/.softcover-build +6 -0
  16. data/lib/softcover/template/chapters/a_chapter.md +10 -11
  17. data/lib/softcover/template/chapters/a_chapter.tex +13 -21
  18. data/lib/softcover/template/chapters/another_chapter.md +3 -1
  19. data/lib/softcover/template/config/lang.yml +14 -0
  20. data/lib/softcover/template/config/preamble.tex +8 -0
  21. data/lib/softcover/template/epub/OEBPS/styles/custom_epub.css +7 -0
  22. data/lib/softcover/template/images/cover-web.png +0 -0
  23. data/lib/softcover/template/images/cover.pdf +0 -0
  24. data/lib/softcover/template/images/cover.png +0 -0
  25. data/lib/softcover/template/latex_styles/custom_pdf.sty +6 -4
  26. data/lib/softcover/template/latex_styles/language_customization.sty +11 -0
  27. data/lib/softcover/template/latex_styles/softcover.sty +10 -7
  28. data/lib/softcover/utils.rb +65 -6
  29. data/lib/softcover/version.rb +1 -1
  30. data/lib/softcover.rb +1 -0
  31. data/softcover.gemspec +10 -10
  32. data/spec/builders/mobi_spec.rb +5 -3
  33. data/spec/builders/pdf_spec.rb +19 -0
  34. data/spec/cli_spec.rb +27 -0
  35. data/spec/commands/build_spec.rb +9 -0
  36. data/spec/commands/check_spec.rb +57 -0
  37. metadata +49 -41
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e236dc06258cb83e779007f53868d7e11a1fe12
4
- data.tar.gz: 4e9cf4fd4ee6a1a03beb796004522e4cb20dce10
3
+ metadata.gz: 5cde257d853b87404d19decb7190ed774b6f68c2
4
+ data.tar.gz: 4a22997a284fa6f364c61aeee24344942a485a94
5
5
  SHA512:
6
- metadata.gz: 1c0f5758cbbd305ea9b0f76a7939be1d39cbba9729d8cd5626a33c844c92415e59839d81d2442ee14d649c5e2a0b102e1dee4321fff671a9eb55b459627387ab
7
- data.tar.gz: 03f7a45f12d7905abdf0f78ace0330eece59d948dcaaeb1841ab72a0018cfd390c0f8010d6cbe59775584ee34656558e432cadc086d3c7a91d186fd15c5f0e7e
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).to_html
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? ? html : "Chapter #{chapter_number}: #{html}"
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: 'Frontmatter',
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
- raise "Chapter file in manifest not found in #{chapter_path}"
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
@@ -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
- filename = `which phantomjs`.chomp
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
- filename = `which inkscape`.chomp
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 ? "Frontmatter" : "Chapter #{n}"
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
- cc = Softcover.custom_styles
116
- Polytexnic::Pipeline.new(polytex, custom_commands: cc).to_html
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
- unless options[:kindlegen]
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[:kindlegen]
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
- filename = `which ebook-convert`.chomp
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
- filename = `which kindlegen`.chomp
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).to_latex
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
- filename = `which xelatex`.chomp
71
- message = "Install LaTeX (http://latex-project.org/ftp.html)"
72
- @xelatex ||= executable(filename, message)
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
- filename = `which gs`.chomp
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 :kindlegen, aliases: '-k',
46
- desc: "Use kindlegen to build the MOBI",
47
- type: :boolean
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
- Softcover::BUILD_ALL_FORMATS.each do |format|
21
- if format == 'mobi'
22
- building_message('EPUB & MOBI', options)
23
- else
24
- building_message(format.upcase, options)
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
- filename = `which java`.chomp
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
- filename = File.join(Dir.home, 'epubcheck-3.0', 'epubcheck-3.0.jar')
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
@@ -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']},
@@ -0,0 +1,6 @@
1
+ # Edit this file to customize your build steps with custom command options
2
+ # or additional commands.
3
+ #
4
+ # softcover build:pdf
5
+ # softcover build:mobi
6
+ # softcover build:preview
@@ -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
- softcover config # View local config
106
- softcover config:add key=value # Add to your local config vars
107
- softcover epub:validate, epub:check # Validate EPUB with epubcheck
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: