gimli 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Fredrik Wallgren
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
20
+
@@ -0,0 +1,60 @@
1
+ h1. gimli - utility for converting markup to pdf
2
+
3
+ h2. Description
4
+
5
+ Gimli is a utility for converting markup to pdf files. Useful for reports and such things.
6
+ It's inspired by the markup convertion in "gollum":https://github.com/github/gollum
7
+ It works by converting the markup to html using "PDFKit":https://github.com/jdpace/PDFKit
8
+ The markup is converted to html using "github/markup":https://github.com/github/markup
9
+
10
+ h3. Markup
11
+
12
+ Markup files may be written in any format supported by GitHub-Markup (except roff).
13
+
14
+ h2. Installation
15
+
16
+ The best way to install Gimli is with RubyGems:
17
+
18
+ bc. $ [sudo] gem install gimli
19
+
20
+ You can install from source:
21
+
22
+ bc. $ cd gimli/
23
+ $ bundle
24
+ $ rake install
25
+
26
+ h2. Running
27
+
28
+ The standard way to run gimli is to go to a folder with markup files and running
29
+
30
+ bc. $ gimli
31
+
32
+ To apply some style to the pdf or override the standard style add a css file in the directory named @gimli.css@ or use the @-s@ flag to point out another css file.
33
+
34
+ Standard behavior is for gimli to output the files in the current directory. To override this use the @-o@ flag to point out another output directory. Gimli tries to create it if it doesn't exist.
35
+
36
+ Run @gimli -h@ for a full list of options available
37
+
38
+ h2. Syntax highlighting
39
+
40
+ In page files you can get automatic syntax highlighting for a wide range of languages by using the following syntax:
41
+
42
+ If you want to be able to use the syntax highlightning you have to install "pygments":http://pygments.org
43
+
44
+ Example installation on Ubuntu
45
+
46
+ bc. $ sudo aptitude install python-setuptools
47
+ $ sudo easy_install pygments
48
+
49
+ bc. ```ruby
50
+ def foo
51
+ puts 'bar'
52
+ end
53
+ ```
54
+
55
+ 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 Pygments. See the list of lexers for valid options.
56
+
57
+ 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).
58
+
59
+ The block must end with three backticks as the first characters on a line.
60
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+
5
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + '/../lib/')
6
+
7
+ require 'gimli'
8
+
9
+ Gimli.process!
10
+
@@ -0,0 +1,109 @@
1
+ body
2
+ {
3
+ font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Sans", Arial, sans-serif;
4
+ font-size: 12px;
5
+ }
6
+
7
+ /* Code */
8
+ code, tt
9
+ {
10
+ background-color: #f8f8f8;
11
+ border: 1px solid #dedede;
12
+ font-size: 13px;
13
+ padding: 1px 5px;
14
+
15
+ -moz-border-radius: 3px;
16
+ -webkit-border-radius: 3px;
17
+ border-radius: 3px;
18
+ }
19
+
20
+ .highlight pre, pre
21
+ {
22
+ background-color: #f8f8f8;
23
+ border: 1px solid #ccc;
24
+ font-size: 13px;
25
+ line-height: 19px;
26
+ overflow: auto;
27
+ padding: 6px;
28
+
29
+ -moz-border-radius: 3px;
30
+ -webkit-border-radius: 3px;
31
+ border-radius: 3px;
32
+ }
33
+
34
+ pre code, pre tt
35
+ {
36
+ background-color: transparent;
37
+ border: none;
38
+ }
39
+
40
+ .highlight .hll { background-color: #ffffcc }
41
+ .highlight .c { color: #8f5902; font-style: italic } /* Comment */
42
+ .highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */
43
+ .highlight .g { color: #000000 } /* Generic */
44
+ .highlight .k { color: #204a87; font-weight: bold } /* Keyword */
45
+ .highlight .l { color: #000000 } /* Literal */
46
+ .highlight .n { color: #000000 } /* Name */
47
+ .highlight .o { color: #ce5c00; font-weight: bold } /* Operator */
48
+ .highlight .x { color: #000000 } /* Other */
49
+ .highlight .p { color: #000000; font-weight: bold } /* Punctuation */
50
+ .highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */
51
+ .highlight .cp { color: #8f5902; font-style: italic } /* Comment.Preproc */
52
+ .highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */
53
+ .highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */
54
+ .highlight .gd { color: #a40000 } /* Generic.Deleted */
55
+ .highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
56
+ .highlight .gr { color: #ef2929 } /* Generic.Error */
57
+ .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
58
+ .highlight .gi { color: #00A000 } /* Generic.Inserted */
59
+ .highlight .go { color: #000000; font-style: italic } /* Generic.Output */
60
+ .highlight .gp { color: #8f5902 } /* Generic.Prompt */
61
+ .highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */
62
+ .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
63
+ .highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */
64
+ .highlight .kc { color: #204a87; font-weight: bold } /* Keyword.Constant */
65
+ .highlight .kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */
66
+ .highlight .kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */
67
+ .highlight .kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */
68
+ .highlight .kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */
69
+ .highlight .kt { color: #204a87; font-weight: bold } /* Keyword.Type */
70
+ .highlight .ld { color: #000000 } /* Literal.Date */
71
+ .highlight .m { color: #0000cf; font-weight: bold } /* Literal.Number */
72
+ .highlight .s { color: #4e9a06 } /* Literal.String */
73
+ .highlight .na { color: #c4a000 } /* Name.Attribute */
74
+ .highlight .nb { color: #204a87 } /* Name.Builtin */
75
+ .highlight .nc { color: #000000 } /* Name.Class */
76
+ .highlight .no { color: #000000 } /* Name.Constant */
77
+ .highlight .nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */
78
+ .highlight .ni { color: #ce5c00 } /* Name.Entity */
79
+ .highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */
80
+ .highlight .nf { color: #000000 } /* Name.Function */
81
+ .highlight .nl { color: #f57900 } /* Name.Label */
82
+ .highlight .nn { color: #000000 } /* Name.Namespace */
83
+ .highlight .nx { color: #000000 } /* Name.Other */
84
+ .highlight .py { color: #000000 } /* Name.Property */
85
+ .highlight .nt { color: #204a87; font-weight: bold } /* Name.Tag */
86
+ .highlight .nv { color: #000000 } /* Name.Variable */
87
+ .highlight .ow { color: #204a87; font-weight: bold } /* Operator.Word */
88
+ .highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */
89
+ .highlight .mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */
90
+ .highlight .mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */
91
+ .highlight .mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */
92
+ .highlight .mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */
93
+ .highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */
94
+ .highlight .sc { color: #4e9a06 } /* Literal.String.Char */
95
+ .highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */
96
+ .highlight .s2 { color: #4e9a06 } /* Literal.String.Double */
97
+ .highlight .se { color: #4e9a06 } /* Literal.String.Escape */
98
+ .highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */
99
+ .highlight .si { color: #4e9a06 } /* Literal.String.Interpol */
100
+ .highlight .sx { color: #4e9a06 } /* Literal.String.Other */
101
+ .highlight .sr { color: #4e9a06 } /* Literal.String.Regex */
102
+ .highlight .s1 { color: #4e9a06 } /* Literal.String.Single */
103
+ .highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */
104
+ .highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */
105
+ .highlight .vc { color: #000000 } /* Name.Variable.Class */
106
+ .highlight .vg { color: #000000 } /* Name.Variable.Global */
107
+ .highlight .vi { color: #000000 } /* Name.Variable.Instance */
108
+ .highlight .il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */
109
+
@@ -0,0 +1,33 @@
1
+ require 'gimli/version'
2
+ require 'gimli/setup'
3
+ require 'gimli/file'
4
+ require 'gimli/converter'
5
+ require 'gimli/albino'
6
+
7
+ module Gimli
8
+
9
+ # Starts the processing of selected files
10
+ def self.process!
11
+ @files = []
12
+ if ARGV.flags.file?
13
+ Gimli.load_file(ARGV.flags.file)
14
+ else
15
+ Dir.glob("*").each do |file|
16
+ Gimli.load_file(file)
17
+ end
18
+ end
19
+
20
+ @files.each do |file|
21
+ converter = Converter.new file
22
+ converter.convert!
23
+ end
24
+ end
25
+
26
+ # Add file to the files to be converted if it's valid
27
+ # @param [String] file
28
+ def self.load_file(file)
29
+ file = File.new file
30
+ @files << file if file.valid?
31
+ end
32
+ end
33
+
@@ -0,0 +1,7 @@
1
+ require 'albino/multi'
2
+
3
+ # Use Albino Multi
4
+ class Gimli::Albino < Albino::Multi
5
+ self.bin = ::Albino::Multi.bin
6
+ end
7
+
@@ -0,0 +1,75 @@
1
+ require 'fileutils'
2
+
3
+ require 'pdfkit'
4
+
5
+ require 'gimli/markup'
6
+
7
+ module Gimli
8
+
9
+ # The class that communicates with PDFKit
10
+ class Converter
11
+
12
+ # Initialize the converter with a File
13
+ # @param [Gimli::File] file The file to convert
14
+ def initialize(file)
15
+ @file = file
16
+ end
17
+
18
+ # Convert the file and save it as a PDF file
19
+ def convert!
20
+ markup = Markup.new @file
21
+ html = markup.render
22
+
23
+ kit = pdf_kit(html)
24
+
25
+ kit.to_file(output_file)
26
+ end
27
+
28
+ # Load the pdfkit with html
29
+ # @param [String] html
30
+ # @return [PDFKit]
31
+ def pdf_kit(html)
32
+ kit = PDFKit.new(html)
33
+
34
+ load_stylesheets kit
35
+
36
+ kit
37
+ end
38
+
39
+ # Load the stylesheets to pdfkit loads the default and the user selected if any
40
+ # @param [PDFKit] kit
41
+ def load_stylesheets(kit)
42
+ # Load standard stylesheet
43
+ style = ::File.expand_path("../../../config/style.css", __FILE__)
44
+ kit.stylesheets << style
45
+
46
+ stylesheet
47
+
48
+ kit.stylesheets << stylesheet if ::File.exists?(stylesheet)
49
+ end
50
+
51
+ # Returns the selected stylesheet. Defaults to ./gimli.css
52
+ # @return [String]
53
+ def stylesheet
54
+ stylesheet = 'gimli.css'
55
+ stylesheet = ARGV.flags.stylesheet if ARGV.flags.stylesheet?
56
+ stylesheet
57
+ end
58
+
59
+ # Returns the directory where to save the output. Defaults to ./
60
+ # @return [String]
61
+ def output_dir
62
+ output_dir = Dir.getwd
63
+ output_dir = ARGV.flags.outputdir if ARGV.flags.outputdir?
64
+ FileUtils.mkdir_p(output_dir) unless ::File.directory?(output_dir)
65
+ output_dir
66
+ end
67
+
68
+ # Generate the name of the output file
69
+ # @return [String]
70
+ def output_file
71
+ ::File.join(output_dir, "#{@file.name}.pdf")
72
+ end
73
+ end
74
+ end
75
+
@@ -0,0 +1,65 @@
1
+ module Gimli
2
+
3
+ # Class used to load files and determine if they are valid
4
+ class File
5
+ attr_reader :filename, :name, :data, :format
6
+
7
+ # Accepted formats
8
+ FORMATS = [:markdown, :textile, :rdoc, :org, :creole, :rest, :asciidoc, :pod, :roff, :mediawiki]
9
+
10
+ # Initializes the file object. Only reads contents if it's a valid file
11
+ def initialize(filename)
12
+ @filename = filename
13
+ extension = ::File.extname(@filename)
14
+ @format = load_format(extension)
15
+ @name = ::File.basename(@filename, extension)
16
+ @data = ::File.open(@filename, 'rb') { |f| f.read } if valid? && ::File.exists?(@filename)
17
+ end
18
+
19
+ # Is the file valid
20
+ # @return [Boolean]
21
+ def valid?
22
+ valid_format? @format
23
+ end
24
+
25
+ # Converts the format to a symbol if it's a valid format nil otherwise
26
+ # @param [String] format
27
+ # @return [Symbol|nil]
28
+ def load_format(format)
29
+ case format
30
+ when /(md|mkdn?|mdown|markdown)$/i
31
+ :markdown
32
+ when /(textile)$/i
33
+ :textile
34
+ when /(rdoc)$/i
35
+ :rdoc
36
+ when /(org)$/i
37
+ :org
38
+ when /(creole)$/i
39
+ :creole
40
+ when /(re?st(\.txt)?)$/i
41
+ :rest
42
+ when /(asciidoc)$/i
43
+ :asciidoc
44
+ when /(pod)$/i
45
+ :pod
46
+ when /(\d)$/i
47
+ :roff
48
+ when /(media)?wiki$/i
49
+ :mediawiki
50
+ else
51
+ nil
52
+ end
53
+ end
54
+
55
+ # Checks if the format is a valid one
56
+ # @param [String] format
57
+ # @return [Boolean]
58
+ def valid_format?(format)
59
+ return false if format.nil?
60
+
61
+ FORMATS.include? format.to_sym
62
+ end
63
+ end
64
+ end
65
+
@@ -0,0 +1,268 @@
1
+ require 'digest/sha1'
2
+ require 'cgi'
3
+
4
+ require 'github/markup'
5
+ require 'nokogiri'
6
+
7
+ module Gimli
8
+
9
+ # Contains functionality to render html from a markup file
10
+ class Markup
11
+ # Initialize a new Markup object.
12
+ #
13
+ # @param [Gimli::File] file The Gimli::File to process
14
+ # @return [Gimli::Markup]
15
+ def initialize(file)
16
+ @filename = file.filename
17
+ @name = file.name
18
+ @data = file.data
19
+ @format = file.format
20
+ @tagmap = {}
21
+ @codemap = {}
22
+ @premap = {}
23
+ end
24
+
25
+ # Render the content with Gollum wiki syntax on top of the file's own
26
+ # markup language.
27
+ #
28
+ # @return [String] The formatted data
29
+ def render
30
+ data = extract_code(@data.dup)
31
+ data = extract_tags(data)
32
+ begin
33
+ data = GitHub::Markup.render(@filename, data)
34
+ if data.nil?
35
+ raise "There was an error converting #{@name} to HTML."
36
+ end
37
+ rescue Object => e
38
+ data = %{<p class="gimli-error">#{e.message}</p>}
39
+ end
40
+ data = process_tags(data)
41
+ data = process_code(data)
42
+
43
+ doc = Nokogiri::HTML::DocumentFragment.parse(data)
44
+ yield doc if block_given?
45
+ data = doc_to_html(doc)
46
+
47
+ data.gsub!(/<p><\/p>/, '')
48
+ data
49
+ end
50
+
51
+ def doc_to_html(doc)
52
+ doc.to_xhtml(:save_with => Nokogiri::XML::Node::SaveOptions::AS_XHTML)
53
+ end
54
+
55
+ # Extract all tags into the tagmap and replace with placeholders.
56
+ #
57
+ # @param [String] data - The raw string data.
58
+ # @return [String] Returns the placeholder's string data.
59
+ def extract_tags(data)
60
+ data.gsub!(/(.?)\[\[(.+?)\]\]([^\[]?)/m) do
61
+ if $1 == "'" && $3 != "'"
62
+ "[[#{$2}]]#{$3}"
63
+ elsif $2.include?('][')
64
+ if $2[0..4] == 'file:'
65
+ pre = $1
66
+ post = $3
67
+ parts = $2.split('][')
68
+ parts[0][0..4] = ""
69
+ link = "#{parts[1]}|#{parts[0].sub(/\.org/,'')}"
70
+ id = Digest::SHA1.hexdigest(link)
71
+ @tagmap[id] = link
72
+ "#{pre}#{id}#{post}"
73
+ else
74
+ $&
75
+ end
76
+ else
77
+ id = Digest::SHA1.hexdigest($2)
78
+ @tagmap[id] = $2
79
+ "#{$1}#{id}#{$3}"
80
+ end
81
+ end
82
+ data
83
+ end
84
+
85
+ # Process all tags from the tagmap and replace the placeholders with the
86
+ # final markup.
87
+ #
88
+ # @param [String] data - The data (with placeholders)
89
+ # @return [String] Returns the marked up String data.
90
+ def process_tags(data)
91
+ @tagmap.each do |id, tag|
92
+ data.gsub!(id, process_tag(tag))
93
+ end
94
+ data
95
+ end
96
+
97
+ # Process a single tag into its final HTML form.
98
+ #
99
+ # @param [String] tag The String tag contents (the stuff inside the double brackets).
100
+ # @return [String] Returns the String HTML version of the tag.
101
+ def process_tag(tag)
102
+ if html = process_image_tag(tag)
103
+ html
104
+ elsif html = process_file_link_tag(tag)
105
+ html
106
+ end
107
+ end
108
+
109
+ # Attempt to process the tag as an image tag.
110
+ #
111
+ # @param [String] tag The String tag contents (the stuff inside the double brackets).
112
+ # @return [String|nil] Returns the String HTML if the tag is a valid image tag or nil if it is not.
113
+ def process_image_tag(tag)
114
+ parts = tag.split('|')
115
+ return if parts.size.zero?
116
+
117
+ name = parts[0].strip
118
+ path = name
119
+
120
+ if path
121
+ opts = parse_image_tag_options(tag)
122
+
123
+ containered = false
124
+
125
+ classes = [] # applied to whatever the outermost container is
126
+ attrs = [] # applied to the image
127
+
128
+ align = opts['align']
129
+ if opts['float']
130
+ containered = true
131
+ align ||= 'left'
132
+ if %w{left right}.include?(align)
133
+ classes << "float-#{align}"
134
+ end
135
+ elsif %w{top texttop middle absmiddle bottom absbottom baseline}.include?(align)
136
+ attrs << %{align="#{align}"}
137
+ elsif align
138
+ if %w{left center right}.include?(align)
139
+ containered = true
140
+ classes << "align-#{align}"
141
+ end
142
+ end
143
+
144
+ if width = opts['width']
145
+ if width =~ /^\d+(\.\d+)?(em|px)$/
146
+ attrs << %{width="#{width}"}
147
+ end
148
+ end
149
+
150
+ if height = opts['height']
151
+ if height =~ /^\d+(\.\d+)?(em|px)$/
152
+ attrs << %{height="#{height}"}
153
+ end
154
+ end
155
+
156
+ if alt = opts['alt']
157
+ attrs << %{alt="#{alt}"}
158
+ end
159
+
160
+ attr_string = attrs.size > 0 ? attrs.join(' ') + ' ' : ''
161
+
162
+ if opts['frame'] || containered
163
+ classes << 'frame' if opts['frame']
164
+ %{<span class="#{classes.join(' ')}">} +
165
+ %{<span>} +
166
+ %{<img src="#{path}" #{attr_string}/>} +
167
+ (alt ? %{<span>#{alt}</span>} : '') +
168
+ %{</span>} +
169
+ %{</span>}
170
+ else
171
+ %{<img src="#{path}" #{attr_string}/>}
172
+ end
173
+ end
174
+ end
175
+
176
+ # Parse any options present on the image tag and extract them into a
177
+ # Hash of option names and values.
178
+ #
179
+ # @param [String] tag The String tag contents (the stuff inside the double brackets).
180
+ # @return [Hash]
181
+ # Returns the options Hash:
182
+ # key - The String option name.
183
+ # val - The String option value or true if it is a binary option.
184
+ def parse_image_tag_options(tag)
185
+ tag.split('|')[1..-1].inject({}) do |memo, attr|
186
+ parts = attr.split('=').map { |x| x.strip }
187
+ memo[parts[0]] = (parts.size == 1 ? true : parts[1])
188
+ memo
189
+ end
190
+ end
191
+
192
+ # Extract all code blocks into the codemap and replace with placeholders.
193
+ #
194
+ # @param [String] data The raw String data.
195
+ # @return [String] Returns the placeholder'd String data.
196
+ def extract_code(data)
197
+ data.gsub!(/^``` ?([^\r\n]+)?\r?\n(.+?)\r?\n```\r?$/m) do
198
+ id = Digest::SHA1.hexdigest($2)
199
+ cached = check_cache(:code, id)
200
+ @codemap[id] = cached ?
201
+ { :output => cached } :
202
+ { :lang => $1, :code => $2 }
203
+ id
204
+ end
205
+ data
206
+ end
207
+
208
+ # Process all code from the codemap and replace the placeholders with the
209
+ # final HTML.
210
+ #
211
+ # @param [String] data The String data (with placeholders).
212
+ # @return [String] Returns the marked up String data.
213
+ def process_code(data)
214
+ return data if data.nil? || data.size.zero? || @codemap.size.zero?
215
+
216
+ blocks = []
217
+ @codemap.each do |id, spec|
218
+ next if spec[:output] # cached
219
+
220
+ code = spec[:code]
221
+ if code.lines.all? { |line| line =~ /\A\r?\n\Z/ || line =~ /^( |\t)/ }
222
+ code.gsub!(/^( |\t)/m, '')
223
+ end
224
+
225
+ blocks << [spec[:lang], code]
226
+ end
227
+
228
+ highlighted = begin
229
+ blocks.size.zero? ? [] : Gimli::Albino.colorize(blocks)
230
+ rescue ::Albino::ShellArgumentError, ::Albino::TimeoutExceeded,
231
+ ::Albino::MaximumOutputExceeded
232
+ []
233
+ end
234
+
235
+ @codemap.each do |id, spec|
236
+ body = spec[:output] || begin
237
+ if (body = highlighted.shift.to_s).size > 0
238
+ update_cache(:code, id, body)
239
+ body
240
+ else
241
+ "<pre><code>#{CGI.escapeHTML(spec[:code])}</code></pre>"
242
+ end
243
+ end
244
+ data.gsub!(id, body)
245
+ end
246
+
247
+ data
248
+ end
249
+
250
+ # Hook for getting the formatted value of extracted tag data.
251
+ #
252
+ # @param [Symbol] type Symbol value identifying what type of data is being extracted.
253
+ # @param [String] id String SHA1 hash of original extracted tag data.
254
+ # @return [String] Returns the String cached formatted data, or nil.
255
+ def check_cache(type, id)
256
+ end
257
+
258
+ # Hook for caching the formatted value of extracted tag data.
259
+ #
260
+ # @param [Symbol] type Symbol value identifying what type of data is being extracted.
261
+ # @param [String] id String SHA1 hash of original extracted tag data.
262
+ # @param [String] data The String formatted value to be cached.
263
+ # @return [nil]
264
+ def update_cache(type, id, data)
265
+ end
266
+ end
267
+ end
268
+
@@ -0,0 +1,21 @@
1
+ require 'optiflag'
2
+
3
+ # Set up the flags available
4
+ module Gimli extend OptiFlagSet
5
+ optional_flag 'file' do
6
+ description 'The file to convert if you do not want to convert all in the current folder'
7
+ alternate_forms 'f'
8
+ end
9
+ optional_flag 'outputdir' do
10
+ description 'The directory to save parsed files if you do not want to use the current folder. The directory is created if it does not exist'
11
+ alternate_forms 'o'
12
+ end
13
+ optional_flag 'stylesheet' do
14
+ description 'The stylesheet to use to override the standard'
15
+ alternate_forms 's'
16
+ end
17
+ usage_flag 'h', 'help', '?'
18
+
19
+ and_process!
20
+ end
21
+
@@ -0,0 +1,6 @@
1
+ module Gimli
2
+
3
+ Version = "0.1.0"
4
+
5
+ end
6
+
@@ -0,0 +1,8 @@
1
+ a
2
+
3
+ ```ruby
4
+ x = 1
5
+ ```
6
+
7
+ b
8
+
@@ -0,0 +1,71 @@
1
+ require './spec/spec_helper'
2
+
3
+ require './lib/gimli'
4
+
5
+ describe Gimli::Converter do
6
+ it 'should give the correct output_file with none given' do
7
+ file = Gimli::File.new 'fake'
8
+ name = 'my_file'
9
+ mock(file).name { name }
10
+
11
+ converter = Gimli::Converter.new file
12
+ mock(converter).output_dir { Dir.getwd }
13
+
14
+ converter.output_file.should == File.join(Dir.getwd, "#{name}.pdf")
15
+ end
16
+
17
+ it 'should give the correct output_file with one given' do
18
+ file = Gimli::File.new 'fake'
19
+ name = 'my_file'
20
+ mock(file).name { name }
21
+
22
+ converter = Gimli::Converter.new file
23
+ mock(converter).output_dir { '/tmp/out' }
24
+
25
+ converter.output_file.should == "/tmp/out/#{name}.pdf"
26
+ end
27
+
28
+ it 'should give the correct output_dir when none given' do
29
+ dir = Dir.getwd
30
+
31
+ file = Gimli::File.new 'fake'
32
+ converter = Gimli::Converter.new file
33
+
34
+ converter.output_dir.should == dir
35
+ end
36
+
37
+ it 'should give the correct output_dir when given' do
38
+ dir = '/tmp/out'
39
+
40
+ file = Gimli::File.new 'fake'
41
+ converter = Gimli::Converter.new file
42
+
43
+ mock(ARGV).flags.mock!.outputdir? { true }
44
+ mock(ARGV).flags.mock!.outputdir { dir }
45
+ mock(File).directory?(dir) { true }
46
+
47
+ converter.output_dir.should == dir
48
+ end
49
+
50
+ it 'should use stylesheet if exists in folder' do
51
+ file = Gimli::File.new 'fake'
52
+ converter = Gimli::Converter.new file
53
+
54
+ mock(ARGV).flags.mock!.stylesheet? { false }
55
+
56
+ converter.stylesheet.should == 'gimli.css'
57
+ end
58
+
59
+ it 'should use stylesheet if given' do
60
+ file = Gimli::File.new 'fake'
61
+ converter = Gimli::Converter.new file
62
+
63
+ style = '/home/me/gimli/my-style.css'
64
+
65
+ mock(ARGV).flags.mock!.stylesheet? { true }
66
+ mock(ARGV).flags.mock!.stylesheet { style }
67
+
68
+ converter.stylesheet.should == style
69
+ end
70
+ end
71
+
@@ -0,0 +1,26 @@
1
+ require './spec/spec_helper'
2
+
3
+ require './lib/gimli'
4
+
5
+ describe Gimli::File do
6
+ it 'should recognize valid format' do
7
+ file = Gimli::File.new 'fake'
8
+ file.valid_format?('textile').should be_true
9
+ end
10
+
11
+ it 'should recognize invalid format' do
12
+ file = Gimli::File.new 'fake'
13
+ file.valid_format?('abc123').should be_false
14
+ end
15
+
16
+ it 'should recognize nil as invalid format' do
17
+ file = Gimli::File.new 'fake'
18
+ file.valid_format?(nil).should be_false
19
+ end
20
+
21
+ it 'should give the name as the filename without the extension' do
22
+ file = Gimli::File.new 'test.txt'
23
+ file.name.should == File.basename(file.filename, File.extname(file.filename))
24
+ end
25
+ end
26
+
@@ -0,0 +1,21 @@
1
+ require './spec/spec_helper'
2
+
3
+ require './lib/gimli'
4
+
5
+ describe Gimli::Markup do
6
+
7
+ it 'should give correct code block' do
8
+
9
+ output = "<p>a</p>\n<div class=\"highlight\"><pre>" +
10
+ "<span class=\"n\">x</span> <span class=\"o\">=</span> " +
11
+ "<span class=\"mi\">1</span>\n</pre>\n</div>\n\n<p>b</p>"
12
+
13
+ file = Gimli::File.new File.expand_path('../../fixtures/code_block.textile', __FILE__)
14
+ markup = Gimli::Markup.new file
15
+
16
+ markup.render.should == output
17
+ end
18
+
19
+
20
+ end
21
+
@@ -0,0 +1,4 @@
1
+ RSpec.configure do |config|
2
+ config.mock_with :rr
3
+ end
4
+
metadata ADDED
@@ -0,0 +1,221 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gimli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Fredrik Wallgren
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-04-29 00:00:00.000000000 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: github-markup
17
+ requirement: &16957440 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *16957440
26
+ - !ruby/object:Gem::Dependency
27
+ name: redcarpet
28
+ requirement: &16957020 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *16957020
37
+ - !ruby/object:Gem::Dependency
38
+ name: RedCloth
39
+ requirement: &16956600 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *16956600
48
+ - !ruby/object:Gem::Dependency
49
+ name: org-ruby
50
+ requirement: &16956180 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: *16956180
59
+ - !ruby/object:Gem::Dependency
60
+ name: creole
61
+ requirement: &16955760 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :runtime
68
+ prerelease: false
69
+ version_requirements: *16955760
70
+ - !ruby/object:Gem::Dependency
71
+ name: wikicloth
72
+ requirement: &16955340 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: *16955340
81
+ - !ruby/object:Gem::Dependency
82
+ name: albino
83
+ requirement: &16954920 !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ! '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: *16954920
92
+ - !ruby/object:Gem::Dependency
93
+ name: nokogiri
94
+ requirement: &16954500 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ type: :runtime
101
+ prerelease: false
102
+ version_requirements: *16954500
103
+ - !ruby/object:Gem::Dependency
104
+ name: wkhtmltopdf-binary
105
+ requirement: &16985560 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ type: :runtime
112
+ prerelease: false
113
+ version_requirements: *16985560
114
+ - !ruby/object:Gem::Dependency
115
+ name: pdfkit
116
+ requirement: &16985140 !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ type: :runtime
123
+ prerelease: false
124
+ version_requirements: *16985140
125
+ - !ruby/object:Gem::Dependency
126
+ name: optiflag
127
+ requirement: &16984720 !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ type: :runtime
134
+ prerelease: false
135
+ version_requirements: *16984720
136
+ - !ruby/object:Gem::Dependency
137
+ name: rspec
138
+ requirement: &16984300 !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: *16984300
147
+ - !ruby/object:Gem::Dependency
148
+ name: rr
149
+ requirement: &16983880 !ruby/object:Gem::Requirement
150
+ none: false
151
+ requirements:
152
+ - - ! '>='
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ type: :development
156
+ prerelease: false
157
+ version_requirements: *16983880
158
+ - !ruby/object:Gem::Dependency
159
+ name: yard
160
+ requirement: &16983460 !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: *16983460
169
+ description: Utility for converting markup files to pdf files. Useful for reports
170
+ etc.
171
+ email: fredrik.wallgren@gmail.com
172
+ executables:
173
+ - gimli
174
+ extensions: []
175
+ extra_rdoc_files:
176
+ - README.textile
177
+ - LICENSE
178
+ files:
179
+ - bin/gimli
180
+ - lib/gimli/version.rb
181
+ - lib/gimli/albino.rb
182
+ - lib/gimli/file.rb
183
+ - lib/gimli/markup.rb
184
+ - lib/gimli/setup.rb
185
+ - lib/gimli/converter.rb
186
+ - lib/gimli.rb
187
+ - spec/spec_helper.rb
188
+ - spec/fixtures/code_block.textile
189
+ - spec/gimli/converter_spec.rb
190
+ - spec/gimli/markup_spec.rb
191
+ - spec/gimli/file_spec.rb
192
+ - config/style.css
193
+ - LICENSE
194
+ - README.textile
195
+ has_rdoc: true
196
+ homepage: https://github.com/walle/gimli
197
+ licenses: []
198
+ post_install_message:
199
+ rdoc_options:
200
+ - --charset=UTF-8
201
+ require_paths:
202
+ - - lib
203
+ required_ruby_version: !ruby/object:Gem::Requirement
204
+ none: false
205
+ requirements:
206
+ - - ! '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ required_rubygems_version: !ruby/object:Gem::Requirement
210
+ none: false
211
+ requirements:
212
+ - - ! '>='
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ requirements: []
216
+ rubyforge_project: gimli
217
+ rubygems_version: 1.6.2
218
+ signing_key:
219
+ specification_version: 3
220
+ summary: Utility for converting markup files to pdf files.
221
+ test_files: []