pdfkit 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of pdfkit might be problematic. Click here for more details.

@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 jdpace
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pdfkit}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["jdpace"]
12
+ s.date = %q{2010-05-21}
13
+ s.description = %q{Uses wkhtmltopdf to create PDFs using HTML}
14
+ s.email = %q{jared@codewordstudios.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "PDFKit.gemspec",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "lib/PDFKit.rb",
28
+ "lib/pdfkit/middleware.rb",
29
+ "lib/pdfkit/pdfkit.rb",
30
+ "spec/PDFKit_spec.rb",
31
+ "spec/fixtures/example.css",
32
+ "spec/spec.opts",
33
+ "spec/spec_helper.rb"
34
+ ]
35
+ s.homepage = %q{http://github.com/jdpace/PDFKit}
36
+ s.rdoc_options = ["--charset=UTF-8"]
37
+ s.require_paths = ["lib"]
38
+ s.rubygems_version = %q{1.3.6}
39
+ s.summary = %q{HTML+CSS -> PDF}
40
+ s.test_files = [
41
+ "spec/pdfkit_spec.rb",
42
+ "spec/spec_helper.rb"
43
+ ]
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
51
+ s.add_development_dependency(%q<rspec>, ["~> 2.0.0.beta.8"])
52
+ else
53
+ s.add_dependency(%q<activesupport>, [">= 0"])
54
+ s.add_dependency(%q<rspec>, ["~> 2.0.0.beta.8"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<activesupport>, [">= 0"])
58
+ s.add_dependency(%q<rspec>, ["~> 2.0.0.beta.8"])
59
+ end
60
+ end
61
+
@@ -0,0 +1,56 @@
1
+ # PDFKit
2
+
3
+ Create PDFs using plain old HTML+CSS. Uses [wkhtmltopdf](http://github.com/antialize/wkhtmltopdf) on the backend which renders HTML using Webkit.
4
+
5
+ ## Installation
6
+
7
+ 1. Install wkhtmltopdf
8
+ # Download the latest binary from http://code.google.com/p/wkhtmltopdf/downloads/list
9
+ # Place the binary somewhere on your path (e.g /usr/local/bin)
10
+ 2. Install PDFKit
11
+ # $ gem install pdfkit
12
+
13
+ ## Usage
14
+
15
+ # PDFKit.new takes the HTML and any options for wkhtmltopdf
16
+ # run `wkhtmltopdf --extended-help` for a full list of options
17
+ kit = PDFKit.new(html, :page_size => 'Letter')
18
+ kit.stylesheets << '/path/to/css/file'
19
+
20
+ # Git an inline PDF
21
+ pdf = kit.to_pdf
22
+
23
+ # Save the PDF to a file
24
+ File.open('/path/to/save/pdf','w') {|file| file << pdf}
25
+
26
+ ## Middleware
27
+
28
+ PDFKit comes with a middleware that allows users to visit any to get a PDF view of any page on your site by appending ?pdf=true to the URL.
29
+
30
+ ### Middleware Setup
31
+
32
+ **Non-Rails Rack apps**
33
+
34
+ # in config.ru
35
+ require 'pdfkit'
36
+ use PDFKit::Middleware
37
+
38
+ **Rails apps**
39
+
40
+ # in application.rb(Rails3) or environment.rb(Rails2)
41
+ require 'pdfkit'
42
+ config.middleware.use PDFKit::Middleware
43
+
44
+ ## Note on Patches/Pull Requests
45
+
46
+ * Fork the project.
47
+ * Make your feature addition or bug fix.
48
+ * Add tests for it. This is important so I don't break it in a
49
+ future version unintentionally.
50
+ * Commit, do not mess with rakefile, version, or history.
51
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
52
+ * Send me a pull request. Bonus points for topic branches.
53
+
54
+ ## Copyright
55
+
56
+ Copyright (c) 2010 Jared Pace. See LICENSE for details.
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "pdfkit"
8
+ gem.summary = %Q{HTML+CSS -> PDF}
9
+ gem.description = %Q{Uses wkhtmltopdf to create PDFs using HTML}
10
+ gem.email = "jared@codewordstudios.com"
11
+ gem.homepage = "http://github.com/jdpace/PDFKit"
12
+ gem.authors = ["jdpace"]
13
+ gem.add_dependency "activesupport"
14
+ gem.add_development_dependency "rspec", "~> 2.0.0.beta.8"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rspec/core/rake_task'
23
+ Rspec::Core::RakeTask.new(:spec) do |spec|
24
+ end
25
+
26
+ Rspec::Core::RakeTask.new(:rcov) do |spec|
27
+ spec.rcov = true
28
+ end
29
+
30
+ task :spec => :check_dependencies
31
+
32
+ task :default => :spec
33
+
34
+ require 'rake/rdoctask'
35
+ Rake::RDocTask.new do |rdoc|
36
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
37
+
38
+ rdoc.rdoc_dir = 'rdoc'
39
+ rdoc.title = "PDFKit #{version}"
40
+ rdoc.rdoc_files.include('README*')
41
+ rdoc.rdoc_files.include('lib/**/*.rb')
42
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,5 @@
1
+ require 'rubygems'
2
+ require 'active_support/core_ext'
3
+ require 'active_support/inflector'
4
+ require 'pdfkit/pdfkit'
5
+ require 'pdfkit/middleware'
@@ -0,0 +1,41 @@
1
+ class PDFKit
2
+
3
+ # A rack middleware for validating HTML via w3c validator
4
+ class Middleware
5
+
6
+ def initialize( app )
7
+ @app = app
8
+ end
9
+
10
+ def call( env )
11
+ status, headers, response = @app.call( env )
12
+
13
+ request = Rack::Request.new( env )
14
+ if !request.params['pdf'].blank?
15
+ if headers['Content-Type'] =~ /text\/html|application\/xhtml\+xml/
16
+ body = response.body
17
+
18
+ # Make absolute urls
19
+ uri = env['REQUEST_URI'].split('?').first
20
+ uri += '/' unless uri.match(/\/$/)
21
+ root = env['rack.url_scheme'] + "://" + env['HTTP_HOST']
22
+ # translate relative urls
23
+ body.gsub!(/(href|src)=['"]([^\/][^\"']*)['"]/,'\1="'+root+'/\2"')
24
+
25
+ # translate absolute urls
26
+ body.gsub!(/(href|src)=['"]\/([^\"]*|[^']*)['"]/,'\1="'+uri+'\2"')
27
+
28
+ pdf = PDFKit.new(body)
29
+ body = pdf.to_pdf
30
+
31
+ headers["Content-Length"] = body.length.to_s
32
+ headers["Content-Type"] = "application/pdf"
33
+ response = [body]
34
+ end
35
+ end
36
+
37
+ [status, headers, response]
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,76 @@
1
+ class PDFKit
2
+
3
+ class NoExecutableError < StandardError
4
+ def initialize
5
+ super('Could not locate wkhtmltopdf executable')
6
+ end
7
+ end
8
+
9
+ attr_accessor :html, :stylesheets
10
+ attr_reader :options
11
+
12
+ def initialize(html, options = {})
13
+ @html = html
14
+ @stylesheets = []
15
+
16
+ default_options = {
17
+ :disable_smart_shrinking => true,
18
+ :page_size => 'Letter',
19
+ :margin_top => '0.75in',
20
+ :margin_right => '0.75in',
21
+ :margin_bottom => '0.75in',
22
+ :margin_left => '0.75in'
23
+ }
24
+ @options = normalize_options(options.reverse_merge(default_options))
25
+
26
+ @cmd = `which wkhtmltopdf`.chomp
27
+ raise NoExecutableError.new if @cmd.blank?
28
+ end
29
+
30
+ def command
31
+ args = [@cmd]
32
+ args += @options.to_a.flatten.compact
33
+ args << '--quiet'
34
+ args << '-' # Get HTML from stdin
35
+ args << '-' # Read PDF from stdout
36
+ args.join(' ')
37
+ end
38
+
39
+ def to_pdf
40
+ append_stylesheets
41
+
42
+ pdf = IO.popen(command, "w+")
43
+ pdf.puts(@html)
44
+ pdf.close_write
45
+ result = pdf.gets(nil)
46
+ pdf.close_read
47
+ return result
48
+ end
49
+
50
+ protected
51
+
52
+ def style_tag_for(stylesheet)
53
+ "<style>#{File.read(stylesheet)}</style>"
54
+ end
55
+
56
+ def append_stylesheets
57
+ stylesheets.each do |stylesheet|
58
+ if @html.match(/<\/head>/)
59
+ @html.gsub!(/(<\/head>)/, "#{style_tag_for(stylesheet)}$1")
60
+ else
61
+ @html.insert(0, style_tag_for(stylesheet))
62
+ end
63
+ end
64
+ end
65
+
66
+ def normalize_options(options)
67
+ normalized_options = {}
68
+ options.each do |key, value|
69
+ normalized_key = "--#{key.to_s.downcase.dasherize}"
70
+ normalized_value = value.is_a?(TrueClass) ? nil : value
71
+ normalized_options[normalized_key] = normalized_value
72
+ end
73
+ normalized_options
74
+ end
75
+
76
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe PDFKit do
4
+
5
+ context "initialization" do
6
+ it "should take HTML for the renderer" do
7
+ pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
8
+ pdfkit.html.should == '<h1>Oh Hai</h1>'
9
+ end
10
+
11
+ it "should parse the options into a cmd line friedly format" do
12
+ pdfkit = PDFKit.new('html', :page_size => 'Letter')
13
+ pdfkit.options.should have_key('--page-size')
14
+ end
15
+
16
+ it "should provide default options" do
17
+ pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
18
+ ['--disable-smart-shrinking', '--margin-top', '--margin-right', '--margin-bottom', '--margin-left'].each do |option|
19
+ pdfkit.options.should have_key(option)
20
+ end
21
+ end
22
+
23
+ it "should not have any stylesheedt by default" do
24
+ pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
25
+ pdfkit.stylesheets.should be_empty
26
+ end
27
+ end
28
+
29
+ context "command" do
30
+ it "should contstruct the correct command" do
31
+ pdfkit = PDFKit.new('html', :page_size => 'Letter')
32
+ pdfkit.command.should include('wkhtmltopdf')
33
+ pdfkit.command.should include('--page-size Letter')
34
+ end
35
+ end
36
+
37
+ context "to_pdf" do
38
+ it "should generate a PDF of the HTML" do
39
+ pdfkit = PDFKit.new('html', :page_size => 'Letter')
40
+ pdf = pdfkit.to_pdf
41
+ pdf.should match(/^%PDF/) # PDF Signature at beginning of file
42
+ end
43
+
44
+ it "should have the stylesheet added to the head if it has one" do
45
+ pdfkit = PDFKit.new("<html><head></head><body>Hai!</body></html>")
46
+ css = File.expand_path(File.dirname(__FILE__) + '/fixtures/example.css')
47
+ pdfkit.stylesheets << css
48
+ pdfkit.to_pdf
49
+ pdfkit.html.should include("<style>#{File.read(css)}</style>")
50
+ end
51
+
52
+ it "should prepend style tags if the HTML doesn't have a head tag" do
53
+ pdfkit = PDFKit.new("<html><body>Hai!</body></html>")
54
+ css = File.expand_path(File.dirname(__FILE__) + '/fixtures/example.css')
55
+ pdfkit.stylesheets << css
56
+ pdfkit.to_pdf
57
+ pdfkit.html.should include("<style>#{File.read(css)}</style><html>")
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1 @@
1
+ body { font-size: 20px; }
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe PDFKit do
4
+
5
+ context "initialization" do
6
+ it "should take HTML for the renderer" do
7
+ pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
8
+ pdfkit.html.should == '<h1>Oh Hai</h1>'
9
+ end
10
+
11
+ it "should parse the options into a cmd line friedly format" do
12
+ pdfkit = PDFKit.new('html', :page_size => 'Letter')
13
+ pdfkit.options.should have_key('--page-size')
14
+ end
15
+
16
+ it "should provide default options" do
17
+ pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
18
+ ['--disable-smart-shrinking', '--margin-top', '--margin-right', '--margin-bottom', '--margin-left'].each do |option|
19
+ pdfkit.options.should have_key(option)
20
+ end
21
+ end
22
+
23
+ it "should not have any stylesheedt by default" do
24
+ pdfkit = PDFKit.new('<h1>Oh Hai</h1>')
25
+ pdfkit.stylesheets.should be_empty
26
+ end
27
+ end
28
+
29
+ context "command" do
30
+ it "should contstruct the correct command" do
31
+ pdfkit = PDFKit.new('html', :page_size => 'Letter')
32
+ pdfkit.command.should include('wkhtmltopdf')
33
+ pdfkit.command.should include('--page-size Letter')
34
+ end
35
+ end
36
+
37
+ context "to_pdf" do
38
+ it "should generate a PDF of the HTML" do
39
+ pdfkit = PDFKit.new('html', :page_size => 'Letter')
40
+ pdf = pdfkit.to_pdf
41
+ pdf.should match(/^%PDF/) # PDF Signature at beginning of file
42
+ end
43
+
44
+ it "should have the stylesheet added to the head if it has one" do
45
+ pdfkit = PDFKit.new("<html><head></head><body>Hai!</body></html>")
46
+ css = File.expand_path(File.dirname(__FILE__) + '/fixtures/example.css')
47
+ pdfkit.stylesheets << css
48
+ pdfkit.to_pdf
49
+ pdfkit.html.should include("<style>#{File.read(css)}</style>")
50
+ end
51
+
52
+ it "should prepend style tags if the HTML doesn't have a head tag" do
53
+ pdfkit = PDFKit.new("<html><body>Hai!</body></html>")
54
+ css = File.expand_path(File.dirname(__FILE__) + '/fixtures/example.css')
55
+ pdfkit.stylesheets << css
56
+ pdfkit.to_pdf
57
+ pdfkit.html.should include("<style>#{File.read(css)}</style><html>")
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'PDFKit'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pdfkit
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - jdpace
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-21 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activesupport
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: rspec
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 2
41
+ - 0
42
+ - 0
43
+ - beta
44
+ - 8
45
+ version: 2.0.0.beta.8
46
+ type: :development
47
+ version_requirements: *id002
48
+ description: Uses wkhtmltopdf to create PDFs using HTML
49
+ email: jared@codewordstudios.com
50
+ executables: []
51
+
52
+ extensions: []
53
+
54
+ extra_rdoc_files:
55
+ - LICENSE
56
+ - README.md
57
+ files:
58
+ - .document
59
+ - .gitignore
60
+ - LICENSE
61
+ - PDFKit.gemspec
62
+ - README.md
63
+ - Rakefile
64
+ - VERSION
65
+ - lib/PDFKit.rb
66
+ - lib/pdfkit/middleware.rb
67
+ - lib/pdfkit/pdfkit.rb
68
+ - spec/PDFKit_spec.rb
69
+ - spec/fixtures/example.css
70
+ - spec/spec.opts
71
+ - spec/spec_helper.rb
72
+ has_rdoc: true
73
+ homepage: http://github.com/jdpace/PDFKit
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --charset=UTF-8
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ segments:
86
+ - 0
87
+ version: "0"
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ requirements: []
96
+
97
+ rubyforge_project:
98
+ rubygems_version: 1.3.6
99
+ signing_key:
100
+ specification_version: 3
101
+ summary: HTML+CSS -> PDF
102
+ test_files:
103
+ - spec/pdfkit_spec.rb
104
+ - spec/spec_helper.rb