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.
314 315 316 |
# File 'lib/softcover/utils.rb', line 314 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
299 300 301 302 303 304 305 |
# File 'lib/softcover/utils.rb', line 299 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 281 282 283 |
# 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.2.2/epubcheck.jar') first_path(version_4) || get_filename(:'epubcheck') || "" when :inkscape default = '/Applications/Inkscape.app/Contents/MacOS/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 when :python3 python = get_filename(:python3) `#{python} --version`.match(/Python 3\.*/) ? python : "" 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.
290 291 292 |
# File 'lib/softcover/utils.rb', line 290 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
285 286 287 |
# File 'lib/softcover/utils.rb', line 285 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.
295 296 297 |
# File 'lib/softcover/utils.rb', line 295 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.
333 334 335 336 |
# File 'lib/softcover/utils.rb', line 333 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.
322 323 324 325 326 327 328 329 330 |
# File 'lib/softcover/utils.rb', line 322 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.
308 309 310 311 |
# File 'lib/softcover/utils.rb', line 308 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 |