grandfather 1.0.0
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.
- 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: []
|