bookchef 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rdoc"
10
+ gem "bundler"
11
+ gem "jeweler"
12
+ gem 'rspec'
13
+ gem 'sass'
14
+ gem 'equivalent-xml'
15
+ gem 'nokogiri-diff'
16
+ end
17
+
18
+ gem "pdfkit", "0.5.0"
19
+ gem "nokogiri"
20
+ gem "ruby-xslt"
@@ -0,0 +1,47 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.3)
5
+ equivalent-xml (0.3.0)
6
+ nokogiri (>= 1.4.3)
7
+ git (1.2.5)
8
+ jeweler (1.8.4)
9
+ bundler (~> 1.0)
10
+ git (>= 1.2.5)
11
+ rake
12
+ rdoc
13
+ json (1.7.6)
14
+ nokogiri (1.5.5)
15
+ nokogiri-diff (0.1.2)
16
+ nokogiri (~> 1.5)
17
+ tdiff (~> 0.3, >= 0.3.2)
18
+ pdfkit (0.5.0)
19
+ rake (10.0.3)
20
+ rdoc (3.12)
21
+ json (~> 1.4)
22
+ rspec (2.12.0)
23
+ rspec-core (~> 2.12.0)
24
+ rspec-expectations (~> 2.12.0)
25
+ rspec-mocks (~> 2.12.0)
26
+ rspec-core (2.12.2)
27
+ rspec-expectations (2.12.1)
28
+ diff-lcs (~> 1.1.3)
29
+ rspec-mocks (2.12.2)
30
+ ruby-xslt (0.9.9)
31
+ sass (3.2.5)
32
+ tdiff (0.3.3)
33
+
34
+ PLATFORMS
35
+ ruby
36
+
37
+ DEPENDENCIES
38
+ bundler
39
+ equivalent-xml
40
+ jeweler
41
+ nokogiri
42
+ nokogiri-diff
43
+ pdfkit (= 0.5.0)
44
+ rdoc
45
+ rspec
46
+ ruby-xslt
47
+ sass
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Roman Snitko
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "bookchef"
18
+ gem.homepage = "http://github.com/snitko/bookchef"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Parser and compiler for BookChef.xml format}
21
+ gem.email = "roman.snitko@gmail.com"
22
+ gem.authors = ["Roman Snitko"]
23
+ gem.executables << 'bookchef'
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ task :default => :test
29
+
30
+ require 'rdoc/task'
31
+ Rake::RDocTask.new do |rdoc|
32
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
33
+ rdoc.rdoc_dir = 'rdoc'
34
+ rdoc.title = "bookchef #{version}"
35
+ rdoc.rdoc_files.include('README*')
36
+ rdoc.rdoc_files.include('lib/**/*.rb')
37
+ end
38
+
39
+ require 'sass'
40
+ task :compile_css do
41
+ `sass --update --scss lib/bookchef/stylesheets/scss/:lib/bookchef/stylesheets/css`
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.7
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require "bookchef"
3
+
4
+ case ARGV[0]
5
+
6
+ when "merge_tree"
7
+ parser = BookChef::TreeMerger.new(ARGV[1], "index.xml")
8
+ parser.run
9
+ parser.save_to ARGV[2]
10
+
11
+ when "make_html"
12
+ parser = BookChef::Compiler::HTML.new(ARGV[1])
13
+ parser.run
14
+ parser.save_to ARGV[2]
15
+
16
+ when "make_pdf"
17
+ html = File.read(ARGV[1])
18
+ compiler = BookChef::Compiler::PDF.new(html, output_file: ARGV[2], html_footer: ARGV[3] )
19
+ compiler.compile
20
+
21
+ else
22
+ puts "Usage: bookchef [command] [input_file_or_dir] [output_file]"
23
+ puts "Commands are:"
24
+ puts " merge_tree - merges book xml files into one xml file,"
25
+ puts " first argument must be a dir containing an index.xml file."
26
+ puts " make_html - compiles that one big xml file into an html"
27
+ puts " make_pdf - compiles html into a pdf file"
28
+
29
+ end
@@ -0,0 +1,38 @@
1
+ require "rubygems"
2
+
3
+ require "nokogiri"
4
+ require "xml/xslt"
5
+ require "pdfkit"
6
+
7
+ require "bookchef/tree_merger"
8
+ require "bookchef/compilers/html"
9
+ require "bookchef/compilers/pdf"
10
+
11
+ class BookChef
12
+ LIB_PATH = File.expand_path(File.dirname(__FILE__) + "/bookchef")
13
+
14
+ class << self
15
+
16
+ # Converts XML special characrters into temporary identifiable entities
17
+ # for later backwards conversion by BookChef compilers.
18
+ def protect_special_chars(s)
19
+ # erb tags
20
+ s.gsub!(/<%(.*?)%>/, '#lt;%\1%#gt;')
21
+ # all xml entities
22
+ s.gsub!(/&([a-zA-Z0-9#]*?);/, '#\1;')
23
+ # standalone ampersand chars
24
+ s.gsub!('&', '#amp;')
25
+ return s
26
+ end
27
+
28
+ def decode_special_chars(s)
29
+ s.gsub(/#([a-zA-Z0-9#]*?);/, '&\1;')
30
+ end
31
+
32
+ def replace_https_with_http(s)
33
+ s.gsub('href="https://', 'href="http://')
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -0,0 +1,30 @@
1
+ class BookChef
2
+ class Compiler
3
+
4
+ # Converts XML into HTML using xslt
5
+ class HTML
6
+
7
+ attr_reader :document, :result
8
+
9
+ def initialize(fn, xslt_stylesheet="#{BookChef::LIB_PATH}/stylesheets/xslt/bookchef_to_html.xsl")
10
+ xslt_stylesheet = File.read(xslt_stylesheet).sub('#{gem_path}', "file://#{BookChef::LIB_PATH}")
11
+ @document = XML::XSLT.new
12
+ @document.xml = fn
13
+ @document.xsl = xslt_stylesheet
14
+ end
15
+
16
+ def run
17
+ @result = BookChef.decode_special_chars(@document.serve)
18
+ @result = BookChef.replace_https_with_http(@result)
19
+ end
20
+
21
+ def save_to(fn)
22
+ f = File.open(fn, "w")
23
+ f.write @result
24
+ f.close
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,60 @@
1
+ class BookChef
2
+ class Compiler
3
+
4
+ # Converts HTML into PDF using PDFKit
5
+ class PDF
6
+
7
+ require "tmpdir"
8
+ require 'digest/md5'
9
+
10
+ def initialize(html_input, options = {})
11
+
12
+ @html_input = html_input
13
+ default_options = {
14
+ output_file: "/tmp/output.pdf",
15
+ footer_html_file: "#{BookChef::LIB_PATH}/templates/footer.html",
16
+ footer_custom_html: ""
17
+ }
18
+ @options = default_options.merge(options)
19
+
20
+ create_footer
21
+
22
+ @pdf = PDFKit.new(
23
+ @html_input,
24
+ enable_external_links: true,
25
+ enable_internal_links: true,
26
+ footer_html: @options[:temp_footer_filename]
27
+ )
28
+
29
+ end
30
+
31
+ def compile
32
+ @pdf.to_file(@options[:output_file])
33
+ after_compile
34
+ end
35
+
36
+
37
+ private
38
+
39
+ def create_footer
40
+ # Taking Footer CSS from the html_input css
41
+ stylesheet_tag = @html_input.match(/<link href=".*?" rel="stylesheet" type="text\/css"\/?>/)
42
+
43
+ footer_html = File.read(@options[:footer_html_file])
44
+ @options[:temp_footer_filename] = "#{Dir.tmpdir}/bookchef_footer_#{Digest::MD5.hexdigest(Time.now.to_s)}_#{rand(100)}.html"
45
+
46
+ File.open(@options[:temp_footer_filename], "w") do |f|
47
+ footer_html.gsub!('#{footer_text}', @options[:footer_custom_html])
48
+ footer_html += stylesheet_tag.to_s if stylesheet_tag # Applying css to Footer
49
+ f.write footer_html
50
+ end
51
+ end
52
+
53
+ def after_compile
54
+ File.unlink(@options[:temp_footer_filename]) if File.exists?(@options[:footer_html_file])
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,152 @@
1
+ body {
2
+ font-family: "Liberation Serif", "Times New Roman";
3
+ line-height: 150%; }
4
+
5
+ code, .code.inline {
6
+ font-family: "Monaco";
7
+ font-size: 80%;
8
+ background-color: #eee; }
9
+
10
+ code {
11
+ display: block;
12
+ clear: both;
13
+ margin: 1em 0;
14
+ padding: 0.5em;
15
+ white-space: pre;
16
+ line-height: 120%; }
17
+
18
+ p {
19
+ margin: 0 0 0 0;
20
+ text-indent: 1em;
21
+ text-align: justify; }
22
+
23
+ span.name, span.filename, span.keyboard {
24
+ font-family: "Monaco";
25
+ font-size: 80%; }
26
+
27
+ img {
28
+ clear: both;
29
+ display: block;
30
+ margin: 2em 1em;
31
+ width: 80%;
32
+ page-break-inside: avoid; }
33
+
34
+ .footnotes {
35
+ font-size: 80%;
36
+ margin: 1em;
37
+ border: dotted 1px #aaaaaa;
38
+ padding: 1em 1em 0 1em;
39
+ page-break-inside: avoid; }
40
+ .footnotes .footnote {
41
+ margin-bottom: 1em; }
42
+
43
+ .references {
44
+ font-style: italic;
45
+ font-size: 80%;
46
+ margin: 1em;
47
+ border: dotted 1px #aaaaaa;
48
+ padding: 1em 1em 0 1em;
49
+ page-break-inside: avoid; }
50
+ .references img {
51
+ margin: 0 0.5em 0 0;
52
+ margin-bottom: -0.3em;
53
+ display: inline;
54
+ width: 16px; }
55
+ .references .reference {
56
+ margin-bottom: 1em; }
57
+
58
+ .footnotes, .references {
59
+ font-size: 70%;
60
+ line-height: 120%; }
61
+
62
+ h1 {
63
+ page-break-inside: avoid; }
64
+
65
+ .chapter {
66
+ page-break-before: always; }
67
+ .chapter h1 {
68
+ font-size: 270%;
69
+ line-height: 100%; }
70
+ .chapter .section {
71
+ margin-top: 2em; }
72
+ .chapter .section h1 {
73
+ font-size: 220%; }
74
+ .chapter .section .section {
75
+ margin-top: 1.7em; }
76
+ .chapter .section .section h1 {
77
+ font-size: 190%; }
78
+ .chapter .section .section .section {
79
+ margin-top: 1.5em; }
80
+ .chapter .section .section .section h1 {
81
+ font-size: 170%; }
82
+ .chapter .section .section .section .section {
83
+ margin-top: 1.3em; }
84
+ .chapter .section .section .section .section h1 {
85
+ font-size: 140%; }
86
+ .chapter .section .section .section .section .section {
87
+ margin-top: 1.1em; }
88
+ .chapter .section .section .section .section .section h1 {
89
+ font-size: 125%; }
90
+
91
+ p.frameDescription {
92
+ font-style: italic;
93
+ font-size: 80%;
94
+ margin: 1.5em 0 -0.5em 0;
95
+ text-indent: 0px; }
96
+
97
+ .cover {
98
+ page-break-after: always; }
99
+ .cover img {
100
+ width: 100%; }
101
+
102
+ .tableOfContents {
103
+ page-break-after: always;
104
+ font-size: 120%; }
105
+ .tableOfContents ul {
106
+ list-style-type: none;
107
+ margin: 0 0 0 0;
108
+ padding: 0 0 0 0; }
109
+
110
+ table {
111
+ margin: 1.5em 1em;
112
+ page-break-inside: avoid;
113
+ border-collapse: collapse; }
114
+ table td {
115
+ vertical-align: top; }
116
+ table td, table th {
117
+ border: solid 1px #aaaaaa;
118
+ padding: 0.5em;
119
+ margin-top: 1.5em;
120
+ font-size: 80%; }
121
+
122
+ ul, ol {
123
+ margin-left: 2em; }
124
+ ul li, ol li {
125
+ margin: 0.5em 0; }
126
+
127
+ sup {
128
+ height: 0;
129
+ line-height: 1;
130
+ vertical-align: baseline;
131
+ _vertical-align: bottom;
132
+ position: relative;
133
+ bottom: 1ex; }
134
+
135
+ .footer {
136
+ border-top: solid 1px #cccccc;
137
+ paddign-top: 1em;
138
+ font-size: 80%;
139
+ line-height: 100%; }
140
+ .footer .text {
141
+ float: left;
142
+ width: 80%;
143
+ color: #aaa; }
144
+ .footer .info {
145
+ float: right;
146
+ width: 20%;
147
+ text-align: right;
148
+ font-weight: bold; }
149
+
150
+ .insertPageBreak {
151
+ page-break-after: always;
152
+ height: 1px; }