markover 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +102 -0
  4. data/bin/markover +31 -0
  5. data/config/style.css +174 -0
  6. data/ext/github_markup.rb +11 -0
  7. data/lib/markover.rb +31 -0
  8. data/lib/markover/config.rb +28 -0
  9. data/lib/markover/converter.rb +120 -0
  10. data/lib/markover/markup.rb +28 -0
  11. data/lib/markover/markup/code.rb +40 -0
  12. data/lib/markover/markup/code_block.rb +30 -0
  13. data/lib/markover/markup/renderer.rb +67 -0
  14. data/lib/markover/markup/yaml_frontmatter_remover.rb +17 -0
  15. data/lib/markover/markupfile.rb +67 -0
  16. data/lib/markover/optionparser.rb +93 -0
  17. data/lib/markover/path.rb +29 -0
  18. data/lib/markover/version.rb +6 -0
  19. data/lib/markover/wkhtmltopdf.rb +39 -0
  20. data/spec/fixtures/autolink_url.md +3 -0
  21. data/spec/fixtures/code_block.textile +8 -0
  22. data/spec/fixtures/code_block_with_utf8.textile +7 -0
  23. data/spec/fixtures/code_with_utf8.textile +6 -0
  24. data/spec/fixtures/integration/markdown.md +60 -0
  25. data/spec/fixtures/integration/style.css +3 -0
  26. data/spec/fixtures/integration/textile.textile +47 -0
  27. data/spec/fixtures/long_code_block.md +5 -0
  28. data/spec/fixtures/recursion/level1.textile +1 -0
  29. data/spec/fixtures/recursion/level2/level2.markdown +1 -0
  30. data/spec/fixtures/table.md +7 -0
  31. data/spec/fixtures/yaml_front_matter.textile +7 -0
  32. data/spec/integration_spec.rb +41 -0
  33. data/spec/markover/converter_spec.rb +124 -0
  34. data/spec/markover/markup/code_block_spec.rb +21 -0
  35. data/spec/markover/markup/code_spec.rb +45 -0
  36. data/spec/markover/markup/renderer_spec.rb +18 -0
  37. data/spec/markover/markup/yaml_frontmatter_remover_spec.rb +21 -0
  38. data/spec/markover/markup_file_spec.rb +45 -0
  39. data/spec/markover/path_spec.rb +32 -0
  40. data/spec/markover/wkhtmltopdf_spec.rb +35 -0
  41. data/spec/spec_helper.rb +11 -0
  42. metadata +228 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: daa4c691576601fd45a61afe55986a5c08835013
4
+ data.tar.gz: dc00fd881aeb4c08e8bb4b935e2f444171cc32e2
5
+ SHA512:
6
+ metadata.gz: 981805f3b6b6096b7d31783561ac32e67bce34c27fcbb1dece16c9825403fbd9e147993ba6388d8d1bf3a2276842a294696d5371618c058334ef029b3bc9f53d
7
+ data.tar.gz: 6f4ea2ad54aae0dbe214589c98ddacfbc5707d2b7ac9db50c97afa829eb004aff7fbc9e49b90a06d066810ee5e9e8203d8418704a72d3d9de1429d63c06afaff
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Benjamin Kammerl aka phortx
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,102 @@
1
+ # markover
2
+
3
+ [![Build Status](https://travis-ci.org/phortx/markover.png?branch=master)](https://travis-ci.org/phortx/markover)
4
+
5
+ ## Description
6
+ markover is a utility for converting markup (markdown, textile, ...) to PDF files. Useful for reports, documentations and such things.
7
+
8
+ It's a fork of the dead [gimli gem](https://github.com/phortx/markover.git).
9
+
10
+ It supports ...
11
+ - ... multiple markup styles
12
+ - ... syntax highlighting
13
+ - ... covers
14
+ - ... CSS
15
+ - ... images
16
+ - ... table of contents
17
+ - and more.
18
+
19
+ It works by converting the markup to pdf using [wkhtmltopdf](https://github.com/antialize/wkhtmltopdf)
20
+ The markup is converted to html using [github/markup](https://github.com/github/markup)
21
+
22
+
23
+ ## Markup
24
+ Markup files may be written in any format supported by GitHub-Markup (except roff).
25
+
26
+
27
+ ## Images
28
+ Images can be included by absolute url on your hard drive or a absolute url on the Internet. You can also refer to an image relative from the markup file. Example in markdown.
29
+
30
+ ```markdown
31
+ ![test.jpg](/tmp/test.jpg)
32
+ ![wiki.png](http://upload.wikimedia.org/wikipedia/en/b/bc/Wiki.png)
33
+ ![test.jpg](../images/test.jpg)
34
+ ```
35
+
36
+ ## Installation
37
+ The best way to install markoverf is with RubyGems:
38
+
39
+ ```bash
40
+ $ gem install markover
41
+ ```
42
+
43
+ You can also install from source:
44
+
45
+ ```bash
46
+ $ git clone https://github.com/phortx/markover.git
47
+ $ cd markover
48
+ $ bundle
49
+ $ rake install
50
+ ```
51
+
52
+ ## Usage
53
+ The standard way to run markover is to go to a folder with markup files and running `markover`
54
+
55
+
56
+ ### Own CSS
57
+ To apply some style to the pdf or override the standard style add a css file in the directory named `markover.css` or use the `-s` flag to point out another css file.
58
+
59
+
60
+ ### Output file
61
+ Standard behavior is for md2pd to output the files in the current directory. To override this use the `-o` flag to point out another output directory. markover tries to create it if it doesn't exist.
62
+
63
+
64
+ ### Jekyll
65
+ markover also plays nice with Jekyll style markup files. You can pass markover the `-y` flag to have it remove Jekyll's YAML front matter from the top of your markup files. Allowing you to use markover & Jekyll together on your Blog/Resume/Catalogue to create nicely formatted versions for online and offline viewing.
66
+
67
+
68
+ ### wkhtmlpdf
69
+ To pass parameters directly to wkhtmltopdf, use the `-w` flag. eg.
70
+
71
+ ```bash
72
+ $ markover -f test.md -w '--toc --footer-right "[page]/[toPage]"'
73
+ ```
74
+
75
+ This gives a pdf with a table of contents and page numbers in the footer.
76
+
77
+ See the [man page](http://wkhtmltopdf.org/usage/wkhtmltopdf.txt) for wkhtmltopdf for all possible parameters.
78
+
79
+
80
+ ### Everything else
81
+ Run `markover -h` for a full list of options available.
82
+
83
+
84
+
85
+ ## Syntax highlighting
86
+ In page files you can get automatic syntax highlighting for a wide range of languages by using the following syntax:
87
+
88
+ <pre lang="no-highlight"><code>
89
+ ```ruby
90
+ def foo
91
+ puts 'bar'
92
+ end
93
+ ```
94
+ </pre>
95
+
96
+ The block must start with three backticks (as the first characters on the line). After that comes the name of the language that is contained by the block. The language must be one of the short name lexer strings supported by coderay. See the list of lexers for valid options.
97
+
98
+ If the block contents are indented two spaces or one tab, then that whitespace will be ignored (this makes the blocks easier to read in plaintext).
99
+
100
+ The block must end with three backticks as the first characters on a line.
101
+
102
+ The syntax highlightning is powered by [coderay](https://github.com/rubychan/coderay) and is using a [github theme](https://github.com/pie4dan/CodeRay-GitHub-Theme).
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + '/../lib/')
4
+
5
+ require 'markover'
6
+ require 'markover/optionparser'
7
+ require 'markover/path'
8
+ require 'markover/markupfile'
9
+
10
+ files = []
11
+ options = Markover::Parser.parse!(ARGV)
12
+
13
+ ARGV.each do |target|
14
+ files += Markover::Path.list_valid(target, options[:recursive]).map { |file| Markover::MarkupFile.new(file) }
15
+ end
16
+
17
+ config = Markover.configure do |config|
18
+ config.files = files
19
+ config.recursive = options[:recursive]
20
+ config.merge = options[:merge]
21
+ config.debug = options[:debug]
22
+ config.wkhtmltopdf_parameters = options[:wkhtmltopdfparameters]
23
+ config.remove_front_matter = options[:removefrontmatter]
24
+ config.output_filename = options[:filename]
25
+ config.output_dir = options[:outputdir]
26
+ config.stylesheet = options[:stylesheet]
27
+ config.table_of_contents = options[:table_of_contents]
28
+ end
29
+
30
+ Markover.process! config
31
+
@@ -0,0 +1,174 @@
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; }
144
+
145
+ .code pre {
146
+ white-space: pre;
147
+ white-space: pre-wrap;
148
+ word-break: break-all;
149
+ word-wrap: break-word;
150
+ }
151
+
152
+ table {
153
+ width: 100%;
154
+ overflow: auto;
155
+ display: block;
156
+ }
157
+
158
+ table th {
159
+ font-weight: bold;
160
+ }
161
+
162
+ table th, table td {
163
+ border: 1px solid #ddd;
164
+ padding: 6px 13px;
165
+ }
166
+
167
+ table tr {
168
+ border-top: 1px solid #ccc;
169
+ background-color: #fff;
170
+ }
171
+
172
+ table tr:nth-child(2n) {
173
+ background-color: #f8f8f8;
174
+ }
@@ -0,0 +1,11 @@
1
+ # Monkey patch github markup to use redcarpet with support for autolinks and tables
2
+ module GitHub::Markup
3
+ alias_method :old_render, :render
4
+ def render(filename, content = nil)
5
+ if Regexp.compile("\\.(md|mkdn?|mdwn|mdown|markdown|litcoffee)$") =~ filename
6
+ Redcarpet::Markdown.new(Redcarpet::Render::HTML, :autolink => true, :tables => true).render(content)
7
+ else
8
+ old_render(filename, content)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require 'markover/version'
4
+ require 'markover/config'
5
+ require 'markover/markupfile'
6
+ require 'markover/converter'
7
+ require 'markover/path'
8
+ require 'markover/wkhtmltopdf'
9
+
10
+ require File.expand_path(File.dirname(__FILE__)) + '/../ext/github_markup.rb'
11
+
12
+ module Markover
13
+
14
+ # Create a config object
15
+ # @example Example usage
16
+ # config = Markover.configure |config| do
17
+ # config.file = './test.md'
18
+ # config.output_dir = '/tmp'
19
+ # config.table_of_contents = true
20
+ # end
21
+ def self.configure
22
+ config = Config.new
23
+ yield config
24
+ config
25
+ end
26
+
27
+ # Starts the processing of selected files
28
+ def self.process!(config)
29
+ Converter.new(config.files, config).convert!
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+
3
+ module Markover
4
+
5
+ # Class that keeps the config parameters
6
+ class Config
7
+ attr_accessor :recursive,
8
+ :merge,
9
+ :debug,
10
+ :wkhtmltopdf_parameters,
11
+ :remove_front_matter,
12
+ :output_filename,
13
+ :output_dir,
14
+ :stylesheet,
15
+ :files,
16
+ :table_of_contents
17
+
18
+ # Sets default values
19
+ def initialize
20
+ @recursive = false
21
+ @merge = false
22
+ @debug = false
23
+ @page_numbers = false
24
+ @table_of_contents = false
25
+ @remove_front_matter = false
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,120 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fileutils'
4
+
5
+ require 'markover/markup'
6
+
7
+ module Markover
8
+
9
+ # The class that converts the files
10
+ class Converter
11
+
12
+ # Initialize the converter with a File
13
+ # @param [Array] files The list of Markover::MarkupFile to convert (passing a single file will still work)
14
+ # @param [Markover::Config] config
15
+ def initialize(files, config)
16
+ @files, @config = files, config
17
+
18
+ @stylesheets = []
19
+ @wkhtmltopdf = Wkhtmltopdf.new @config.wkhtmltopdf_parameters
20
+ end
21
+
22
+ # Convert the file and save it as a PDF file
23
+ def convert!
24
+ merged_contents = []
25
+ @files.each do |file|
26
+ markup = Markup::Renderer.new file, @config.remove_front_matter
27
+ html = convert_image_urls markup.render, file.filename
28
+ if @config.merge
29
+ html = "<div class=\"page-break\"></div>#{html}" unless merged_contents.empty?
30
+ merged_contents << html
31
+ else
32
+ output_pdf(html, file)
33
+ end
34
+ puts html if @config.debug
35
+ end
36
+
37
+ unless merged_contents.empty?
38
+ html = merged_contents.join
39
+ output_pdf(html, nil)
40
+ end
41
+ end
42
+
43
+ # Rewrite relative image urls to absolute
44
+ # @param [String] html some html to parse
45
+ # @return [String] the html with all image urls replaced to absolute
46
+ def convert_image_urls(html, filename)
47
+ dir_string = ::File.dirname(::File.expand_path(filename))
48
+ html.scan(/<img[^>]+src="([^"]+)"/).each do |url|
49
+ html.gsub!(url[0], ::File.expand_path(url[0], dir_string)) unless url[0] =~ /^https?/
50
+ end
51
+
52
+ html
53
+ end
54
+
55
+ # Create the pdf
56
+ # @param [String] html the html input
57
+ # @param [String] filename the name of the output file
58
+ def output_pdf(html, filename)
59
+ load_stylesheets
60
+ append_stylesheets html
61
+ add_head html
62
+ @wkhtmltopdf.output_pdf html, output_file(filename)
63
+ end
64
+
65
+ def add_head(html)
66
+ html.insert(0, "\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n</head>\n")
67
+ end
68
+
69
+ # Load the stylesheets to pdfkit loads the default and the user selected if any
70
+ def load_stylesheets
71
+ # Load standard stylesheet
72
+ style = ::File.expand_path("../../../config/style.css", __FILE__)
73
+ @stylesheets << style
74
+ @stylesheets << stylesheet if ::File.exists?(stylesheet)
75
+ end
76
+
77
+ def append_stylesheets(html)
78
+ @stylesheets.each do |stylesheet|
79
+ html.insert(0, style_tag_for(stylesheet))
80
+ end
81
+ end
82
+
83
+ def style_tag_for(stylesheet)
84
+ "<style>#{File.read(stylesheet)}</style>"
85
+ end
86
+
87
+ # Returns the selected stylesheet. Defaults to ./markover.css
88
+ # @return [String]
89
+ def stylesheet
90
+ @config.stylesheet.nil? ? 'markover.css' : @config.stylesheet
91
+ end
92
+
93
+ # Returns the directory where to save the output. Defaults to ./
94
+ # @return [String]
95
+ def output_dir
96
+ output_dir = @config.output_dir.nil? ? Dir.getwd : @config.output_dir
97
+ FileUtils.mkdir_p(output_dir) unless ::File.directory?(output_dir)
98
+ output_dir
99
+ end
100
+
101
+ # Generate the name of the output file
102
+ # @return [String]
103
+ # @param [Markover::MarkupFile] file optionally, specify a file, otherwise use output filename
104
+ def output_file(file = nil)
105
+ if file
106
+ output_filename = file.name
107
+ if !@config.output_filename.nil? && @files.length == 1
108
+ output_filename = @config.output_filename
109
+ end
110
+ else
111
+ output_filename = Time.now.to_s.split(' ').join('_')
112
+ output_filename = @files.last.name if @files.length == 1 || @config.merge
113
+ output_filename = @config.output_filename unless @config.output_filename.nil?
114
+ end
115
+
116
+ ::File.join(output_dir, "#{output_filename}.pdf")
117
+ end
118
+ end
119
+ end
120
+