Module: Softcover::Utils
- Extended by:
- Utils
- Included in:
- Softcover, Book, BookManifest, BookManifest::Chapter, Builder, Builders::Html, Builders::Mobi, Builders::Pdf, CLI, Client, Commands::Build, Commands::Check, Commands::Deployment, Commands::EpubValidator, Commands::Publisher, Commands::Server, Uploader, Utils
- Defined in:
- lib/softcover/utils.rb
Constant Summary collapse
- UNITS =
%W(B KB MB GB TB).freeze
Instance Method Summary collapse
-
#add_highlight_class!(pygments_css) ⇒ Object
Adds a ‘highlight’ class for MathJax compatibility.
-
#article? ⇒ Boolean
Returns true if document is an article.
- #as_size(number) ⇒ Object
-
#book_file_lines(manifest) ⇒ Object
Returns the lines of book file as an array, removing commented-out lines.
- #chapter_label(chapter_number) ⇒ Object
-
#commands(lines) ⇒ Object
Returns the commands from the given lines.
- #current_book ⇒ Object
-
#dependency_filename(label) ⇒ Object
Returns the filename of a dependency given a label.
-
#digest(string) ⇒ Object
Returns a digest of the string.
-
#executable(filename) ⇒ Object
Returns the executable if it exists, raising an error otherwise.
-
#execute(command) ⇒ Object
Execute a command.
-
#filename_or_default(name, default) ⇒ Object
Returns the filename if it exists on the path and a default otherwise.
-
#first_path(file) ⇒ Object
Returns first location on the path for a given file.
- #get_filename(name) ⇒ Object
- #html_extension ⇒ Object
- #in_book_directory? ⇒ Boolean
-
#language_labels ⇒ Object
Returns the language labels from the config file.
-
#linux? ⇒ Boolean
Returns true if platform is Linux.
- #logged_in? ⇒ Boolean
-
#master_content(manifest) ⇒ Object
Returns the content for the master LaTeX file.
-
#master_filename(manifest) ⇒ Object
Returns the name of the master LaTeX file.
- #master_latex_header(manifest) ⇒ Object
- #mkdir(dir) ⇒ Object
-
#non_comment_lines(lines) ⇒ Object
Returns only non-comment lines.
-
#os_x? ⇒ Boolean
Returns true if platform is OS X.
-
#path(path_string = '') ⇒ Object
Returns the system-independent file path.
-
#polytexnic_html(text) ⇒ Object
Run text through the Polytexnic pipeline to make an HTML snippet.
-
#raw_lines(manifest) ⇒ Object
Returns all the lines in Book.txt.
- #reset_current_book! ⇒ Object
-
#rm(file) ⇒ Object
Removes a file (or list of files).
-
#rm_r(directory) ⇒ Object
Removes a directory recursively.
- #silence ⇒ Object
-
#silence_stream(stream) ⇒ Object
Silences a stream.
-
#source ⇒ Object
Returns the source type (PolyTeX or Markdown) of the current book.
-
#template_dir(options) ⇒ Object
Returns the directory of the document template.
-
#tmpify(manifest, filename) ⇒ Object
Returns the tmp version of a filename.
-
#unpublish_slug ⇒ Object
Returns the slug to be unpublished.
-
#write_master_latex_file(manifest) ⇒ Object
Writes the master LaTeX file <name>.tex to use chapters from Book.txt.
-
#write_pygments_file(format, path) ⇒ Object
Writes a Pygments style file.
Instance Method Details
#add_highlight_class!(pygments_css) ⇒ Object
Adds a ‘highlight’ class for MathJax compatibility.
168 169 170 |
# File 'lib/softcover/utils.rb', line 168 def add_highlight_class!(pygments_css) pygments_css.gsub!(/^/, '.highlight ') end |
#article? ⇒ Boolean
Returns true if document is an article.
311 312 313 |
# File 'lib/softcover/utils.rb', line 311 def article? !!File.readlines(path('config/preamble.tex')).first.match(/extarticle/) end |
#as_size(number) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/softcover/utils.rb', line 50 def as_size(number) if number.to_i < 1024 exponent = 0 else max_exp = UNITS.size - 1 exponent = ( Math.log( number ) / Math.log( 1024 ) ).to_i exponent = max_exp if exponent > max_exp number /= 1024 ** exponent end "#{number.round} #{UNITS[ exponent ]}" end |
#book_file_lines(manifest) ⇒ Object
Returns the lines of book file as an array, removing commented-out lines.
82 83 84 |
# File 'lib/softcover/utils.rb', line 82 def book_file_lines(manifest) non_comment_lines(raw_lines(manifest)) end |
#chapter_label(chapter_number) ⇒ Object
296 297 298 299 300 301 302 |
# File 'lib/softcover/utils.rb', line 296 def chapter_label(chapter_number) if language_labels["chapter"]["order"] == "reverse" "#{chapter_number} #{language_labels['chapter']['word']}" else "#{language_labels['chapter']['word']} #{chapter_number}" end end |
#commands(lines) ⇒ Object
Returns the commands from the given lines. We skip comments and blank lines.
240 241 242 243 |
# File 'lib/softcover/utils.rb', line 240 def commands(lines) skip = /(^\s*#|^\s*$)/ lines.reject { |line| line =~ skip }.join("\n") end |
#current_book ⇒ Object
4 5 6 7 8 9 |
# File 'lib/softcover/utils.rb', line 4 def current_book # using module level variable because it should be context independent @@current_book ||= begin in_book_directory? ? Softcover::Book.new(origin: source) : false end end |
#dependency_filename(label) ⇒ Object
Returns the filename of a dependency given a label.
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 |
# File 'lib/softcover/utils.rb', line 253 def dependency_filename(label) case label when :latex get_filename(:xelatex) when :ghostscript get_filename(:gs) when :calibre get_filename(:'ebook-convert') when :epubcheck # Finds EpubCheck anywhere on the path. version_4 = path('epubcheck-4.0.2/epubcheck.jar') first_path(version_4) || get_filename(:'epubcheck') || "" when :inkscape default = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape' filename_or_default(:inkscape, default) when :phantomjs phantomjs = get_filename(label) # Test for version 2, which is now necessary. version = `#{phantomjs} -v`.scan(/^(\d)\./).flatten.first.to_i rescue nil if version == 2 phantomjs else "" end else get_filename(label) end end |
#digest(string) ⇒ Object
Returns a digest of the string.
173 174 175 |
# File 'lib/softcover/utils.rb', line 173 def digest(string) Digest::SHA1.hexdigest(string) end |
#executable(filename) ⇒ Object
Returns the executable if it exists, raising an error otherwise.
178 179 180 181 182 183 184 185 186 |
# File 'lib/softcover/utils.rb', line 178 def executable(filename) filename.tap do |f| unless File.exist?(f) $stderr.puts "Document not built due to missing dependency" $stderr.puts "Run `softcover check` to check dependencies" exit 1 end end end |
#execute(command) ⇒ Object
Execute a command. The issue here is that ‘exec` is awful in tests, since it exits the process. This command arranges to use `system` in tests instead.
216 217 218 |
# File 'lib/softcover/utils.rb', line 216 def execute(command) Softcover.test? ? system(command) : exec(command) end |
#filename_or_default(name, default) ⇒ Object
Returns the filename if it exists on the path and a default otherwise.
287 288 289 |
# File 'lib/softcover/utils.rb', line 287 def filename_or_default(name, default) (f = get_filename(name)).empty? ? default : f end |
#first_path(file) ⇒ Object
Returns first location on the path for a given file.
246 247 248 249 250 |
# File 'lib/softcover/utils.rb', line 246 def first_path(file) possible_paths = ENV['PATH'].split(File::PATH_SEPARATOR). collect { |x| File.join(x, file) } possible_paths.find { |f| File.file?(f) } end |
#get_filename(name) ⇒ Object
282 283 284 |
# File 'lib/softcover/utils.rb', line 282 def get_filename(name) `which #{name}`.chomp end |
#html_extension ⇒ Object
44 45 46 |
# File 'lib/softcover/utils.rb', line 44 def html_extension 'html' end |
#in_book_directory? ⇒ Boolean
25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/softcover/utils.rb', line 25 def in_book_directory? Softcover::BookManifest::find_book_root! files = Dir['**/*'] Softcover::FORMATS.each do |format| unless files.any?{ |file| File.extname(file) == ".#{format}" } puts "No #{format} found, skipping." end end return Softcover::BookManifest::valid_directory? end |
#language_labels ⇒ Object
Returns the language labels from the config file.
292 293 294 |
# File 'lib/softcover/utils.rb', line 292 def language_labels YAML.load_file(File.join(Softcover::Directories::CONFIG, 'lang.yml')) end |
#linux? ⇒ Boolean
Returns true if platform is Linux.
234 235 236 |
# File 'lib/softcover/utils.rb', line 234 def linux? RUBY_PLATFORM.match(/linux/) end |
#logged_in? ⇒ Boolean
39 40 41 42 |
# File 'lib/softcover/utils.rb', line 39 def logged_in? require 'softcover/config' Softcover::Config['api_key'].present? end |
#master_content(manifest) ⇒ Object
Returns the content for the master LaTeX file.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/softcover/utils.rb', line 98 def master_content(manifest) front_or_mainmatter = /(.*):\s*$/ source_file = /(.*)(?:\.md|\.tex)\s*$/ tex_file = [master_latex_header(manifest)] book_file_lines(manifest).each do |line| if line.match(source_file) tex_file << "\\include{#{manifest.polytex_dir}/#{$1}}" elsif line.match(front_or_mainmatter) # frontmatter or mainmatter tex_file << "\\#{$1}" elsif line.strip == 'cover' tex_file << '\\includepdf{images/cover.pdf}' else # raw command, like 'maketitle' or 'tableofcontents' tex_file << "\\#{line.strip}" end end tex_file << '\end{document}' tex_file.join("\n") + "\n" end |
#master_filename(manifest) ⇒ Object
Returns the name of the master LaTeX file.
77 78 79 |
# File 'lib/softcover/utils.rb', line 77 def master_filename(manifest) "#{manifest.filename}.tex" end |
#master_latex_header(manifest) ⇒ Object
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/softcover/utils.rb', line 118 def master_latex_header(manifest) preamble = File.read(path('config/preamble.tex')) subtitle = manifest.subtitle.nil? ? "" : "\\subtitle{#{manifest.subtitle}}" <<-EOS #{preamble} \\usepackage{#{Softcover::Directories::STYLES}/softcover} \\VerbatimFootnotes % Allows verbatim text in footnotes \\title{#{manifest.title}} #{subtitle} \\author{#{manifest.}} \\date{#{manifest.date}} \\begin{document} EOS end |
#mkdir(dir) ⇒ Object
188 189 190 |
# File 'lib/softcover/utils.rb', line 188 def mkdir(dir) Dir.mkdir(dir) unless File.directory?(dir) end |
#non_comment_lines(lines) ⇒ Object
Returns only non-comment lines.
87 88 89 90 |
# File 'lib/softcover/utils.rb', line 87 def non_comment_lines(lines) comment = /^\s*#.*$/ lines.reject { |line| line.match(comment) } end |
#os_x? ⇒ Boolean
Returns true if platform is OS X.
229 230 231 |
# File 'lib/softcover/utils.rb', line 229 def os_x? RUBY_PLATFORM.match(/darwin/) end |
#path(path_string = '') ⇒ Object
Returns the system-independent file path. It’s nicer to write ‘path(’foo/bar/baz’)‘ than `File.join(’foo’, ‘bar’, ‘baz’)‘.
209 210 211 |
# File 'lib/softcover/utils.rb', line 209 def path(path_string='') File.join(*path_string.split('/')) end |
#polytexnic_html(text) ⇒ Object
Run text through the Polytexnic pipeline to make an HTML snippet.
330 331 332 333 |
# File 'lib/softcover/utils.rb', line 330 def polytexnic_html(text) Nokogiri::HTML(Polytexnic::Pipeline.new(text).to_html).at_css('p') .inner_html.strip end |
#raw_lines(manifest) ⇒ Object
Returns all the lines in Book.txt.
93 94 95 |
# File 'lib/softcover/utils.rb', line 93 def raw_lines(manifest) File.readlines(manifest.book_file) end |
#reset_current_book! ⇒ Object
21 22 23 |
# File 'lib/softcover/utils.rb', line 21 def reset_current_book! @@current_book = nil end |
#rm(file) ⇒ Object
Removes a file (or list of files).
193 194 195 196 197 198 199 |
# File 'lib/softcover/utils.rb', line 193 def rm(file) if file.is_a?(Array) file.each { |f| rm(f) } else FileUtils.rm(file) if File.exist?(file) end end |
#rm_r(directory) ⇒ Object
Removes a directory recursively.
202 203 204 |
# File 'lib/softcover/utils.rb', line 202 def rm_r(directory) FileUtils.rm_r(directory) if File.directory?(directory) end |
#silence ⇒ Object
220 221 222 223 224 225 226 |
# File 'lib/softcover/utils.rb', line 220 def silence return yield if ENV['silence'] == 'false' silence_stream(STDOUT) do yield end end |
#silence_stream(stream) ⇒ Object
Silences a stream. This is taken directly from Rails Active Support ‘silence_stream`. The `silence_stream` method is deprecated because it’s not thread-safe, but we don’t care about that and the deprecation warnings are annoying.
319 320 321 322 323 324 325 326 327 |
# File 'lib/softcover/utils.rb', line 319 def silence_stream(stream) old_stream = stream.dup stream.reopen(RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ ? 'NUL:' : '/dev/null') stream.sync = true yield ensure stream.reopen(old_stream) old_stream.close end |
#source ⇒ Object
Returns the source type (PolyTeX or Markdown) of the current book.
12 13 14 |
# File 'lib/softcover/utils.rb', line 12 def source Dir.glob(path('chapters/*.md')).empty? ? :polytex : :markdown end |
#template_dir(options) ⇒ Object
Returns the directory of the document template.
305 306 307 308 |
# File 'lib/softcover/utils.rb', line 305 def template_dir() doc = [:article] ? 'article' : 'book' File. File.join(File.dirname(__FILE__), "#{doc}_template") end |
#tmpify(manifest, filename) ⇒ Object
Returns the tmp version of a filename. E.g., tmpify(‘foo.tex’) => ‘foo.tmp.tex’
136 137 138 139 140 141 142 |
# File 'lib/softcover/utils.rb', line 136 def tmpify(manifest, filename) tmp = Softcover::Directories::TMP mkdir tmp sep = File::SEPARATOR filename.sub(manifest.polytex_dir + sep, tmp + sep). sub('.tex', '.tmp.tex') end |
#unpublish_slug ⇒ Object
Returns the slug to be unpublished.
17 18 19 |
# File 'lib/softcover/utils.rb', line 17 def unpublish_slug Softcover::BookManifest.new(origin: source).slug end |
#write_master_latex_file(manifest) ⇒ Object
Writes the master LaTeX file <name>.tex to use chapters from Book.txt. We skip this step if Book.txt doesn’t exist, as that means the user is writing raw LaTeX.
70 71 72 73 74 |
# File 'lib/softcover/utils.rb', line 70 def write_master_latex_file(manifest) if File.exist?(manifest.book_file) File.write(master_filename(manifest), master_content(manifest)) end end |
#write_pygments_file(format, path) ⇒ Object
Writes a Pygments style file. We support both :html (outputting CSS) and :latex (outputting a LaTeX style file).
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/softcover/utils.rb', line 147 def write_pygments_file(format, path) require 'pygments' extension = case format when :html 'css' when :latex 'sty' end # Here we burrow into the private 'Pygments#mentos' method. # Pygments exposes a 'css' method to return the CSS, # but we want to be able to output a LaTeX style file as well. # The inclusion of the ':css' symbol is necessary but doesn't actually # result in CSS being output unless the format is 'html'. pygments = Pygments::Popen.new.send(:mentos, :css, [format.to_s, '']) add_highlight_class!(pygments) if format == :html File.open(File.join(path, "pygments.#{extension}"), 'w') do |f| f.write(pygments) end end |