grandfather 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/grandfather +17 -0
- data/config/style.css +143 -0
- data/grandfather.gemspec +34 -0
- data/lib/grandfather.rb +28 -0
- data/lib/grandfather/code.rb +27 -0
- data/lib/grandfather/codeblock.rb +22 -0
- data/lib/grandfather/combine.rb +79 -0
- data/lib/grandfather/config.rb +14 -0
- data/lib/grandfather/md.rb +30 -0
- data/lib/grandfather/path.rb +24 -0
- data/lib/grandfather/render.rb +48 -0
- data/lib/grandfather/version.rb +6 -0
- data/lib/grandfather/wkhtmltopdf.rb +27 -0
- metadata +203 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3fa2b601b810ee56dc785e6160f311ce014e6ebe
|
4
|
+
data.tar.gz: 6c06a10331f32770cc19829b6c63c2d12971d8d7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 74c22b99cc4faa607357e6ec5d99020dfb9535fc5905d8aab709a10d9373781ba75bf1b6a51e49d9b7500f0b3a017136bca3422b86eda0c0fd352bdce70c38cd
|
7
|
+
data.tar.gz: fc39a40e08ef7e365dbab8429ced2d1a3e769b17abd79f488f88da0084844c3bf77548cc4c28ad5ca21e4b58108837a4c6d695472309d565d0fc7e56be399d30
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Sean Darcy
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Grandfather
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'grandfather'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install grandfather
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/grandfather
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'pry'
|
3
|
+
require 'byebug'
|
4
|
+
|
5
|
+
#$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + '/../lib/')
|
6
|
+
|
7
|
+
require_relative '../lib/grandfather'
|
8
|
+
|
9
|
+
#if ARGV.flags.version?
|
10
|
+
# puts "Version: #{Grandfather::VERSION}"
|
11
|
+
# exit
|
12
|
+
#end
|
13
|
+
|
14
|
+
config = Grandfather.configure do |config|
|
15
|
+
end
|
16
|
+
|
17
|
+
Grandfather.process! config
|
data/config/style.css
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
body
|
2
|
+
{
|
3
|
+
font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Sans", Arial, sans-serif;
|
4
|
+
font-size: 12px;
|
5
|
+
}
|
6
|
+
|
7
|
+
.page-break
|
8
|
+
{
|
9
|
+
page-break-before: always;
|
10
|
+
}
|
11
|
+
|
12
|
+
.CodeRay {
|
13
|
+
background-color: #FFF;
|
14
|
+
border: 1px solid #CCC;
|
15
|
+
font-family: Monaco, "Courier New", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", monospace;
|
16
|
+
color: #000;
|
17
|
+
padding: 1em 0px 1em 1em;
|
18
|
+
}
|
19
|
+
|
20
|
+
.CodeRay pre {
|
21
|
+
margin: 0px;
|
22
|
+
}
|
23
|
+
|
24
|
+
div.CodeRay { }
|
25
|
+
span.CodeRay { white-space: pre; border: 0px; padding: 2px }
|
26
|
+
|
27
|
+
table.CodeRay { border-collapse: collapse; width: 100%; padding: 2px }
|
28
|
+
table.CodeRay td {
|
29
|
+
padding: 1em 0.5em;
|
30
|
+
vertical-align: top;
|
31
|
+
}
|
32
|
+
|
33
|
+
.CodeRay .line-numbers, .CodeRay .no {
|
34
|
+
background-color: #ECECEC;
|
35
|
+
color: #AAA;
|
36
|
+
text-align: right;
|
37
|
+
}
|
38
|
+
|
39
|
+
.CodeRay .line-numbers a {
|
40
|
+
color: #AAA;
|
41
|
+
}
|
42
|
+
|
43
|
+
.CodeRay .line-numbers tt { font-weight: bold }
|
44
|
+
.CodeRay .line-numbers .highlighted { color: red }
|
45
|
+
.CodeRay .line { display: block; float: left; width: 100%; }
|
46
|
+
.CodeRay span.line-numbers { padding: 0px 4px }
|
47
|
+
.CodeRay .code { width: 100% }
|
48
|
+
|
49
|
+
ol.CodeRay { font-size: 10pt }
|
50
|
+
ol.CodeRay li { white-space: pre }
|
51
|
+
|
52
|
+
.CodeRay .code pre { overflow: auto }
|
53
|
+
.CodeRay .debug { color:white ! important; background:blue ! important; }
|
54
|
+
|
55
|
+
.CodeRay .annotation { color:#007 }
|
56
|
+
.CodeRay .attribute-name { color:#f08 }
|
57
|
+
.CodeRay .attribute-value { color:#700 }
|
58
|
+
.CodeRay .binary { color:#509; font-weight:bold }
|
59
|
+
.CodeRay .comment { color:#998; font-style: italic;}
|
60
|
+
.CodeRay .char { color:#04D }
|
61
|
+
.CodeRay .char .content { color:#04D }
|
62
|
+
.CodeRay .char .delimiter { color:#039 }
|
63
|
+
.CodeRay .class { color:#458; font-weight:bold }
|
64
|
+
.CodeRay .complex { color:#A08; font-weight:bold }
|
65
|
+
.CodeRay .constant { color:teal; }
|
66
|
+
.CodeRay .color { color:#0A0 }
|
67
|
+
.CodeRay .class-variable { color:#369 }
|
68
|
+
.CodeRay .decorator { color:#B0B; }
|
69
|
+
.CodeRay .definition { color:#099; font-weight:bold }
|
70
|
+
.CodeRay .directive { color:#088; font-weight:bold }
|
71
|
+
.CodeRay .delimiter { color:black }
|
72
|
+
.CodeRay .doc { color:#970 }
|
73
|
+
.CodeRay .doctype { color:#34b }
|
74
|
+
.CodeRay .doc-string { color:#D42; font-weight:bold }
|
75
|
+
.CodeRay .escape { color:#666; font-weight:bold }
|
76
|
+
.CodeRay .entity { color:#800; font-weight:bold }
|
77
|
+
.CodeRay .error { color:#F00; background-color:#FAA }
|
78
|
+
.CodeRay .exception { color:#C00; font-weight:bold }
|
79
|
+
.CodeRay .filename { color:#099; }
|
80
|
+
.CodeRay .function { color:#900; font-weight:bold }
|
81
|
+
.CodeRay .global-variable { color:teal; font-weight:bold }
|
82
|
+
.CodeRay .hex { color:#058; font-weight:bold }
|
83
|
+
.CodeRay .integer { color:#099; }
|
84
|
+
.CodeRay .include { color:#B44; font-weight:bold }
|
85
|
+
.CodeRay .inline { color: black }
|
86
|
+
.CodeRay .inline .inline { background: #ccc }
|
87
|
+
.CodeRay .inline .inline .inline { background: #bbb }
|
88
|
+
.CodeRay .inline .inline-delimiter { color: #D14; }
|
89
|
+
.CodeRay .inline-delimiter { color: #D14; }
|
90
|
+
.CodeRay .important { color:#f00; }
|
91
|
+
.CodeRay .interpreted { color:#B2B; font-weight:bold }
|
92
|
+
.CodeRay .instance-variable { color:teal }
|
93
|
+
.CodeRay .label { color:#970; font-weight:bold }
|
94
|
+
.CodeRay .local-variable { color:#963 }
|
95
|
+
.CodeRay .octal { color:#40E; font-weight:bold }
|
96
|
+
.CodeRay .operator { }
|
97
|
+
.CodeRay .predefined-constant { font-weight:bold }
|
98
|
+
.CodeRay .predefined { color:#369; font-weight:bold }
|
99
|
+
.CodeRay .preprocessor { color:#579; }
|
100
|
+
.CodeRay .pseudo-class { color:#00C; font-weight:bold }
|
101
|
+
.CodeRay .predefined-type { color:#074; font-weight:bold }
|
102
|
+
.CodeRay .reserved, .keyword { color:#000; font-weight:bold }
|
103
|
+
|
104
|
+
.CodeRay .key { color: #808; }
|
105
|
+
.CodeRay .key .delimiter { color: #606; }
|
106
|
+
.CodeRay .key .char { color: #80f; }
|
107
|
+
.CodeRay .value { color: #088; }
|
108
|
+
|
109
|
+
.CodeRay .regexp { background-color:#fff0ff }
|
110
|
+
.CodeRay .regexp .content { color:#808 }
|
111
|
+
.CodeRay .regexp .delimiter { color:#404 }
|
112
|
+
.CodeRay .regexp .modifier { color:#C2C }
|
113
|
+
.CodeRay .regexp .function { color:#404; font-weight: bold }
|
114
|
+
|
115
|
+
.CodeRay .string { color: #D20; }
|
116
|
+
.CodeRay .string .string { }
|
117
|
+
.CodeRay .string .string .string { background-color:#ffd0d0 }
|
118
|
+
.CodeRay .string .content { color: #D14; }
|
119
|
+
.CodeRay .string .char { color: #D14; }
|
120
|
+
.CodeRay .string .delimiter { color: #D14; }
|
121
|
+
|
122
|
+
.CodeRay .shell { color:#D14 }
|
123
|
+
.CodeRay .shell .content { }
|
124
|
+
.CodeRay .shell .delimiter { color:#D14 }
|
125
|
+
|
126
|
+
.CodeRay .symbol { color:#990073 }
|
127
|
+
.CodeRay .symbol .content { color:#A60 }
|
128
|
+
.CodeRay .symbol .delimiter { color:#630 }
|
129
|
+
|
130
|
+
.CodeRay .tag { color:#070 }
|
131
|
+
.CodeRay .tag-special { color:#D70; font-weight:bold }
|
132
|
+
.CodeRay .type { color:#339; font-weight:bold }
|
133
|
+
.CodeRay .variable { color:#036 }
|
134
|
+
|
135
|
+
.CodeRay .insert { background: #afa; }
|
136
|
+
.CodeRay .delete { background: #faa; }
|
137
|
+
.CodeRay .change { color: #aaf; background: #007; }
|
138
|
+
.CodeRay .head { color: #f8f; background: #505 }
|
139
|
+
|
140
|
+
.CodeRay .insert .insert { color: #080; font-weight:bold }
|
141
|
+
.CodeRay .delete .delete { color: #800; font-weight:bold }
|
142
|
+
.CodeRay .change .change { color: #66f; }
|
143
|
+
.CodeRay .head .head { color: #f4f; }
|
data/grandfather.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'grandfather/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "grandfather"
|
8
|
+
spec.version = Grandfather::VERSION
|
9
|
+
spec.authors = "Sean Darcy"
|
10
|
+
spec.email = "darcys22@gmail.com"
|
11
|
+
spec.description = "Utility for combining several markdown chapters of a book into a single pdf"
|
12
|
+
spec.summary = "Utility for combining chapters into single pdf"
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
|
17
|
+
spec.add_dependency 'redcarpet', '~> 2.1.1'
|
18
|
+
spec.add_dependency 'RedCloth', '~> 4.2.7'
|
19
|
+
spec.add_dependency 'coderay', '~> 1.0.7'
|
20
|
+
spec.add_dependency 'nokogiri', '~> 1.5.5'
|
21
|
+
spec.add_dependency "wkhtmltopdf-binary", "~> 0.9.9.1"
|
22
|
+
spec.add_dependency 'optiflag', '~> 0.7'
|
23
|
+
|
24
|
+
|
25
|
+
spec.files = `git ls-files`.split($/)
|
26
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
27
|
+
#spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency "rake"
|
31
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
32
|
+
spec.add_development_dependency "byebug"
|
33
|
+
spec.add_development_dependency "pry"
|
34
|
+
end
|
data/lib/grandfather.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require_relative 'grandfather/version'
|
4
|
+
require_relative 'grandfather/config'
|
5
|
+
require_relative 'grandfather/md'
|
6
|
+
require_relative 'grandfather/combine'
|
7
|
+
require_relative 'grandfather/render'
|
8
|
+
require_relative 'grandfather/code'
|
9
|
+
require_relative 'grandfather/codeblock'
|
10
|
+
require_relative 'grandfather/wkhtmltopdf'
|
11
|
+
require_relative 'grandfather/path'
|
12
|
+
|
13
|
+
module Grandfather
|
14
|
+
|
15
|
+
# Create a config object
|
16
|
+
def self.configure
|
17
|
+
config = Config.new
|
18
|
+
yield config
|
19
|
+
config
|
20
|
+
end
|
21
|
+
|
22
|
+
# Starts processing files
|
23
|
+
def self.process!(config)
|
24
|
+
@files = Path.list_valid(config.file, config.recursive).map { |file| Md.new(file) }
|
25
|
+
Combine.new(@files, config).combine!
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Grandfather
|
4
|
+
class Code
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@code_blocks = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def extract(data)
|
11
|
+
data.gsub!(/^``` ?([^\r\n]+)?\r?\n(.+?)\r?\n```\r?$/m) do
|
12
|
+
id = Digest::SHA1.hexdigest($2)
|
13
|
+
@code_blocks << CodeBlock.new(id, $1, $2)
|
14
|
+
end
|
15
|
+
data
|
16
|
+
end
|
17
|
+
|
18
|
+
def process(data)
|
19
|
+
return data if data.nil? || data.size.zero? || @code_blocks.size.zero?
|
20
|
+
@code_blocks.each do |block|
|
21
|
+
data.gsub!(block.id, block.highlighted)
|
22
|
+
end
|
23
|
+
data
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'coderay'
|
4
|
+
|
5
|
+
module Grandfather
|
6
|
+
|
7
|
+
class CodeBlock
|
8
|
+
attr_reader :id, :language, :code
|
9
|
+
|
10
|
+
def initialize(id, language, code)
|
11
|
+
@id, @language, @code = id, language, code
|
12
|
+
end
|
13
|
+
|
14
|
+
def highlighted
|
15
|
+
if @language
|
16
|
+
CodeRay.scan(@code, @language).html(:line_numbers => :table)
|
17
|
+
else
|
18
|
+
CodeRay.scan(@code, :text).div
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Grandfather
|
6
|
+
|
7
|
+
class Combine
|
8
|
+
def initialize(files, config)
|
9
|
+
@files, @config = files, config
|
10
|
+
|
11
|
+
@stylesheets = []
|
12
|
+
@wkhtmltopdf = Wkhtmltopdf.new @config.wkhtmltopdf_parameters
|
13
|
+
end
|
14
|
+
|
15
|
+
def combine!
|
16
|
+
merged_contents = []
|
17
|
+
@files.each do |file|
|
18
|
+
markup = Renderer.new file
|
19
|
+
merged_contents << markup.render
|
20
|
+
merged_contents << "<div class=\"page-break\"></div>"
|
21
|
+
end
|
22
|
+
|
23
|
+
unless merged_contents.empty?
|
24
|
+
output_pdf(merged_contents.join, nil)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def output_pdf(html, filename)
|
29
|
+
load_stylesheets
|
30
|
+
append_stylesheets html
|
31
|
+
add_head html
|
32
|
+
@wkhtmltopdf.output_pdf html, output_file(filename)
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_head(html)
|
36
|
+
html.insert(0, "\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n</head>\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
def load_stylesheets
|
40
|
+
style = ::File.expand_path("../../../config/style.css", __FILE__)
|
41
|
+
@stylesheets << style
|
42
|
+
@stylesheets << stylesheet if ::File.exists?(stylesheet)
|
43
|
+
end
|
44
|
+
|
45
|
+
def append_stylesheets(html)
|
46
|
+
@stylesheets.each do |stylesheet|
|
47
|
+
html.insert(0, style_tag_for(stylesheet))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def style_tag_for(stylesheet)
|
52
|
+
"<Style>#{File.read(stylesheet)}</style>"
|
53
|
+
end
|
54
|
+
|
55
|
+
def stylesheet
|
56
|
+
@config.stylesheet.nil? ? 'default.css' : @config.stylesheet
|
57
|
+
end
|
58
|
+
|
59
|
+
def output_dir
|
60
|
+
output_dir = @config.output_dir.nil? ? Dir.getwd : @config.output_dir
|
61
|
+
FileUtils.mkdir_p*output_dir unless ::File.directory?(output_dir)
|
62
|
+
output_dir
|
63
|
+
end
|
64
|
+
|
65
|
+
def output_file(file = nil)
|
66
|
+
if file
|
67
|
+
output_filename = file.name
|
68
|
+
if !@config.output_filename.nil? && @files.length == 1
|
69
|
+
output_filename = @config.output_filename
|
70
|
+
end
|
71
|
+
else
|
72
|
+
output_filename = "default"
|
73
|
+
end
|
74
|
+
|
75
|
+
::File.join(output_dir, "#{output_filename}.pdf")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Grandfather
|
4
|
+
|
5
|
+
# Class for config params
|
6
|
+
class Config
|
7
|
+
attr_accessor :output_filename, :file, :recursive, :wkhtmltopdf_parameters, :stylesheet, :output_dir
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@output_filename = "Book.pdf"
|
11
|
+
@recursive = false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Grandfather
|
4
|
+
|
5
|
+
# Class load files and determine if valid
|
6
|
+
class Md
|
7
|
+
attr_reader :filename, :name, :data
|
8
|
+
|
9
|
+
def initialize(filename)
|
10
|
+
@filename = filename
|
11
|
+
@extension = ::File.extname(@filename)
|
12
|
+
@name = ::File.basename(@filename, @extension)
|
13
|
+
@data = ::File.open(@filename, 'rb' ) { |f| f.read } if ::File.exists?(@filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
def valid?
|
17
|
+
valid_format? @extension
|
18
|
+
end
|
19
|
+
|
20
|
+
def valid_format?(format)
|
21
|
+
# All the files are missing extensions, if it has an extension it is wrong
|
22
|
+
# kinda hacky not happy with it
|
23
|
+
format.empty?
|
24
|
+
#return false if format.nil?
|
25
|
+
|
26
|
+
#format.to_sym == :md
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding utf-8
|
2
|
+
|
3
|
+
module Grandfather
|
4
|
+
|
5
|
+
class Path
|
6
|
+
|
7
|
+
def self.list_valid(target, recursive = false)
|
8
|
+
if recursive
|
9
|
+
target ||= Dir.pwd
|
10
|
+
if File.directory?(target)
|
11
|
+
target = File.join(target, '**', '*')
|
12
|
+
end
|
13
|
+
else
|
14
|
+
target ||= Dir.pwd
|
15
|
+
if File.directory?(target)
|
16
|
+
target = File.join(target, '*')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
@what = Dir.glob(target).select { |file| Md.new(file).valid? }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Grandfather
|
4
|
+
|
5
|
+
class Renderer
|
6
|
+
|
7
|
+
require 'redcarpet'
|
8
|
+
require 'nokogiri'
|
9
|
+
|
10
|
+
def initialize(file)
|
11
|
+
@file = file
|
12
|
+
|
13
|
+
@data = file.data
|
14
|
+
@code = Code.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def render
|
18
|
+
prepare_data
|
19
|
+
render_data
|
20
|
+
post_process_data
|
21
|
+
|
22
|
+
return @data
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def prepare_data
|
28
|
+
@data = @code.extract(@data)
|
29
|
+
end
|
30
|
+
|
31
|
+
def render_data(content = nil)
|
32
|
+
begin
|
33
|
+
@data = @data.force_encoding('utf-8') if @data.respond_to? :force_encoding
|
34
|
+
@data = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :tables => true).render(@data)
|
35
|
+
if @data.nil?
|
36
|
+
raise "There was an error converting #{@file.name} to HTML."
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def post_process_data
|
42
|
+
@data = @code.process(@data)
|
43
|
+
doc = Nokogiri::HTML::DocumentFragment.parse(@data, 'UTF-8')
|
44
|
+
@data = doc.to_xhtml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XHTML, :encoding => 'UTF-8')
|
45
|
+
@data.gsub!(/<p><\/P>/, '')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Grandfather
|
2
|
+
class Wkhtmltopdf
|
3
|
+
|
4
|
+
def initialize(parameters = nil)
|
5
|
+
@parameters = parameters
|
6
|
+
end
|
7
|
+
|
8
|
+
def output_pdf(html, filename)
|
9
|
+
args = command(filename)
|
10
|
+
invoke = args.join(' ')
|
11
|
+
|
12
|
+
IO.popen(invoke, "wb+") do |pdf|
|
13
|
+
pdf.puts(html)
|
14
|
+
pdf.close_write
|
15
|
+
pdf.gets(nil)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def command(filename)
|
20
|
+
[bin, @parameters, '--quiet', '-', "\"#{filename}\""].compact
|
21
|
+
end
|
22
|
+
|
23
|
+
def bin
|
24
|
+
@bin ||= "\"#{(`which wkhtmltopdf`).chomp}\""
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: grandfather
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sean Darcy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: redcarpet
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.1.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.1.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: RedCloth
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.2.7
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.2.7
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: coderay
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.0.7
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.0.7
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: nokogiri
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.5.5
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.5.5
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: wkhtmltopdf-binary
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.9.9.1
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.9.9.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: optiflag
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.7'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.7'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: bundler
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.3'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ~>
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.3'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: byebug
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pry
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: Utility for combining several markdown chapters of a book into a single
|
154
|
+
pdf
|
155
|
+
email: darcys22@gmail.com
|
156
|
+
executables:
|
157
|
+
- grandfather
|
158
|
+
extensions: []
|
159
|
+
extra_rdoc_files: []
|
160
|
+
files:
|
161
|
+
- .gitignore
|
162
|
+
- Gemfile
|
163
|
+
- LICENSE.txt
|
164
|
+
- README.md
|
165
|
+
- Rakefile
|
166
|
+
- bin/grandfather
|
167
|
+
- config/style.css
|
168
|
+
- grandfather.gemspec
|
169
|
+
- lib/grandfather.rb
|
170
|
+
- lib/grandfather/code.rb
|
171
|
+
- lib/grandfather/codeblock.rb
|
172
|
+
- lib/grandfather/combine.rb
|
173
|
+
- lib/grandfather/config.rb
|
174
|
+
- lib/grandfather/md.rb
|
175
|
+
- lib/grandfather/path.rb
|
176
|
+
- lib/grandfather/render.rb
|
177
|
+
- lib/grandfather/version.rb
|
178
|
+
- lib/grandfather/wkhtmltopdf.rb
|
179
|
+
homepage: ''
|
180
|
+
licenses:
|
181
|
+
- MIT
|
182
|
+
metadata: {}
|
183
|
+
post_install_message:
|
184
|
+
rdoc_options: []
|
185
|
+
require_paths:
|
186
|
+
- lib
|
187
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
188
|
+
requirements:
|
189
|
+
- - '>='
|
190
|
+
- !ruby/object:Gem::Version
|
191
|
+
version: '0'
|
192
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
193
|
+
requirements:
|
194
|
+
- - '>='
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
197
|
+
requirements: []
|
198
|
+
rubyforge_project:
|
199
|
+
rubygems_version: 2.1.11
|
200
|
+
signing_key:
|
201
|
+
specification_version: 4
|
202
|
+
summary: Utility for combining chapters into single pdf
|
203
|
+
test_files: []
|