code2pdf_rdeterre 0.4.2

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.
Files changed (36) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +61 -0
  6. data/LICENSE +24 -0
  7. data/README.md +52 -0
  8. data/Rakefile +7 -0
  9. data/bin/code2pdf +39 -0
  10. data/code2pdf.gemspec +24 -0
  11. data/examples/example.pdf +24488 -0
  12. data/lib/code2pdf.rb +4 -0
  13. data/lib/code2pdf/convert_to_pdf.rb +120 -0
  14. data/lib/code2pdf/version.rb +3 -0
  15. data/spec/code2pdf/convert_to_pdf_spec.rb +73 -0
  16. data/spec/fixtures/hello_world/.code2pdf +7 -0
  17. data/spec/fixtures/hello_world/doc/HelloWorld.html +162 -0
  18. data/spec/fixtures/hello_world/doc/HelloWorld/Gambi.html +150 -0
  19. data/spec/fixtures/hello_world/doc/HelloWorld/Goodbye.html +199 -0
  20. data/spec/fixtures/hello_world/doc/HelloWorld/Helo.html +199 -0
  21. data/spec/fixtures/hello_world/doc/created.rid +5 -0
  22. data/spec/fixtures/hello_world/doc/index.html +66 -0
  23. data/spec/fixtures/hello_world/doc/lib/gambi_rb.html +52 -0
  24. data/spec/fixtures/hello_world/doc/lib/goodbye_rb.html +52 -0
  25. data/spec/fixtures/hello_world/doc/lib/hello_rb.html +52 -0
  26. data/spec/fixtures/hello_world/doc/rdoc.css +706 -0
  27. data/spec/fixtures/hello_world/doc/tmp_txt.html +90 -0
  28. data/spec/fixtures/hello_world/lib/gambi.rb +5 -0
  29. data/spec/fixtures/hello_world/lib/goodbye.rb +7 -0
  30. data/spec/fixtures/hello_world/lib/hello.rb +7 -0
  31. data/spec/fixtures/hello_world/tmp.txt +1 -0
  32. data/spec/fixtures/hello_world_original.pdf +0 -0
  33. data/spec/fixtures/purplelist.yml +3 -0
  34. data/spec/fixtures/syntax_highlight.html +15 -0
  35. data/spec/spec_helper.rb +10 -0
  36. metadata +189 -0
@@ -0,0 +1,4 @@
1
+ require 'yaml'
2
+ require 'pdfkit'
3
+ require 'code2pdf/convert_to_pdf'
4
+ require 'rouge'
@@ -0,0 +1,120 @@
1
+ class ConvertToPDF
2
+ PDF_OPTIONS = {
3
+ page_size: 'A4'
4
+ }.freeze
5
+
6
+ def initialize(params = {})
7
+ if !params.key?(:from) || params[:from].nil?
8
+ raise ArgumentError.new 'where is the codebase you want to convert to PDF?'
9
+ elsif !valid_directory?(params[:from])
10
+ raise LoadError.new "#{params[:from]} not found"
11
+ elsif !params.key?(:to) || params[:to].nil?
12
+ raise ArgumentError.new 'where should I save the generated pdf file?'
13
+ else
14
+ @from, @to, @except = params[:from], params[:to], params[:except].to_s
15
+
16
+ if File.exist?(@except) && invalid_blacklist?
17
+ raise LoadError.new "#{@except} is not a valid blacklist YAML file"
18
+ end
19
+
20
+ save
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def save
27
+ pdf.to_file(@to)
28
+ end
29
+
30
+ def pdf
31
+ html ||= ''
32
+
33
+ style = 'size: 12px; font-family: Helvetica, sans-serif;'
34
+
35
+ read_files.each do |file|
36
+ html += "<strong style='#{style}'>File: #{file.first}</strong></br></br>"
37
+ html += prepare_line_breaks(syntax_highlight(file)).to_s
38
+ html += add_space(30)
39
+ end
40
+
41
+ @kit = PDFKit.new(html, page_size: 'A4')
42
+ @kit
43
+ end
44
+
45
+ def syntax_highlight(file)
46
+ file_type = File.extname(file.first)[1..-1]
47
+ file_lexer = Rouge::Lexer.find(file_type)
48
+ return file.last unless file_lexer
49
+
50
+ theme = Rouge::Themes::Base16.mode(:light)
51
+ formatter = Rouge::Formatters::HTMLInline.new(theme)
52
+ formatter = Rouge::Formatters::HTMLTable.new(formatter, start_line: 1)
53
+ formatter.format(file_lexer.lex(file.last))
54
+ end
55
+
56
+ def invalid_blacklist?
57
+ return true if FileTest.directory?(@except)
58
+
59
+ @blacklist = YAML.load_file(@except)
60
+
61
+ !@blacklist.key?(:directories) || !@blacklist.key?(:files)
62
+ end
63
+
64
+ def in_directory_blacklist?(item_path)
65
+ @blacklist[:directories].include?(item_path.gsub("#{@from}/", '')) if @blacklist
66
+ end
67
+
68
+ def in_file_blacklist?(item_path)
69
+ if @blacklist
70
+ @blacklist[:files].include?(item_path.split('/').last) || @blacklist[:files].include?(item_path.gsub("#{@from}/", ''))
71
+ end
72
+ end
73
+
74
+ def valid_directory?(dir)
75
+ File.exist?(dir) && FileTest.directory?(dir)
76
+ end
77
+
78
+ def valid_file?(file)
79
+ File.exist?(file) && FileTest.file?(file)
80
+ end
81
+
82
+ def read_files(path = nil)
83
+ @files ||= []
84
+ path ||= @from
85
+
86
+ Dir.foreach(path) do |item|
87
+ item_path = "#{path}/#{item}"
88
+
89
+ if valid_directory?(item_path) && !%w[. ..].include?(item) && !in_directory_blacklist?(item_path)
90
+ read_files(item_path)
91
+ elsif valid_file?(item_path) && !in_file_blacklist?(item_path)
92
+ @files << [item_path, process_file(item_path)]
93
+ end
94
+ end
95
+
96
+ @files
97
+ end
98
+
99
+ def process_file(file)
100
+ puts "Reading file #{file}"
101
+
102
+ content = ''
103
+ File.open(file, 'r') do |f|
104
+ if `file #{file}` !~ /text/
105
+ content << "<color rgb='777777'>[binary]</color>"
106
+ else
107
+ f.each_line { |line_content| content << line_content }
108
+ end
109
+ end
110
+ content.encode("utf-8", invalid: :replace, undef: :replace)
111
+ end
112
+
113
+ def prepare_line_breaks(content)
114
+ content.gsub(/\n/, '<br>')
115
+ end
116
+
117
+ def add_space(height)
118
+ "<div style='margin-bottom: #{height}px'>&nbsp;</div>"
119
+ end
120
+ end
@@ -0,0 +1,3 @@
1
+ module Code2pdf
2
+ VERSION = '0.4.2'.freeze
3
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ require 'digest/md5'
3
+ require 'pdf/inspector'
4
+
5
+ describe ConvertToPDF do
6
+ after do
7
+ pdf = 'spec/fixtures/hello_world.pdf'
8
+ File.delete(pdf) if File.exist?(pdf)
9
+ end
10
+
11
+ describe '#pdf' do
12
+ it 'creates a PDF file containing all desired source code' do
13
+ path = 'spec/fixtures/hello_world'
14
+ pdf = 'spec/fixtures/hello_world_output.pdf'
15
+ original = 'spec/fixtures/hello_world_original.pdf'
16
+ blacklist = 'spec/fixtures/hello_world/.code2pdf'
17
+
18
+ ConvertToPDF.new from: path, to: pdf, except: blacklist
19
+ text_analysis = read_strings("#{Dir.pwd}/#{pdf}")
20
+ text_analysis_original = read_strings("#{Dir.pwd}/#{original}")
21
+ expect(text_analysis).to eq(text_analysis_original)
22
+ File.delete(pdf)
23
+ end
24
+
25
+ it 'raises an error if required params are not present' do
26
+ expect { ConvertToPDF.new(foo: 'bar') }.to raise_error(ArgumentError)
27
+ end
28
+
29
+ it 'raises an error if path does not exist' do
30
+ path = 'spec/fixtures/isto_non_existe_quevedo'
31
+ pdf = 'spec/fixtures/isto_non_existe_quevedo.pdf'
32
+
33
+ expect { ConvertToPDF.new(from: path, to: pdf) }.to raise_error(LoadError)
34
+ end
35
+
36
+ it 'raises an error if blacklist file is not valid' do
37
+ path = 'spec/fixtures/hello_world'
38
+ pdf = 'spec/fixtures/hello_world.pdf'
39
+ blacklist = 'spec/fixtures/purplelist.yml'
40
+
41
+ expect { ConvertToPDF.new from: path, to: pdf, except: blacklist }.to raise_error(LoadError)
42
+ end
43
+ end
44
+
45
+ describe '#prepare_line_breaks' do
46
+ let :pdf do
47
+ ConvertToPDF.new from: 'spec/fixtures/hello_world', to: 'spec/fixtures/hello_world.pdf'
48
+ end
49
+
50
+ it 'converts strings with \n to <br> for PDF generation' do
51
+ test_text = "test\ntest"
52
+ expect(pdf.send(:prepare_line_breaks, test_text)).to eq('test<br>test')
53
+ end
54
+ end
55
+
56
+ describe '#syntax_highlight' do
57
+ let :pdf do
58
+ ConvertToPDF.new from: 'spec/fixtures/hello_world', to: 'spec/fixtures/hello_world.pdf'
59
+ end
60
+
61
+ it 'returns file with syntax_highlight html clases' do
62
+ path = 'spec/fixtures/hello_world/lib/hello.rb'
63
+ output = File.read('spec/fixtures/syntax_highlight.html')
64
+ content = pdf.send(:process_file, path)
65
+ file = [path, content]
66
+ expect(pdf.send(:syntax_highlight, file)).to eq(output)
67
+ end
68
+ end
69
+ end
70
+
71
+ def read_strings(file)
72
+ PDF::Inspector::Text.analyze(File.read(file)).strings
73
+ end
@@ -0,0 +1,7 @@
1
+ :directories:
2
+ - doc
3
+ :files:
4
+ - .DS_Store
5
+ - .code2pdf
6
+ - tmp.txt
7
+ - gambi.rb
@@ -0,0 +1,162 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
7
+
8
+ <title>Module: HelloWorld</title>
9
+
10
+ <link rel="stylesheet" href="./rdoc.css" type="text/css" media="screen" />
11
+
12
+ <script src="./js/jquery.js" type="text/javascript"
13
+ charset="utf-8"></script>
14
+ <script src="./js/thickbox-compressed.js" type="text/javascript"
15
+ charset="utf-8"></script>
16
+ <script src="./js/quicksearch.js" type="text/javascript"
17
+ charset="utf-8"></script>
18
+ <script src="./js/darkfish.js" type="text/javascript"
19
+ charset="utf-8"></script>
20
+
21
+ </head>
22
+ <body class="module">
23
+
24
+ <div id="metadata">
25
+ <div id="home-metadata">
26
+ <div id="home-section" class="section">
27
+ <h3 class="section-header">
28
+ <a href="./index.html">Home</a>
29
+ <a href="./index.html#classes">Classes</a>
30
+ <a href="./index.html#methods">Methods</a>
31
+ </h3>
32
+ </div>
33
+ </div>
34
+
35
+ <div id="file-metadata">
36
+ <div id="file-list-section" class="section">
37
+ <h3 class="section-header">In Files</h3>
38
+ <div class="section-body">
39
+ <ul>
40
+
41
+ <li><a href="./lib/gambi_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
42
+ class="thickbox" title="lib/gambi.rb">lib/gambi.rb</a></li>
43
+
44
+ <li><a href="./lib/goodbye_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
45
+ class="thickbox" title="lib/goodbye.rb">lib/goodbye.rb</a></li>
46
+
47
+ <li><a href="./lib/hello_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
48
+ class="thickbox" title="lib/hello.rb">lib/hello.rb</a></li>
49
+
50
+ </ul>
51
+ </div>
52
+ </div>
53
+
54
+
55
+ </div>
56
+
57
+ <div id="class-metadata">
58
+
59
+ <!-- Parent Class -->
60
+
61
+
62
+ <!-- Namespace Contents -->
63
+
64
+ <div id="namespace-list-section" class="section">
65
+ <h3 class="section-header">Namespace</h3>
66
+ <ul class="link-list">
67
+
68
+ <li><span class="type">CLASS</span> <a href="HelloWorld/Gambi.html">HelloWorld::Gambi</a></li>
69
+
70
+ <li><span class="type">CLASS</span> <a href="HelloWorld/Goodbye.html">HelloWorld::Goodbye</a></li>
71
+
72
+ <li><span class="type">CLASS</span> <a href="HelloWorld/Helo.html">HelloWorld::Helo</a></li>
73
+
74
+ </ul>
75
+ </div>
76
+
77
+
78
+ <!-- Method Quickref -->
79
+
80
+
81
+ <!-- Included Modules -->
82
+
83
+ </div>
84
+
85
+ <div id="project-metadata">
86
+
87
+
88
+ <div id="fileindex-section" class="section project-section">
89
+ <h3 class="section-header">Files</h3>
90
+ <ul>
91
+
92
+ <li class="file"><a href="./tmp_txt.html">tmp.txt</a></li>
93
+
94
+ </ul>
95
+ </div>
96
+
97
+
98
+ <div id="classindex-section" class="section project-section">
99
+ <h3 class="section-header">Class Index
100
+ <span class="search-toggle"><img src="./images/find.png"
101
+ height="16" width="16" alt="[+]"
102
+ title="show/hide quicksearch" /></span></h3>
103
+ <form action="#" method="get" accept-charset="utf-8" class="initially-hidden">
104
+ <fieldset>
105
+ <legend>Quicksearch</legend>
106
+ <input type="text" name="quicksearch" value=""
107
+ class="quicksearch-field" />
108
+ </fieldset>
109
+ </form>
110
+
111
+ <ul class="link-list">
112
+
113
+ <li><a href="./HelloWorld.html">HelloWorld</a></li>
114
+
115
+ <li><a href="./HelloWorld/Gambi.html">HelloWorld::Gambi</a></li>
116
+
117
+ <li><a href="./HelloWorld/Goodbye.html">HelloWorld::Goodbye</a></li>
118
+
119
+ <li><a href="./HelloWorld/Helo.html">HelloWorld::Helo</a></li>
120
+
121
+ </ul>
122
+ <div id="no-class-search-results" style="display: none;">No matching classes.</div>
123
+ </div>
124
+
125
+
126
+ </div>
127
+ </div>
128
+
129
+ <div id="documentation">
130
+ <h1 class="module">HelloWorld</h1>
131
+
132
+ <div id="description">
133
+
134
+ </div>
135
+
136
+ <!-- Constants -->
137
+
138
+
139
+ <!-- Attributes -->
140
+
141
+
142
+ <!-- Methods -->
143
+
144
+
145
+ </div>
146
+
147
+
148
+ <div id="rdoc-debugging-section-dump" class="debugging-section">
149
+
150
+ <p>Disabled; run with --debug to generate this.</p>
151
+
152
+ </div>
153
+
154
+ <div id="validator-badges">
155
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
156
+ <p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
157
+ Rdoc Generator</a> 1.1.6</small>.</p>
158
+ </div>
159
+
160
+ </body>
161
+ </html>
162
+
@@ -0,0 +1,150 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
7
+
8
+ <title>Class: HelloWorld::Gambi</title>
9
+
10
+ <link rel="stylesheet" href="../rdoc.css" type="text/css" media="screen" />
11
+
12
+ <script src="../js/jquery.js" type="text/javascript"
13
+ charset="utf-8"></script>
14
+ <script src="../js/thickbox-compressed.js" type="text/javascript"
15
+ charset="utf-8"></script>
16
+ <script src="../js/quicksearch.js" type="text/javascript"
17
+ charset="utf-8"></script>
18
+ <script src="../js/darkfish.js" type="text/javascript"
19
+ charset="utf-8"></script>
20
+
21
+ </head>
22
+ <body class="class">
23
+
24
+ <div id="metadata">
25
+ <div id="home-metadata">
26
+ <div id="home-section" class="section">
27
+ <h3 class="section-header">
28
+ <a href="../index.html">Home</a>
29
+ <a href="../index.html#classes">Classes</a>
30
+ <a href="../index.html#methods">Methods</a>
31
+ </h3>
32
+ </div>
33
+ </div>
34
+
35
+ <div id="file-metadata">
36
+ <div id="file-list-section" class="section">
37
+ <h3 class="section-header">In Files</h3>
38
+ <div class="section-body">
39
+ <ul>
40
+
41
+ <li><a href="../lib/gambi_rb.html?TB_iframe=true&amp;height=550&amp;width=785"
42
+ class="thickbox" title="lib/gambi.rb">lib/gambi.rb</a></li>
43
+
44
+ </ul>
45
+ </div>
46
+ </div>
47
+
48
+
49
+ </div>
50
+
51
+ <div id="class-metadata">
52
+
53
+ <!-- Parent Class -->
54
+
55
+ <div id="parent-class-section" class="section">
56
+ <h3 class="section-header">Parent</h3>
57
+
58
+ <p class="link">Object</p>
59
+
60
+ </div>
61
+
62
+
63
+ <!-- Namespace Contents -->
64
+
65
+
66
+ <!-- Method Quickref -->
67
+
68
+
69
+ <!-- Included Modules -->
70
+
71
+ </div>
72
+
73
+ <div id="project-metadata">
74
+
75
+
76
+ <div id="fileindex-section" class="section project-section">
77
+ <h3 class="section-header">Files</h3>
78
+ <ul>
79
+
80
+ <li class="file"><a href="../tmp_txt.html">tmp.txt</a></li>
81
+
82
+ </ul>
83
+ </div>
84
+
85
+
86
+ <div id="classindex-section" class="section project-section">
87
+ <h3 class="section-header">Class Index
88
+ <span class="search-toggle"><img src="../images/find.png"
89
+ height="16" width="16" alt="[+]"
90
+ title="show/hide quicksearch" /></span></h3>
91
+ <form action="#" method="get" accept-charset="utf-8" class="initially-hidden">
92
+ <fieldset>
93
+ <legend>Quicksearch</legend>
94
+ <input type="text" name="quicksearch" value=""
95
+ class="quicksearch-field" />
96
+ </fieldset>
97
+ </form>
98
+
99
+ <ul class="link-list">
100
+
101
+ <li><a href="../HelloWorld.html">HelloWorld</a></li>
102
+
103
+ <li><a href="../HelloWorld/Gambi.html">HelloWorld::Gambi</a></li>
104
+
105
+ <li><a href="../HelloWorld/Goodbye.html">HelloWorld::Goodbye</a></li>
106
+
107
+ <li><a href="../HelloWorld/Helo.html">HelloWorld::Helo</a></li>
108
+
109
+ </ul>
110
+ <div id="no-class-search-results" style="display: none;">No matching classes.</div>
111
+ </div>
112
+
113
+
114
+ </div>
115
+ </div>
116
+
117
+ <div id="documentation">
118
+ <h1 class="class">HelloWorld::Gambi</h1>
119
+
120
+ <div id="description">
121
+
122
+ </div>
123
+
124
+ <!-- Constants -->
125
+
126
+
127
+ <!-- Attributes -->
128
+
129
+
130
+ <!-- Methods -->
131
+
132
+
133
+ </div>
134
+
135
+
136
+ <div id="rdoc-debugging-section-dump" class="debugging-section">
137
+
138
+ <p>Disabled; run with --debug to generate this.</p>
139
+
140
+ </div>
141
+
142
+ <div id="validator-badges">
143
+ <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
144
+ <p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
145
+ Rdoc Generator</a> 1.1.6</small>.</p>
146
+ </div>
147
+
148
+ </body>
149
+ </html>
150
+