bookmaker 0.6.0 → 0.7.0.pre3

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.
@@ -21,6 +21,15 @@ module Kitabu
21
21
  @engine ||= Object.const_get(MARKDOWN_LIBRARIES.find {|lib| Object.const_defined?(lib)})
22
22
  end
23
23
 
24
+ def self.to_latex(content)
25
+ case engine.name
26
+ when "Redcarpet"
27
+ # render = Redcarpet::Render::HTML.new(:hard_wrap => true, :xhtml => true)
28
+ # Redcarpet::Markdown.new(render).render(content)
29
+ else
30
+ engine.new(content).to_latex
31
+ end
32
+ end
24
33
  # Convert Markdown to HTML.
25
34
  def self.to_html(content)
26
35
  case engine.name
@@ -55,15 +55,25 @@ module Bookmaker
55
55
  stats = Bookmaker::Stats.new(root_dir)
56
56
 
57
57
  say [
58
- "Chapters: #{stats.chapters}",
59
- "Words: #{stats.words}",
60
- # "Images: #{stats.images}",
61
- # "Links: #{stats.links}",
62
- # "Footnotes: #{stats.footnotes}",
63
- # "Code blocks: #{stats.code_blocks}"
58
+ # "Chapters: #{stats.chapters}",
59
+ "Goal: #{sprintf("%7d", stats.target)}",
60
+ "Words: #{sprintf("%7d", stats.words)}",
61
+ " -------",
62
+ "Left: #{sprintf("%7d", stats.remaining)}",
63
+ "\nProgress: #{sprintf("%5d", stats.today)}"
64
64
  ].join("\n")
65
65
  end
66
-
66
+
67
+ desc "move old_id new_id", "Move scene to new sequence."
68
+ def move(oid,nid)
69
+ s = Structure.new(root_dir)
70
+ s.move(oid,nid)
71
+ end
72
+ desc "trash [OPTIONS]", "Move scene to trash."
73
+ def trash(scene_id)
74
+ s = Structure.new(root_dir)
75
+ s.trash(scene_id)
76
+ end
67
77
  private
68
78
  def config
69
79
  YAML.load_file(config_path).with_indifferent_access
@@ -21,6 +21,12 @@ module Bookmaker
21
21
  helper = root_dir.join("config/helper.rb")
22
22
  load(helper) if helper.exist?
23
23
 
24
+ raise "Missing Templates directory (_templates)" unless File.exist?("_templates")
25
+ raise "Missing Images directory (_images)" unless File.exist?("_images")
26
+ raise "Missing Output directory (_output)" unless File.exist?("_output")
27
+
28
+ puts Dependency.xelatex?
29
+
24
30
  export_pdf = [nil, "pdf"].include?(options[:only])
25
31
  export_html = [nil, "html", "mobi", "epub"].include?(options[:only])
26
32
  export_epub = [nil, "mobi", "epub"].include?(options[:only])
@@ -50,7 +56,7 @@ module Bookmaker
50
56
  end
51
57
 
52
58
  Notifier.notify(
53
- :image => Bookmaker::ROOT.join("templates/ebook.png"),
59
+ :image => Bookmaker::ROOT.join("_templates/ebook.png"),
54
60
  :title => "Bookmaker",
55
61
  :message => "Your \"#{config[:title]}\" e-book has been exported!"
56
62
  )
@@ -12,30 +12,34 @@ module Bookmaker
12
12
  template "config.erb", "_bookmaker.yml"
13
13
  end
14
14
  def copy_templates
15
- copy_file "latex.erb", "templates/pdf/layout.erb"
16
- copy_file "dp-logo.png", "images/dp-logo.png"
15
+ copy_file "pdf/layout.erb", "_templates/pdf/layout.erb"
16
+ copy_file "dp-logo.png", "_images/dp-logo.png"
17
+
18
+ copy_file "html/layout.erb", "_templates/html/layout.erb"
19
+ copy_file "html/thanks.erb", "_templates/html/thanks.erb"
20
+ copy_file "html/copyright.erb", "_templates/html/copyright.erb"
21
+ copy_file "html/user.css", "_templates/html/user.css"
22
+ copy_file "html/layout.css", "_templates/html/layout.css"
23
+ copy_file "html/syntax.css", "_templates/html/syntax.css"
17
24
 
18
- copy_file "html.erb", "templates/html/layout.erb"
19
- copy_file "user.css", "templates/html/user.css"
20
- copy_file "layout.css", "templates/html/layout.css"
21
- copy_file "syntax.css", "templates/html/syntax.css"
25
+ copy_file "epub/back.erb", "_templates/epub/back.html"
26
+ copy_file "epub/copyright.erb", "_templates/epub/copyright.erb"
27
+ copy_file "epub/cover.erb", "_templates/epub/cover.erb"
28
+ copy_file "epub/cover.html", "_templates/epub/cover.html"
29
+ copy_file "epub/page.erb", "_templates/epub/page.erb"
30
+ copy_file "epub/user.css", "_templates/epub/user.css"
22
31
 
23
- copy_file "back.erb", "templates/epub/back.erb"
24
- copy_file "copyright.erb", "templates/epub/copyright.erb"
25
- copy_file "cover.erb", "templates/epub/cover.erb"
26
- copy_file "epub.erb", "templates/epub/page.erb"
27
- copy_file "epub.css", "templates/epub/user.css"
28
- copy_file "cover.jpg", "images/cover.jpg"
29
- copy_file "rakefile.rb", "Rakefile"
30
- copy_file "extras.tex", "extras/characters.tex"
31
- copy_file "extras.tex", "extras/dedicationls.tex"
32
+ copy_file "cover.jpg", "_images/cover.jpg"
33
+ copy_file "rakefile.rb", "Rakefile"
34
+ copy_file "extras.tex", "_extras/characters.tex"
35
+ copy_file "extras.tex", "_extras/dedications.tex"
32
36
  end
33
37
  def copy_sample_text
34
- copy_file "sample.tex" , "text/01_First-Chapter/01-Welcome.tex"
38
+ copy_file "sample.tex", "text/01_First-Chapter/01-Welcome.tex"
35
39
  end
36
40
  def create_directories
37
- empty_directory "output"
38
- empty_directory "images"
41
+ empty_directory "_output"
42
+ empty_directory "_images"
39
43
  end
40
44
  private
41
45
  # Retrieve user's name using finger.
@@ -1,3 +1,4 @@
1
+ require 'fileutils'
1
2
  module Bookmaker
2
3
  module Parser
3
4
  class Epub < Base
@@ -28,11 +29,12 @@ module Bookmaker
28
29
  epub.cover cover_image
29
30
  end
30
31
  write_coverpage!
32
+ write_thankspage!
31
33
  write_copyright!
32
34
  write_sections!
33
35
  write_backpage!
34
36
  write_toc!
35
- epub.files cover_page + sections.map(&:filepath) + back_page + copyright_page + assets
37
+ epub.files cover_page + thanks_page + sections.map(&:filepath) + back_page + copyright_page + assets
36
38
  epub.nav navigation
37
39
 
38
40
  epub.save(epub_path)
@@ -51,28 +53,46 @@ module Bookmaker
51
53
  def copyright_page
52
54
  Dir[copyright_path]
53
55
  end
56
+ def thanks_page
57
+ Dir[thanks_path]
58
+ end
54
59
  def write_backpage!
55
- contents = render_template(root_dir.join("templates/epub/back.html"), config)
60
+ contents = render_template(root_dir.join("_templates/epub/back.html"), config)
56
61
  File.open(back_path,"w") do |file|
57
62
  file << contents
58
63
  end
59
64
  end
60
65
  def write_coverpage!
61
- contents = render_template(root_dir.join("templates/epub/cover.html"), config)
66
+ contents = render_template(root_dir.join("_templates/epub/cover.html"), config)
67
+ puts "Writing cover page. #{cover_path}"
68
+ #
69
+ # raise File.dirname(cover_path).inspect
70
+ FileUtils.mkdir_p(File.dirname(cover_path))
62
71
  File.open(cover_path,"w") do |file|
63
72
  file << contents
64
73
  end
65
74
  end
66
75
  def write_copyright!
67
- contents = render_template(root_dir.join("templates/html/copyright.erb"), config)
76
+ contents = render_template(root_dir.join("_templates/html/copyright.erb"), config)
68
77
  # File.open('help.html','w').write(contents)
78
+ FileUtils.mkdir_p(File.dirname(copyright_path))
69
79
  File.open(copyright_path,"w") do |file|
70
80
  file << contents
71
81
  # puts file
72
82
  end
73
83
  end
84
+ def write_thankspage!
85
+ contents = render_template(root_dir.join("_templates/html/thanks.erb"), config)
86
+ # File.open('help.html','w').write(contents)
87
+ FileUtils.mkdir_p(File.dirname(thanks_path))
88
+ File.open(thanks_path,"w") do |file|
89
+ file << contents
90
+ # puts file
91
+ end
92
+ end
74
93
  def write_toc!
75
94
  toc = TOC::Epub.new(navigation)
95
+ FileUtils.mkdir_p(File.dirname(toc_path))
76
96
  File.open(toc_path, "w") do |file|
77
97
  file << toc.to_html
78
98
  end
@@ -121,7 +141,7 @@ module Bookmaker
121
141
  end
122
142
  def assets
123
143
  @assets ||= begin
124
- assets = Dir[root_dir.join("templates/epub/*.css")]
144
+ assets = Dir[root_dir.join("_templates/epub/*.css")]
125
145
  assets += Dir[root_dir.join("images/**/*.{jpg,png,gif}")]
126
146
  assets
127
147
  end
@@ -138,20 +158,23 @@ module Bookmaker
138
158
  end
139
159
  end
140
160
  def template_path
141
- root_dir.join("templates/epub/page.erb")
161
+ root_dir.join("_templates/epub/page.erb")
142
162
  end
143
163
  def html_path
144
- root_dir.join("output/#{name}.html")
164
+ root_dir.join("_output/#{name}.html")
145
165
  end
146
166
  def epub_path
147
- root_dir.join("output/#{name}.epub")
167
+ root_dir.join("_output/#{name}.epub")
148
168
  end
149
169
  def tmp_dir
150
- root_dir.join("output/tmp")
170
+ root_dir.join("_output/tmp")
151
171
  end
152
172
  def cover_path
153
173
  tmp_dir.join("cover.html")
154
174
  end
175
+ def thanks_path
176
+ tmp_dir.join("thanks.html")
177
+ end
155
178
  def back_path
156
179
  tmp_dir.join("back.html")
157
180
  end
@@ -5,7 +5,8 @@ module Bookmaker
5
5
  def content
6
6
  raw = []
7
7
  entries.keys.each do |chapter|
8
- text = "<h2>#{chapter.split(/_/)[1].gsub('-',' ').titleize}</h2>"
8
+ # text = "<h2>#{chapter.split(/_/)[1].gsub('-',' ').titleize}</h2>"
9
+ text = "<h2>Chapter</h2>"
9
10
  sections = []
10
11
  entries[chapter].each do |section|
11
12
  sections << "<p>#{read_content(section)[0].split(/\n{2,}/).map do |s|
@@ -26,8 +27,8 @@ module Bookmaker
26
27
  :contents => toc.content,
27
28
  :toc => toc.to_html,
28
29
  })
29
- output = render_template(root_dir.join("templates/html/layout.erb"), locals)
30
- f = File.open(root_dir.join("output/#{name}.html"), 'w')
30
+ output = render_template(root_dir.join("_templates/html/layout.erb"), locals)
31
+ f = File.open(root_dir.join("_output/#{name}.html"), 'w')
31
32
  f.write(output)
32
33
  f.close
33
34
  true
@@ -44,20 +45,30 @@ module Bookmaker
44
45
  text.gsub!(/``(.*?'?)''/) { "&ldquo;#{$1}&rdquo;"}
45
46
  text.gsub!(/``(.*?'?)"/) { "&ldquo;#{$1}&rdquo;"}
46
47
  text.gsub!(/``/, "&ldquo;")
47
- text.gsub!(/\b'\b/) { "&#39;" }
48
+ text.gsub!(/\b'\b/) { "&rsquo;" }
48
49
  text.gsub!(/`(.*?)'/) { "&lsquo;#{$1}&rsquo;"}
49
50
  # \{([^\}]+?)\} Within the curly braces.
50
51
  text.gsub!(/\\pf?break\{\}/,"<hr />")
52
+ text.gsub!(/\\pf?break/,"<hr />")
53
+ text.gsub!(/\\%/,'%')
54
+ text.gsub!(/\\`e/,'&eacute;')
55
+ text.gsub!(/\\textgreater\{?\}?/, "&gt;")
56
+ text.gsub!(/\\Bophendze/,'Bophendze')
51
57
  text.gsub!(/\\ldots\{\}/,"&hellip;")
52
58
  text.gsub!(/\\Dash\{\}/, "&mdash;")
59
+ text.gsub!(/\\Dash/, "&mdash;")
53
60
  text.gsub!(/\\begin\{quote\}(.*?)\\end\{quote\}/m) { "<blockquote>#{$1.strip}</blockquote>"}
54
61
  text.gsub!(/<\/blockquote>\s+?<blockquote>/m, "\n")
55
62
  text.gsub!(/\\begin\{([^\}]+?)\}(.*?)\\end\{[^\}]+?\}/m) { "<div class='#{$1.strip}'>#{$2.strip}</div>"}
56
63
  text.gsub!(/\\section\{([^\}]+?)\}/m) { "<h3>#{$1.strip}</h3>"}
57
- ['Character','Equipment'].each do |s|
58
- text.gsub!(/\\#{s}\{[^\}]+?\}\{([^\}]+?)\}/) { "<span class='#{s}'>#{$1.strip}</span>"}
59
- text.gsub!(/\\#{s}\{([^\}]+?)\}/) { "<span class='#{s.downcase}'>#{$1.strip}</span>"}
64
+ ['Character','Equipment','Organization','Index'].each do |s|
65
+ # puts "Working on #{s}"
66
+ # text.gsub!(/\\#{s}{Drazen, Joven}{(Drazen)}/) { "<span class='#{s.downcase}'>#{$1.strip}</span>"}
67
+ text.gsub!(/\\#{s}\{[^\}]+?\}\{([^\}]+?)\}/) { "<span class='#{s.downcase}'>#{$1.strip}</span>"}
68
+ text.gsub!(/\\#{s}\{([^\}]+?)\}/) { ""}
69
+ # text.gsub!(/\\#{s}\{([^\}]+?)\}/) { "<span class='#{s.downcase}'>#{$1.strip}</span>"}
60
70
  end
71
+ text.gsub!(/\\footnote\{([^\}]+?)\}/m) { ""}
61
72
  text.gsub!(/\\emph\{([^\}]+?)\}/m) { "<em>#{$1.strip}</em>"}
62
73
  text.gsub!(/\\thought\{([^\}]+?)\}/m) { "<em>#{$1.strip}</em>"}
63
74
  text.gsub!(/\\(.*?)\{([^\}]+?)\}/) { "<span class='#{$1.downcase}'>#{$2.strip}</span>"}
@@ -65,7 +76,6 @@ module Bookmaker
65
76
  text.gsub!(/<\/span>\{[^\}]+?}/, "</span>")
66
77
  text.gsub!(/<p><h([1-6])>(.*?)<\/h[1-6]><\/p>/) { "<h#{$1}>#{$2.strip}</h#{$1}>"}
67
78
  text.gsub!(/(\S+)~(\S+)/) { "#{$1}&nbsp;#{$2}"}
68
- # text.gsub!(/> +/, ">")
69
79
  output << text
70
80
  end
71
81
  output.gsub!(/\n\n+/, "\n\n")
@@ -97,7 +107,7 @@ module Bookmaker
97
107
  # def parse
98
108
  # reset_footnote_index!
99
109
  #
100
- # # File.open(root_dir.join("output/#{name}.html"), "w") do |file|
110
+ # # File.open(root_dir.join("_output/#{name}.html"), "w") do |file|
101
111
  # # file << parse_layout(content)
102
112
  # # end
103
113
  # true
@@ -211,7 +221,7 @@ module Bookmaker
211
221
  # :toc => toc.to_html,
212
222
  # :changelog => render_changelog
213
223
  # })
214
- # render_template(root_dir.join("templates/html/layout.erb"), locals)
224
+ # render_template(root_dir.join("_templates/html/layout.erb"), locals)
215
225
  # end
216
226
  #
217
227
  # # Render changelog file.
@@ -10,7 +10,7 @@ module Bookmaker
10
10
  false
11
11
  end
12
12
  def epub_file
13
- root_dir.join("output/#{name}.epub")
13
+ root_dir.join("_output/#{name}.epub")
14
14
  end
15
15
  end
16
16
  end
@@ -7,6 +7,7 @@ module Bookmaker
7
7
  raw = []
8
8
  entries.keys.each do |chapter|
9
9
  title = (chapter.empty?) ? "Untitled" : chapter.split('_')[1]
10
+ title = 'Untitled' if title.nil?
10
11
  raw << "\\Chapter{#{title.gsub('-',' ')}}\n\n"
11
12
  entries[chapter].each do |section|
12
13
  s = read_content(section)[0]
@@ -46,7 +47,7 @@ module Bookmaker
46
47
  text.gsub!('* * *', "\n\n\\pbreak{}\n\n")
47
48
  end
48
49
  def tex_file
49
- root_dir.join("output/#{name}.tex")
50
+ root_dir.join("_output/#{name}.tex")
50
51
  end
51
52
  end
52
53
  end
@@ -1,45 +1,114 @@
1
+ class Fixnum
2
+ def day
3
+ self * (60 * 60 * 24) # seconds * hours * minutes
4
+ end
5
+ def ago
6
+ Time.now - self
7
+ end
8
+ end
9
+ require 'json'
1
10
  module Bookmaker
2
11
  class Stats
3
12
  attr_reader :root_dir
4
13
 
5
14
  def initialize(root_dir)
6
15
  @root_dir = root_dir
16
+ @files = Dir["#{root_dir}/text/**/[0-9]*.tex"]
17
+ @words = 0
18
+ @progress = (File.exist?(log)) ? JSON.parse(File.open(log,'r').read).clone : {}
7
19
  end
8
20
 
9
- def text
10
- @text ||= html.text
21
+ def log
22
+ "#{root_dir}/.wordcount"
11
23
  end
12
24
 
13
- def html
14
- @html ||= Nokogiri::HTML(content)
25
+ def target
26
+ Bookmaker.config(@root_dir)['wordcount']
15
27
  end
16
-
17
- def words
18
- @words ||= text.split(" ").size
28
+ def now
29
+ Date.today.to_s
19
30
  end
31
+ def words
32
+ if @words == 0
33
+ most_recent = @files.max_by {|f| File.mtime(f)}
34
+ if !@progress[now].nil? and File.mtime(log) > File.mtime(most_recent)
35
+ @progress[now]
36
+ else
37
+ detex = "/usr/texbin/detex"
20
38
 
21
- def chapters
22
- @chapters ||= html.css(".chapter").size
39
+ file = Tempfile.new('foo.tex')
40
+ file.write(text)
41
+ file.close
42
+ @progress[now] = `detex #{file.path}| wc -w`.to_i
43
+ file.unlink
44
+ # Do previous day's progress...if nil.
45
+ @progress[Date.yesterday.to_s] = @progress[now] if @progress.keys.count == 1
46
+ end
47
+ end
48
+ if (lasttime != Date.yesterday.to_s)
49
+ # Update the record.
50
+ n = lasttime
51
+ w = @progress[lasttime]
52
+ n.upto(Date.yesterday.to_s) do |k|
53
+ # puts "Upto #{k}: @progress[#{k}] = #{w}"
54
+ @progress[k] = w
55
+ end
56
+ end
57
+ File.open(log,'w').write( JSON.generate(@progress) )
58
+ @words = @progress[now]
23
59
  end
24
-
25
- def images
26
- @images ||= html.css("img").size
60
+ def lasttime
61
+ p = nil
62
+ @progress.keys.sort.each do |k|
63
+ break if k == now
64
+ p = k
65
+ end
66
+ p
27
67
  end
28
-
29
- def footnotes
30
- @footnotes ||= html.css("p.footnote").size
68
+ def yesterday
69
+ @progress[lasttime]
31
70
  end
32
-
33
- def links
34
- @links ||= html.css("[href^='http']").size
71
+ def today
72
+ @words - @progress[lasttime]
35
73
  end
36
-
37
- def code_blocks
38
- @code_blocks ||= html.css("pre").size
74
+ def text
75
+ @text = nil
76
+ @text = @files.map{|f| File.open(f,'r').read}.join("\n\n\n") if @text.nil?
39
77
  end
40
-
41
- def content
42
- @content ||= Parser::HTML.new(root_dir).content
78
+ def remaining
79
+ target - words
43
80
  end
81
+
82
+ # def html
83
+ # @html ||= Nokogiri::HTML(content)
84
+ # end
85
+
86
+ # def words
87
+ # @words ||= text.split(" ").size
88
+ # end
89
+
90
+ # def chapters
91
+ # @chapters ||= html.css(".chapter").size
92
+ # end
93
+
94
+ # def images
95
+ # @images ||= html.css("img").size
96
+ # end
97
+
98
+ # def footnotes
99
+ # @footnotes ||= html.css("p.footnote").size
100
+ # end
101
+
102
+ # def links
103
+ # @links ||= html.css("[href^='http']").size
104
+ # end
105
+
106
+ # def code_blocks
107
+ # @code_blocks ||= html.css("pre").size
108
+ # end
109
+
110
+ # def content
111
+ # @content ||= Parser::HTML.new(root_dir).content
112
+ # end
44
113
  end
45
114
  end