publishr 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/bin/publishr +53 -0
- data/lib/epub_skeleton/META-INF/container.xml +6 -0
- data/lib/epub_skeleton/epub.css +90 -0
- data/lib/epub_skeleton/mimetype +1 -0
- data/lib/epub_templates/content.opf.erb +33 -0
- data/lib/epub_templates/kramdown.html +11 -0
- data/lib/epub_templates/manifest_items.erb +1 -0
- data/lib/epub_templates/nav_points.erb +6 -0
- data/lib/epub_templates/spine_items.erb +1 -0
- data/lib/epub_templates/toc.ncx.erb +21 -0
- data/lib/publishr.rb +27 -0
- data/lib/publishr/epub_renderer.rb +128 -0
- data/lib/publishr/latex_processor.rb +85 -0
- data/lib/publishr/latex_renderer.rb +54 -0
- data/lib/publishr/markup_processor.rb +95 -0
- data/lib/publishr/project.rb +66 -0
- data/lib/publishr/version.rb +3 -0
- data/publishr.gemspec +24 -0
- metadata +67 -0
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/publishr
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# PublishR -- Fast publishing for ebooks and paper
|
4
|
+
# Copyright (C) 2012 Michael Franzl
|
5
|
+
#
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as
|
8
|
+
# published by the Free Software Foundation, either version 3 of the
|
9
|
+
# License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
21
|
+
|
22
|
+
require 'publishr'
|
23
|
+
|
24
|
+
if ARGV[0].nil?
|
25
|
+
puts ''
|
26
|
+
puts 'PublishR -- Fast publishing for ebooks and paper'
|
27
|
+
puts 'Copyright (C) 2012 Michael Franzl'
|
28
|
+
puts ''
|
29
|
+
puts ''
|
30
|
+
puts "USAGE: publishr [name] [path_to_source_dir] [format] [path_to_converters]"
|
31
|
+
puts ''
|
32
|
+
puts " [name] is an unique string that identifies your project. Rendered files will be named after this."
|
33
|
+
puts " [path_to_source_dir] directory must minimally contain: [cover.jpg, covertext.txt, frontmatter.txt, toc.txt, metadata.yml]"
|
34
|
+
puts " [format] must be {mobi, epub, pdf}"
|
35
|
+
puts " [path_to_converters] directory must contain `kindlegen` and `jpg2ps`. They cannot be shipped with this program due to legal reasons."
|
36
|
+
puts ''
|
37
|
+
puts 'EXAMPLE: publishr mybook1 my/files/mybook epub path/to/converters'
|
38
|
+
puts ''
|
39
|
+
puts 'This program is free software: you can redistribute it and/or modify'
|
40
|
+
puts 'it under the terms of the GNU Affero General Public License as'
|
41
|
+
puts 'published by the Free Software Foundation, either version 3 of the'
|
42
|
+
puts 'License, or (at your option) any later version.'
|
43
|
+
puts ''
|
44
|
+
puts ''
|
45
|
+
Process.exit
|
46
|
+
end
|
47
|
+
|
48
|
+
project = Publishr::Project.new(ARGV[0], ARGV[1], ARGV[3])
|
49
|
+
|
50
|
+
case ARGV[2]
|
51
|
+
when 'kindle' then project.make_kindle
|
52
|
+
when 'pdf' then project.make_pdf
|
53
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
p {
|
2
|
+
margin-bottom: 1em;
|
3
|
+
font-size: medium;
|
4
|
+
}
|
5
|
+
|
6
|
+
.blockquote_transcript_1 {
|
7
|
+
margin-left: 1em;
|
8
|
+
font-size: small;
|
9
|
+
}
|
10
|
+
|
11
|
+
.blockquote__1 {
|
12
|
+
margin-left: 1em;
|
13
|
+
font-size: small;
|
14
|
+
}
|
15
|
+
|
16
|
+
.blockquote_email_1 {
|
17
|
+
margin-left: 1em;
|
18
|
+
font-size: xx-small;
|
19
|
+
font-family: Monospace;
|
20
|
+
}
|
21
|
+
|
22
|
+
|
23
|
+
.blockquote_transcript_2 {
|
24
|
+
margin-left: 1em;
|
25
|
+
font-size: small;
|
26
|
+
font-style: italic;
|
27
|
+
}
|
28
|
+
|
29
|
+
.blockquote__2 {
|
30
|
+
margin-left: 1em;
|
31
|
+
font-size: small;
|
32
|
+
font-style: italic;
|
33
|
+
}
|
34
|
+
|
35
|
+
.blockquote_email_2 {
|
36
|
+
margin-left: 1em;
|
37
|
+
font-size: xx-small;
|
38
|
+
font-style: italic;
|
39
|
+
font-family: Monospace;
|
40
|
+
}
|
41
|
+
|
42
|
+
|
43
|
+
code {
|
44
|
+
font-style: italic;
|
45
|
+
font-size: small;
|
46
|
+
}
|
47
|
+
|
48
|
+
.image {
|
49
|
+
text-align: center;
|
50
|
+
}
|
51
|
+
|
52
|
+
h1 {
|
53
|
+
margin-bottom: 1em;
|
54
|
+
margin-top: 2em;
|
55
|
+
font-size: xx-large;
|
56
|
+
text-align: center;
|
57
|
+
}
|
58
|
+
|
59
|
+
h2 {
|
60
|
+
margin-bottom: 2em;
|
61
|
+
text-align: center;
|
62
|
+
}
|
63
|
+
|
64
|
+
h3 {
|
65
|
+
margin-bottom: 1em;
|
66
|
+
margin-top: 1em;
|
67
|
+
text-align: center;
|
68
|
+
}
|
69
|
+
|
70
|
+
.covertext {
|
71
|
+
text-align: center;
|
72
|
+
font-size: xx-small;
|
73
|
+
}
|
74
|
+
|
75
|
+
.copyright {
|
76
|
+
font-size: xx-small;
|
77
|
+
text-indent: 0;
|
78
|
+
}
|
79
|
+
|
80
|
+
.title {
|
81
|
+
text-align: center;
|
82
|
+
}
|
83
|
+
|
84
|
+
.footnote {
|
85
|
+
font-size: x-small;
|
86
|
+
}
|
87
|
+
|
88
|
+
.toc {
|
89
|
+
text-indent: 0;
|
90
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
application/epub+zip
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
|
3
|
+
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="<%= @metadata['identifier'] %>">
|
4
|
+
|
5
|
+
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opf="http://www.idpf.org/2007/opf">
|
6
|
+
<dc:title><%= @metadata['title'] %></dc:title>
|
7
|
+
<dc:language xsi:type="dcterms:RFC3066"><%= @metadata['language'] %></dc:language>
|
8
|
+
<meta name="cover" content="coverjpg" />
|
9
|
+
<dc:identifier id="<%= @metadata['identifier'] %>" opf:scheme="ISBN"><%= @metadata['isbn'] %></dc:identifier>
|
10
|
+
<dc:creator><%= @metadata['creator'] %></dc:creator>
|
11
|
+
<dc:publisher><%= @metadata['publisher'] %></dc:publisher>
|
12
|
+
<dc:subject><%= @metadata['subject'] %></dc:subject>
|
13
|
+
<dc:date xsi:type="dcterms:W3CDTF">2012-01-01</dc:date>
|
14
|
+
<dc:description><%= @metadata['description'] %></dc:description>
|
15
|
+
<dc:rights><%= @metadata['copyright'] %></dc:rights>
|
16
|
+
</metadata>
|
17
|
+
|
18
|
+
<manifest>
|
19
|
+
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" />
|
20
|
+
<item id="css" href="epub.css" media-type="text/css" />
|
21
|
+
<%= manifest_items %>
|
22
|
+
</manifest>
|
23
|
+
|
24
|
+
<spine toc="ncx">
|
25
|
+
<%= spine_items %>
|
26
|
+
</spine>
|
27
|
+
|
28
|
+
<guide>
|
29
|
+
<reference type="toc" title="Table of Contents" href="toc.html" />
|
30
|
+
<reference type="text" title="Text" href="covertext.html" />
|
31
|
+
</guide>
|
32
|
+
|
33
|
+
</package>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
5
|
+
<meta name="language" content="de">
|
6
|
+
<link rel="stylesheet" type="text/css" href="epub.css" media="screen">
|
7
|
+
</head>
|
8
|
+
<body>
|
9
|
+
<%= @body %>
|
10
|
+
</body>
|
11
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<item href="<%= filename %>" id="<%= id %>" media-type="<%= mediatype %>"/>
|
@@ -0,0 +1 @@
|
|
1
|
+
<itemref idref="<%= id %>" />
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN" "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">
|
3
|
+
|
4
|
+
<ncx xmlns="http://www.daisy.org/z3986/2005/ncx/" version="2005-1">
|
5
|
+
|
6
|
+
<head>
|
7
|
+
<meta name="dtb:uid" content="http://www.hxa7241.org/articles/content/epup-guide_hxa7241_2007_2.epub"/>
|
8
|
+
<meta name="dtb:depth" content="2"/>
|
9
|
+
<meta name="dtb:totalPageCount" content="0"/>
|
10
|
+
<meta name="dtb:maxPageNumber" content="0"/>
|
11
|
+
</head>
|
12
|
+
|
13
|
+
<docTitle>
|
14
|
+
<text><%= @name %></text>
|
15
|
+
</docTitle>
|
16
|
+
|
17
|
+
<navMap>
|
18
|
+
<%= nav_points %>
|
19
|
+
</navMap>
|
20
|
+
|
21
|
+
</ncx>
|
data/lib/publishr.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# PublishR -- Fast publishing for ebooks and paper
|
2
|
+
# Copyright (C) 2012 Michael Franzl
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU Affero General Public License as
|
6
|
+
# published by the Free Software Foundation, either version 3 of the
|
7
|
+
# License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require 'kramdown'
|
19
|
+
require 'erb'
|
20
|
+
require 'yaml'
|
21
|
+
require 'fileutils'
|
22
|
+
|
23
|
+
require 'publishr/project'
|
24
|
+
require 'publishr/markup_processor'
|
25
|
+
require 'publishr/epub_renderer'
|
26
|
+
require 'publishr/latex_processor'
|
27
|
+
require 'publishr/latex_renderer'
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# PublishR -- Fast publishing for ebooks and paper
|
2
|
+
# Copyright (C) 2012 Michael Franzl
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU Affero General Public License as
|
6
|
+
# published by the Free Software Foundation, either version 3 of the
|
7
|
+
# License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module Publishr
|
19
|
+
class EpubRenderer
|
20
|
+
def initialize(name,inpath,outpath,metadata)
|
21
|
+
@name = name
|
22
|
+
@inpath = inpath
|
23
|
+
@outpath = outpath
|
24
|
+
@metadata = metadata
|
25
|
+
@gempath = File.expand_path('../../../', __FILE__)
|
26
|
+
|
27
|
+
@html_files = []
|
28
|
+
@image_files = []
|
29
|
+
end
|
30
|
+
|
31
|
+
def render
|
32
|
+
make_epub_directory_structure
|
33
|
+
render_htmls
|
34
|
+
compile_xmls
|
35
|
+
end
|
36
|
+
|
37
|
+
def make_epub_directory_structure
|
38
|
+
FileUtils.rm_rf @outpath
|
39
|
+
FileUtils.cp_r File.join(@gempath,'lib','epub_skeleton'), @outpath
|
40
|
+
FileUtils.cp Dir[File.join(@inpath,'..','images','*.jpg')], @outpath
|
41
|
+
FileUtils.cp Dir[File.join(@inpath,'images','*.jpg')], @outpath
|
42
|
+
FileUtils.cp File.join(@inpath,'cover.jpg'), @outpath
|
43
|
+
@image_files = Dir[File.join(@outpath,'*.jpg')]
|
44
|
+
# users can provide an overriding css file
|
45
|
+
FileUtils.cp_f File.join(@inpath,'epub.css'), @outpath if File.exists?(File.join(@inpath,'epub.css'))
|
46
|
+
end
|
47
|
+
|
48
|
+
def render_htmls
|
49
|
+
kramdown_options = {
|
50
|
+
:auto_ids => false,
|
51
|
+
:smart_quotes => ["sbquo", "lsquo", "bdquo", "ldquo"],
|
52
|
+
:template => File.join(@gempath,'lib','epub_templates','kramdown.html')
|
53
|
+
}
|
54
|
+
Dir[File.join(@inpath,'*.txt')].each do |infilepath|
|
55
|
+
kramdown = File.open(infilepath, 'r').read
|
56
|
+
html = Kramdown::Document.new(kramdown, kramdown_options).to_html
|
57
|
+
degraded_html = MarkupProcessor.new(html,@metadata).degrade
|
58
|
+
outfilepath = File.join(@outpath, File.basename(infilepath).gsub(/(.*).txt/, '\1.html'))
|
59
|
+
File.open(outfilepath, 'w'){ |f| f.write degraded_html }
|
60
|
+
end
|
61
|
+
@html_files = ([File.join(@outpath,'covertext.html')] + [File.join(@outpath,'frontmatter.html')] + [File.join(@outpath,'toc.html')] + Dir[File.join(@outpath,'*.html')].sort).uniq
|
62
|
+
end
|
63
|
+
|
64
|
+
def compile_xmls
|
65
|
+
File.open(File.join(@outpath,'content.opf'),'w'){ |f| f.write render_content_opf }
|
66
|
+
File.open(File.join(@outpath,'toc.ncx'),'w'){ |f| f.write render_toc_ncx }
|
67
|
+
Dir.chdir @outpath
|
68
|
+
filename = File.join(@inpath,"#{ @name }.epub")
|
69
|
+
`zip -X0 #{ filename } mimetype`
|
70
|
+
`zip -Xur9D #{ filename } *`
|
71
|
+
end
|
72
|
+
|
73
|
+
def render_content_opf
|
74
|
+
erb = File.open(File.join(@gempath,'lib','epub_templates','content.opf.erb'),'r').read
|
75
|
+
spine_items = render_spine_items
|
76
|
+
manifest_items = render_manifest_items
|
77
|
+
ERB.new(erb).result binding
|
78
|
+
end
|
79
|
+
|
80
|
+
def render_toc_ncx
|
81
|
+
erb = File.open(File.join(@gempath,'lib','epub_templates','toc.ncx.erb'),'r').read
|
82
|
+
nav_points = render_nav_points
|
83
|
+
ERB.new(erb).result binding
|
84
|
+
end
|
85
|
+
|
86
|
+
def render_nav_points
|
87
|
+
erb = File.open(File.join(@gempath,'lib','epub_templates','nav_points.erb'),'r').read
|
88
|
+
results = []
|
89
|
+
i = 0
|
90
|
+
@html_files.each do |h|
|
91
|
+
filename = File.basename(h)
|
92
|
+
id = filename.gsub '.',''
|
93
|
+
i += 1
|
94
|
+
results << (ERB.new(erb).result binding)
|
95
|
+
end
|
96
|
+
results.join("\n")
|
97
|
+
end
|
98
|
+
|
99
|
+
def render_manifest_items
|
100
|
+
image_files = Dir[File.join(@outpath,'*.jpg')]
|
101
|
+
erb = File.open(File.join(@gempath,'lib','epub_templates','manifest_items.erb'),'r').read
|
102
|
+
results = []
|
103
|
+
(@html_files + @image_files).each do |h|
|
104
|
+
filename = File.basename(h)
|
105
|
+
id = filename.gsub '.',''
|
106
|
+
mediatype = case File.extname(h)
|
107
|
+
when '.html' then 'application/xhtml+xml'
|
108
|
+
when '.jpg' then 'image/jpeg'
|
109
|
+
when '.png' then 'image/png'
|
110
|
+
end
|
111
|
+
results << (ERB.new(erb).result binding)
|
112
|
+
end
|
113
|
+
results.join("\n")
|
114
|
+
end
|
115
|
+
|
116
|
+
def render_spine_items
|
117
|
+
erb = File.open(File.join(@gempath,'lib','epub_templates','spine_items.erb'),'r').read
|
118
|
+
results = []
|
119
|
+
@html_files.each do |h|
|
120
|
+
id = File.basename(h).gsub '.',''
|
121
|
+
results << (ERB.new(erb).result binding)
|
122
|
+
end
|
123
|
+
results.join("\n")
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Encoding: UTF-8
|
2
|
+
|
3
|
+
# PublishR -- Fast publishing for ebooks and paper
|
4
|
+
# Copyright (C) 2012 Michael Franzl
|
5
|
+
#
|
6
|
+
# This program is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Affero General Public License as
|
8
|
+
# published by the Free Software Foundation, either version 3 of the
|
9
|
+
# License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Affero General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Affero General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module Publishr
|
21
|
+
class LatexProcessor
|
22
|
+
def initialize(latex,inpath)
|
23
|
+
@lines = latex.split("\n")
|
24
|
+
@line = ''
|
25
|
+
@inpath = inpath
|
26
|
+
|
27
|
+
@custom_fixes = File.open(File.join(@inpath,'latex_postprocessing.rb'), 'r').read if File.exists?(File.join(@inpath,'latex_postprocessing.rb', 'r'))
|
28
|
+
@global_fixes = File.open(File.join(@inpath,'..','latex_postprocessing.rb'), 'r').read if File.exists?(File.join(@inpath,'..','latex_postprocessing.rb'))
|
29
|
+
end
|
30
|
+
|
31
|
+
def fix
|
32
|
+
processed_lines = []
|
33
|
+
@lines.each do |l|
|
34
|
+
@line = l
|
35
|
+
process_line
|
36
|
+
processed_lines << @line
|
37
|
+
end
|
38
|
+
processed_lines.join("\n")
|
39
|
+
end
|
40
|
+
|
41
|
+
def process_line
|
42
|
+
@line.gsub! /.hypertarget{.*?}{}/, ''
|
43
|
+
@line.gsub! /.label{.*?}/, ''
|
44
|
+
|
45
|
+
# latex uses eps, so remove jpg ending
|
46
|
+
@line.gsub! /(.includegraphics{.*?).jpg}/, '\1}'
|
47
|
+
|
48
|
+
# better formatting for names, book titles and technical terms
|
49
|
+
@line.gsub! /name\((.*?)\)/, '\name{\1}'
|
50
|
+
@line.gsub! /title\((.*?)\)/, '\book{\1}'
|
51
|
+
@line.gsub! /{\\tt (.*?)}/, '\object{\1}'
|
52
|
+
|
53
|
+
# covert kramdown css attributes to LaTeX environments
|
54
|
+
@line.gsub! /{quot(.*?)} % class="(.*?)"/, '{quot\1\2}'
|
55
|
+
@line.gsub! /{quote}/, '{quotenormal}'
|
56
|
+
@line.gsub! /{quotation}/, '{quotationnormal}'
|
57
|
+
|
58
|
+
# transform custom kramdown comments
|
59
|
+
@line.gsub! '% bigskip', "\\bigskip"
|
60
|
+
@line.gsub! '% pagebreak', "\\pagebreak[4]"
|
61
|
+
@line.gsub! '% newpage', "\\newpage"
|
62
|
+
|
63
|
+
# bind ellipsis to previous word
|
64
|
+
@line.gsub! /(\w \\ldots{})/, '\\mbox{\1}'
|
65
|
+
|
66
|
+
# set better space for [...]
|
67
|
+
@line.gsub! /\[\\ldots{}\]/, '\\omission{}'
|
68
|
+
|
69
|
+
# separate thousands, beginning with 10000
|
70
|
+
@line.gsub! /(\d\d)(\d\d\d) /, '\1\\,\2 '
|
71
|
+
|
72
|
+
@line.gsub! '°', '\\textdegree'
|
73
|
+
|
74
|
+
eval(@custom_fixes, binding) if @custom_fixes
|
75
|
+
eval(@global_fixes, binding) if @global_fixes
|
76
|
+
|
77
|
+
# use correct hyphen code for better automatic hyphenation
|
78
|
+
@line.gsub! /(\w)-(\w)/, '\1\\hyp{}\2'
|
79
|
+
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# PublishR -- Fast publishing for ebooks and paper
|
2
|
+
# Copyright (C) 2012 Michael Franzl
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU Affero General Public License as
|
6
|
+
# published by the Free Software Foundation, either version 3 of the
|
7
|
+
# License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module Publishr
|
19
|
+
class LatexRenderer
|
20
|
+
def initialize(name,path)
|
21
|
+
@name = name
|
22
|
+
@inpath = path
|
23
|
+
@outpath = File.join(@inpath,'latex')
|
24
|
+
@gempath = File.expand_path('../../../', __FILE__)
|
25
|
+
end
|
26
|
+
|
27
|
+
def render
|
28
|
+
make_tex_directory_structure
|
29
|
+
render_tex
|
30
|
+
end
|
31
|
+
|
32
|
+
def make_tex_directory_structure
|
33
|
+
FileUtils.mkdir_p @outpath
|
34
|
+
FileUtils.cp Dir[File.join(@inpath,'..','images','*.jpg')], @outpath
|
35
|
+
FileUtils.cp Dir[File.join(@inpath,'images','*.jpg')], @outpath
|
36
|
+
FileUtils.cp_r File.join(@gempath,'lib','tex_templates','book.tex'), @outpath
|
37
|
+
FileUtils.cp_r File.join(@inpath,'preamble.tex'), @outpath
|
38
|
+
end
|
39
|
+
|
40
|
+
def render_tex
|
41
|
+
kramdown_options = {
|
42
|
+
:latex_headers => ['chapter*', "section*", "subsection*", "subsubsection*", "paragraph*", "subparagraph*"],
|
43
|
+
:smart_quotes => ["sbquo", "lsquo", "bdquo", "ldquo"]
|
44
|
+
}
|
45
|
+
Dir[File.join(@inpath,'*.txt')].each do |infilepath|
|
46
|
+
kramdown = File.open(infilepath, 'r').read
|
47
|
+
latex = Kramdown::Document.new(kramdown, kramdown_options).to_latex
|
48
|
+
fixed_latex = LatexProcessor.new(latex,@inpath).fix
|
49
|
+
outfilepath = File.join(@outpath, File.basename(infilepath).gsub(/(.*).txt/, '\1.tex'))
|
50
|
+
File.open(outfilepath, 'w'){ |f| f.write fixed_latex }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Publishr
|
3
|
+
class MarkupProcessor
|
4
|
+
def initialize(markup,metadata)
|
5
|
+
@lines = markup.split("\n")
|
6
|
+
@line = ''
|
7
|
+
@metadata = metadata
|
8
|
+
|
9
|
+
@depth = 0
|
10
|
+
@quotetype = nil
|
11
|
+
@add_footnote = false
|
12
|
+
@process_footnotes = false
|
13
|
+
@footnote_number = 0
|
14
|
+
@footnote_reference = ''
|
15
|
+
end
|
16
|
+
|
17
|
+
def degrade
|
18
|
+
processed_lines = []
|
19
|
+
@lines.each do |l|
|
20
|
+
@line = l
|
21
|
+
process_line
|
22
|
+
processed_lines << @line
|
23
|
+
end
|
24
|
+
processed_lines.join("\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_line
|
28
|
+
@process_footnotes = true if @line.include?('<div class="footnotes">')
|
29
|
+
@process_footnotes = false if @process_footnotes == true and @line.include?('</div>')
|
30
|
+
@add_footnote = true and @footnote_number += 1 if @line.include?('<li id="fn')
|
31
|
+
|
32
|
+
annotate_blockquote
|
33
|
+
improve_typography
|
34
|
+
make_uppercase
|
35
|
+
change_footnote_references
|
36
|
+
process_footnotes if @process_footnotes == true
|
37
|
+
add_footnote if @add_footnote == true and @line.include?('<p>')
|
38
|
+
end
|
39
|
+
|
40
|
+
def improve_typography
|
41
|
+
@line.gsub! '<em>', '<b>'
|
42
|
+
@line.gsub! '</em>', '</b>'
|
43
|
+
@line.gsub!(/title\((.*?)\)/,'<cite>\1</cite>')
|
44
|
+
@line.gsub!(/name\((.*?)\)/,'<var>\1</var>')
|
45
|
+
@line.gsub!(/(\(\w\))/,'<i>\1</i>')
|
46
|
+
|
47
|
+
if @language == 'de'
|
48
|
+
@line.gsub!(/([FA]:)/,'<b>\1</b>')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Kindle doesn't recognize <blockquote>, so add class to p tags depending on the blockquote depth
|
54
|
+
def annotate_blockquote
|
55
|
+
if @line.include?('<blockquote')
|
56
|
+
@depth += 1
|
57
|
+
@quotetype = /<blockquote class="(.*?)">/.match(@line) if @depth == 1
|
58
|
+
end
|
59
|
+
if @line.include?('</blockquote')
|
60
|
+
@depth -= 1
|
61
|
+
@quotetype = nil if @depth.zero?
|
62
|
+
end
|
63
|
+
@line.gsub!(/<p/,"<p class=\"blockquote_#{ @quotetype[1] if @quotetype }_#{ @depth }\"") unless @depth.zero?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Kindle doesn't recognize text-transform: uppercase;
|
67
|
+
def make_uppercase
|
68
|
+
@line.gsub!(/<var>(.*?)<\/var>/){ "<cite>#{ $1.upcase }</cite>" }
|
69
|
+
@line.gsub!(/<h1(.*?)>(.*?)<\/h1>/){ "<h1#{ $1 }>#{ $2.upcase }</h1><hr />" }
|
70
|
+
end
|
71
|
+
|
72
|
+
def change_footnote_references
|
73
|
+
@line.gsub! /<sup id="fnref:.*?">/, ''
|
74
|
+
@line.gsub! '</sup>', ''
|
75
|
+
@line.gsub! /rel="footnote">(.*?)<\/a>/, '> [\1]</a>'
|
76
|
+
@line.gsub!(/(<div class=.footnotes.>)/){ "<br style='page-break-before:always;'>#{ $1 }<h4>#{ @metadata['footnote_heading'] }</h4>" }
|
77
|
+
end
|
78
|
+
|
79
|
+
def process_footnotes
|
80
|
+
@line.gsub!(/<p(.*?)>/){ "<p>" }
|
81
|
+
@footnote_reference = /<li (id="fn.*")/.match(@line)[1] if @line.include?('<li id="fn')
|
82
|
+
@line.gsub! /<li id="fn.*>/, ''
|
83
|
+
@line.gsub! /<\/li>/, ''
|
84
|
+
@line.gsub! /<ol>/, ''
|
85
|
+
@line.gsub! /<\/ol>/, ''
|
86
|
+
@line.gsub! /<a href="#fnref.*<\/a>/, ''
|
87
|
+
end
|
88
|
+
|
89
|
+
# Kindle doesn't display <ol> list numbers when jumping to a footnote, so replace them with conventional text
|
90
|
+
def add_footnote
|
91
|
+
@line.gsub! /<p>/, "<hr><p class='footnote' #{ @footnote_reference }><b>[#{ @footnote_number }]</b>: "
|
92
|
+
@add_footnote = false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# PublishR -- Fast publishing for ebooks and paper
|
2
|
+
# Copyright (C) 2012 Michael Franzl
|
3
|
+
#
|
4
|
+
# This program is free software: you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU Affero General Public License as
|
6
|
+
# published by the Free Software Foundation, either version 3 of the
|
7
|
+
# License, or (at your option) any later version.
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU Affero General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Affero General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
module Publishr
|
19
|
+
class Project
|
20
|
+
def initialize(name,relativepath,converterspath)
|
21
|
+
@name = name
|
22
|
+
@inpath = File.join(Dir.pwd,relativepath)
|
23
|
+
@converterspath = File.join(Dir.pwd,converterspath)
|
24
|
+
|
25
|
+
@metadata = YAML::load(File.open(File.join(@inpath,'metadata.yml'), 'r').read)
|
26
|
+
end
|
27
|
+
|
28
|
+
def make_kindle
|
29
|
+
outpath = File.join(@inpath,'epub')
|
30
|
+
epub = EpubRenderer.new(@name,@inpath,outpath,@metadata)
|
31
|
+
epub.render
|
32
|
+
binaryfile = File.join(@converterspath,'kindlegen')
|
33
|
+
epubfile = File.join(@inpath,"#{ @name }.epub")
|
34
|
+
IO.popen("#{ binaryfile } -verbose #{ epubfile }") do |io|
|
35
|
+
while (line = io.gets) do
|
36
|
+
puts line
|
37
|
+
end
|
38
|
+
end
|
39
|
+
FileUtils.rm_r outpath
|
40
|
+
FileUtils.cp File.join(@inpath,"#{ @name }.mobi"), '/media/Kindle/documents'
|
41
|
+
end
|
42
|
+
|
43
|
+
def make_pdf
|
44
|
+
pdf = LatexRenderer.new(@name,@inpath)
|
45
|
+
pdf.render
|
46
|
+
|
47
|
+
outpath = File.join(@inpath,'latex')
|
48
|
+
binaryfile = File.join(@converterspath,'jpeg2ps')
|
49
|
+
Dir[File.join(outpath,'*.jpg')].each do |infilepath|
|
50
|
+
outfilepath = File.join(outpath, File.basename(infilepath).gsub(/(.*).jpg/, '\1.eps'))
|
51
|
+
`#{ binaryfile } -r 0 -o #{ outfilepath } #{ infilepath }`
|
52
|
+
end
|
53
|
+
|
54
|
+
Dir.chdir outpath
|
55
|
+
IO.popen('pdflatex preamble.tex') do |io|
|
56
|
+
while (line = io.gets) do
|
57
|
+
puts line
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
FileUtils.mv File.join(outpath,'preamble.pdf'), File.join(@inpath,"#{ @name }.pdf")
|
62
|
+
#FileUtils.rm_r outpath
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
data/publishr.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "publishr/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "publishr"
|
7
|
+
s.version = Publishr::VERSION
|
8
|
+
s.authors = ["Michael Franzl"]
|
9
|
+
s.email = ["michael@billgastro.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Fast publishing for ebooks and paper}
|
12
|
+
s.description = %q{Fast publishing for ebooks and paper}
|
13
|
+
|
14
|
+
s.rubyforge_project = "publishr"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: publishr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Franzl
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-02 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description: Fast publishing for ebooks and paper
|
15
|
+
email:
|
16
|
+
- michael@billgastro.com
|
17
|
+
executables:
|
18
|
+
- publishr
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- Rakefile
|
25
|
+
- bin/publishr
|
26
|
+
- lib/epub_skeleton/META-INF/container.xml
|
27
|
+
- lib/epub_skeleton/epub.css
|
28
|
+
- lib/epub_skeleton/mimetype
|
29
|
+
- lib/epub_templates/content.opf.erb
|
30
|
+
- lib/epub_templates/kramdown.html
|
31
|
+
- lib/epub_templates/manifest_items.erb
|
32
|
+
- lib/epub_templates/nav_points.erb
|
33
|
+
- lib/epub_templates/spine_items.erb
|
34
|
+
- lib/epub_templates/toc.ncx.erb
|
35
|
+
- lib/publishr.rb
|
36
|
+
- lib/publishr/epub_renderer.rb
|
37
|
+
- lib/publishr/latex_processor.rb
|
38
|
+
- lib/publishr/latex_renderer.rb
|
39
|
+
- lib/publishr/markup_processor.rb
|
40
|
+
- lib/publishr/project.rb
|
41
|
+
- lib/publishr/version.rb
|
42
|
+
- publishr.gemspec
|
43
|
+
homepage: ''
|
44
|
+
licenses: []
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project: publishr
|
63
|
+
rubygems_version: 1.8.10
|
64
|
+
signing_key:
|
65
|
+
specification_version: 3
|
66
|
+
summary: Fast publishing for ebooks and paper
|
67
|
+
test_files: []
|