Remove ActiveSupport dependency and minor fixes

This commit is contained in:
Adam Bouqdib 2016-05-31 19:08:00 +00:00
parent b135372c30
commit b14ef9be32
7 changed files with 68 additions and 74 deletions

View File

@ -99,7 +99,7 @@ For asset URLs in CSS files we recommend creating a separate CSS file overriding
## To Do ## To Do
- Remove dependencies for ActiveSupport & PDFKit - Remove PDFKit Dependency
- Write tests (rspec) - Write tests (rspec)
- Package default PDF layout file in Gem - Package default PDF layout file in Gem
- Support layouts in partials - Support layouts in partials

View File

@ -1,5 +1,5 @@
Gem::Specification.new do |spec| Gem::Specification.new do |spec|
spec.version = "0.1.0" spec.version = "0.1.2"
spec.homepage = "http://github.com/abemedia/jekyll-pdf/" spec.homepage = "http://github.com/abemedia/jekyll-pdf/"
spec.authors = ["Adam Bouqdib"] spec.authors = ["Adam Bouqdib"]
spec.email = ["adam@abemedia.co.uk"] spec.email = ["adam@abemedia.co.uk"]
@ -16,7 +16,6 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency("wkhtmltopdf-installer", "~> 0.12") spec.add_runtime_dependency("wkhtmltopdf-installer", "~> 0.12")
spec.add_runtime_dependency("pdfkit", "~> 0.8") spec.add_runtime_dependency("pdfkit", "~> 0.8")
spec.add_runtime_dependency("digest", "~> 0") spec.add_runtime_dependency("digest", "~> 0")
spec.add_runtime_dependency("activesupport", "~> 4.2")
spec.add_runtime_dependency("jekyll", ">= 2.0", "~> 3.1") spec.add_runtime_dependency("jekyll", ">= 2.0", "~> 3.1")
spec.add_development_dependency "bundler", "~> 1.6" spec.add_development_dependency "bundler", "~> 1.6"

View File

@ -1,99 +1,99 @@
require 'pdfkit' require 'pdfkit'
require 'active_support/core_ext/hash/deep_merge'
module Jekyll module Jekyll
module PDF module PDF
class Document < Jekyll::Page class Document < Jekyll::Page
include Helper include Helper
def initialize(site, base, page) def initialize(site, base, page)
@site = site @site = site
@base = base @base = base
@dir = File.dirname(page.url) @dir = File.dirname(page.url)
@name = File.basename(page.url, File.extname(page.url)) + ".pdf" @name = File.basename(page.url, File.extname(page.url)) + ".pdf"
@settings = site.config['pdf'] || {} @settings = site.config['pdf'].clone || {}
@partials = ['cover','header_html','footer_html'] @partials = ['cover','header_html','footer_html']
self.process(@name) self.process(@name)
self.data = page.data.clone self.data = page.data.clone
self.content = page.content.clone self.content = page.content.clone
# Set layout to the PDF layout # Set layout to the PDF layout
self.data['layout'] = layout self.data['layout'] = layout
# Get PDF settings from the layouts # Get PDF settings from the layouts
@settings = (site.config['pdf'] || {}).deep_merge(self.getConfig(self.data)) Jekyll::Utils.deep_merge_hashes!(@settings, self.getConfig(self.data))
PDFKit.configure do |config| PDFKit.configure do |config|
config.verbose = site.config['verbose'] config.verbose = site.config['verbose']
end end
# Set pdf_url variable in the source page (for linking to the PDF version) # Set pdf_url variable in the source page (for linking to the PDF version)
page.data['pdf_url'] = self.url page.data['pdf_url'] = self.url
# Set html_url variable in the source page (for linking to the HTML version) # Set html_url variable in the source page (for linking to the HTML version)
self.data['html_url'] = page.url self.data['html_url'] = page.url
# create the partial objects # create the partial objects
@partials.each do |partial| @partials.each do |partial|
@settings[partial] = Jekyll::PDF::Partial.new(self, @settings[partial]) if @settings[partial] != nil @settings[partial] = Jekyll::PDF::Partial.new(self, @settings[partial]) if @settings[partial] != nil
end end
end end
# Recursively merge settings from the page, layout, site config & jekyll-pdf defaults # Recursively merge settings from the page, layout, site config & jekyll-pdf defaults
# todo: use jekyll's merge function # todo: use jekyll's merge function
def getConfig(data) def getConfig(data)
settings = data['pdf'].is_a?(Hash) ? data['pdf'] : {} settings = data['pdf'].is_a?(Hash) ? data['pdf'] : {}
layout = @site.layouts[data['layout']].data.clone if data['layout'] != nil layout = @site.layouts[data['layout']].data.clone if data['layout'] != nil
# No parent layout found - return settings hash # No parent layout found - return settings hash
return settings if layout == nil return settings if layout == nil
# Merge settings with parent layout settings # Merge settings with parent layout settings
layout['pdf'] = (layout['pdf'] || {}).deep_merge(settings) layout['pdf'] ||= {}
Jekyll::Utils.deep_merge_hashes!(layout['pdf'], settings)
return self.getConfig(layout) return self.getConfig(layout)
end end
def write(dest_prefix, dest_suffix = nil) def write(dest_prefix, dest_suffix = nil)
self.render(@site.layouts, @site.site_payload) if self.output == nil self.render(@site.layouts, @site.site_payload) if self.output == nil
path = File.join(dest_prefix, CGI.unescape(self.url)) path = File.join(dest_prefix, CGI.unescape(self.url))
dest = File.dirname(path) dest = File.dirname(path)
# Create directory # Create directory
FileUtils.mkdir_p(dest) unless File.exist?(dest) FileUtils.mkdir_p(dest) unless File.exist?(dest)
# write partials # write partials
@partials.each do |partial| @partials.each do |partial|
@settings[partial].write if @settings[partial] != nil @settings[partial].write if @settings[partial] != nil
end end
# Debugging - create html version of PDF # Debugging - create html version of PDF
File.open("#{path}.html", 'w') {|f| f.write(self.output) } if @settings["debug"] File.open("#{path}.html", 'w') {|f| f.write(self.output) } if @settings["debug"]
@settings.delete("debug") @settings.delete("debug")
# Build PDF file # Build PDF file
fix_relative_paths fix_relative_paths
kit = PDFKit.new(self.output, @settings) kit = PDFKit.new(self.output, @settings)
file = kit.to_file(path) file = kit.to_file(path)
#self.output = kit.to_pdf #self.output = kit.to_pdf
end end
def layout() def layout()
# Set page layout to the PDF layout # Set page layout to the PDF layout
layout = self.data['pdf_layout'] || @settings['layout'] layout = self.data['pdf_layout'] || @settings['layout']
# Check if a PDF version exists for the current layout (e.g. layout_pdf) # Check if a PDF version exists for the current layout (e.g. layout_pdf)
if layout == nil && self.data['layout'] != nil && File.exist?("_layouts/" + self.data['layout'] + "_pdf.html") if layout == nil && self.data['layout'] != nil && File.exist?("_layouts/" + self.data['layout'] + "_pdf.html")
layout = self.data['layout'] + "_pdf" layout = self.data['layout'] + "_pdf"
end end
layout || 'pdf' layout || 'pdf'
end end
end end
end end
end end

View File

@ -3,7 +3,7 @@ module Jekyll
class Generator < Jekyll::Generator class Generator < Jekyll::Generator
safe true safe true
priority :lowest priority :lowest
def generate(site) def generate(site)
# Loop through pages & documents and build PDFs # Loop through pages & documents and build PDFs
[site.pages, site.documents].each do |items| [site.pages, site.documents].each do |items|
@ -12,7 +12,7 @@ module Jekyll
end end
end end
end end
end end
end end
end end

View File

@ -2,8 +2,7 @@ module Jekyll
module PDF module PDF
module Helper module Helper
def fix_relative_paths def fix_relative_paths
prefix = "file://#{site.dest}/" output.gsub!(/(href|src)=(['"])\/([^\/"']([^\"']*|[^"']*))?['"]/, "\\1=\\2file://#{site.dest}/\\3\\2") if output != nil
output = output.gsub(/(href|src)=(['"])\/([^\/"']([^\"']*|[^"']*))?['"]/, "\\1=\\2#{prefix}\\3\\2")
end end
end end
end end

View File

@ -2,7 +2,7 @@
Jekyll::Hooks.register :site, :post_write do |jekyll, payload| Jekyll::Hooks.register :site, :post_write do |jekyll, payload|
if jekyll.data[:jekyll_pdf_partials] if jekyll.data[:jekyll_pdf_partials]
jekyll.data[:jekyll_pdf_partials].each do |partial| jekyll.data[:jekyll_pdf_partials].each do |partial|
partial.clean File.delete(partial) if File.exist?(partial)
end end
jekyll.data.delete(:jekyll_pdf_partials) jekyll.data.delete(:jekyll_pdf_partials)
end end

View File

@ -5,16 +5,16 @@ module Jekyll
module PDF module PDF
class Partial class Partial
extend Forwardable extend Forwardable
attr_accessor :doc attr_accessor :doc
attr_accessor :partial attr_accessor :partial
attr_accessor :write attr_accessor :write
attr_accessor :content, :ext attr_accessor :content, :ext
attr_writer :output attr_writer :output
def_delegators :@doc, :site, :name, :ext, :relative_path, :extname, def_delegators :@doc, :site, :name, :ext, :relative_path, :extname,
:render_with_liquid?, :collection, :related_posts :render_with_liquid?, :collection, :related_posts
# Initialize this Partial instance. # Initialize this Partial instance.
# #
# doc - The Document. # doc - The Document.
@ -25,7 +25,7 @@ module Jekyll
self.partial = partial self.partial = partial
self.content = build_partial(partial) self.content = build_partial(partial)
end end
# Fetch YAML front-matter data from related doc, without layout key # Fetch YAML front-matter data from related doc, without layout key
# #
# Returns Hash of doc data # Returns Hash of doc data
@ -34,101 +34,97 @@ module Jekyll
@data.delete("layout") @data.delete("layout")
@data @data
end end
def trigger_hooks(*) def trigger_hooks(*)
end end
def path def path
File.join(doc.path, partial) File.join(doc.path, partial)
end end
# Returns the file name for the temporary file def id
def filename
File.basename(path, File.extname(path)) + "-" + Digest::MD5.hexdigest(to_s) + File.extname(path) File.basename(path, File.extname(path)) + "-" + Digest::MD5.hexdigest(to_s) + File.extname(path)
end end
# Returns the cache directory # Returns the cache directory
def dir def dir
@dir ||= cache_dir @dir ||= cache_dir
end end
def to_s def to_s
output || content output || content
end end
def to_liquid def to_liquid
doc.data[partial] = nil doc.data[partial] = nil
@to_liquid ||= doc.to_liquid @to_liquid ||= doc.to_liquid
doc.data[partial] = self doc.data[partial] = self
@to_liquid @to_liquid
end end
# Returns the shorthand String identifier of this doc. # Returns the shorthand String identifier of this doc.
def inspect def inspect
"<Partial: #{self.id}>" "<Partial: #{self.id}>"
end end
def output def output
@output ||= Renderer.new(doc.site, self, site.site_payload).run @output ||= Renderer.new(doc.site, self, site.site_payload).run
end end
# generate temp file & set output to it's path # generate temp file & set output to it's path
def write def write
tempfile = File.join(dir, filename) tempfile = File.absolute_path(File.join(dir, id))
unless File.exist?(tempfile) unless File.exist?(tempfile)
FileUtils.mkdir_p(File.dirname(tempfile)) unless File.exist?(File.dirname(tempfile)) FileUtils.mkdir_p(File.dirname(tempfile)) unless File.exist?(File.dirname(tempfile))
File.open(tempfile, 'w') {|f| f.write(to_s) } File.open(tempfile, 'w') {|f| f.write(to_s) }
end end
site.data[:jekyll_pdf_partials] ||= []
site.data[:jekyll_pdf_partials] << self
@output = tempfile @output = tempfile
# store path for cleanup
site.data[:jekyll_pdf_partials] ||= []
site.data[:jekyll_pdf_partials] << "#{self}"
end end
# delete temp file
def clean
File.delete(@output)
end
def place_in_layout? def place_in_layout?
false false
end end
protected protected
def cache_dir def cache_dir
return site.config["pdf"]["cache"] if site.config["pdf"] != nil && site.config["pdf"].has_key?('cache') return site.config["pdf"]["cache"] if site.config["pdf"] != nil && site.config["pdf"].has_key?('cache')
# Use jekyll-assets cache directory if it exists # Use jekyll-assets cache directory if it exists
cache_dir = site.config["assets"]["cache"] || '.asset-cache' if site.config["assets"] != nil cache_dir = site.config["assets"]["cache"] || '.asset-cache' if site.config["assets"] != nil
File.join(cache_dir || Dir.tmpdir(), 'pdf') File.join(cache_dir || Dir.tmpdir(), 'pdf')
end end
# Internal: Generate partial html # Internal: Generate partial html
# #
# Partials are rendered same time as content is rendered. # Partials are rendered same time as content is rendered.
# #
# Returns partial html String # Returns partial html String
def build_partial(path) def build_partial(path)
# vars to insert into partial # vars to insert into partial
vars = ['frompage','topage','page','webpage','section','subsection','subsubsection'] vars = ['frompage','topage','page','webpage','section','subsection','subsubsection']
doc.data["pdf"] = {} doc.data["pdf"] = {}
vars.each { |var| doc.data["pdf"][var] = "<span class='__#{var}'></span>" } vars.each { |var| doc.data["pdf"][var] = "<span class='__#{var}'></span>" }
# JavaScript to replace var placeholders with content # JavaScript to replace var placeholders with content
script = "<script>!function(){var t={},n=document.location.search.substring(1).split('&');for(var e in n){var o=n[e].split('=',2);t[o[0]]=decodeURIComponent(o[1])}var n=#{vars};for(var e in n)for(var r=document.getElementsByClassName('__'+n[e]),a=0;a<r.length;++a)r[a].textContent=t[n[e]]}();</script>\n" script = "<script>!function(){var t={},n=document.location.search.substring(1).split('&');for(var e in n){var o=n[e].split('=',2);t[o[0]]=decodeURIComponent(o[1])}var n=#{vars};for(var e in n)for(var r=document.getElementsByClassName('__'+n[e]),a=0;a<r.length;++a)r[a].textContent=t[n[e]]}();</script>\n"
# Parse & render # Parse & render
content = File.read(File.join("_includes", path)) content = File.read(File.join("_includes", path))
# Add replacer script to body # Add replacer script to body
if content =~ /<\/body>/i if content =~ /<\/body>/i
content[/(<\/body>)/i] = script + content[/(<\/body>)/i] content[/(<\/body>)/i] = script + content[/(<\/body>)/i]
else else
Jekyll.logger.warn <<-eos Jekyll.logger.warn <<-eos
Couldn't find <body> in #{path}. Make sure your partial is a properly formatted HTML document (including DOCTYPE) e.g. Couldn't find <body> in #{path}. Make sure your partial is a properly formatted HTML document (including DOCTYPE) e.g.
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -149,9 +145,9 @@ module Jekyll
</html> </html>
} }
end end
content content
end end
end end
end end