diff --git a/README.md b/README.md index a195fd0..f6bba87 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ For asset URLs in CSS files we recommend creating a separate CSS file overriding ## To Do -- Remove dependencies for ActiveSupport & PDFKit +- Remove PDFKit Dependency - Write tests (rspec) - Package default PDF layout file in Gem - Support layouts in partials \ No newline at end of file diff --git a/jekyll-pdf.gemspec b/jekyll-pdf.gemspec index f48fba2..dc87113 100644 --- a/jekyll-pdf.gemspec +++ b/jekyll-pdf.gemspec @@ -1,5 +1,5 @@ Gem::Specification.new do |spec| - spec.version = "0.1.0" + spec.version = "0.1.2" spec.homepage = "http://github.com/abemedia/jekyll-pdf/" spec.authors = ["Adam Bouqdib"] 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("pdfkit", "~> 0.8") spec.add_runtime_dependency("digest", "~> 0") - spec.add_runtime_dependency("activesupport", "~> 4.2") spec.add_runtime_dependency("jekyll", ">= 2.0", "~> 3.1") spec.add_development_dependency "bundler", "~> 1.6" diff --git a/lib/jekyll/pdf/document.rb b/lib/jekyll/pdf/document.rb index ab85949..78f8d1c 100644 --- a/lib/jekyll/pdf/document.rb +++ b/lib/jekyll/pdf/document.rb @@ -1,99 +1,99 @@ require 'pdfkit' -require 'active_support/core_ext/hash/deep_merge' - + module Jekyll module PDF class Document < Jekyll::Page include Helper - + def initialize(site, base, page) @site = site @base = base @dir = File.dirname(page.url) @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'] - + self.process(@name) self.data = page.data.clone self.content = page.content.clone - + # Set layout to the PDF layout self.data['layout'] = layout - + # 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| config.verbose = site.config['verbose'] end - + # Set pdf_url variable in the source page (for linking to the PDF version) page.data['pdf_url'] = self.url - + # Set html_url variable in the source page (for linking to the HTML version) self.data['html_url'] = page.url - + # create the partial objects @partials.each do |partial| @settings[partial] = Jekyll::PDF::Partial.new(self, @settings[partial]) if @settings[partial] != nil end end - + # Recursively merge settings from the page, layout, site config & jekyll-pdf defaults # todo: use jekyll's merge function def getConfig(data) settings = data['pdf'].is_a?(Hash) ? data['pdf'] : {} layout = @site.layouts[data['layout']].data.clone if data['layout'] != nil - + # No parent layout found - return settings hash return settings if layout == nil - + # 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) end - + def write(dest_prefix, dest_suffix = nil) self.render(@site.layouts, @site.site_payload) if self.output == nil - + path = File.join(dest_prefix, CGI.unescape(self.url)) dest = File.dirname(path) - + # Create directory FileUtils.mkdir_p(dest) unless File.exist?(dest) - + # write partials @partials.each do |partial| @settings[partial].write if @settings[partial] != nil end - + # Debugging - create html version of PDF File.open("#{path}.html", 'w') {|f| f.write(self.output) } if @settings["debug"] @settings.delete("debug") - + # Build PDF file fix_relative_paths kit = PDFKit.new(self.output, @settings) file = kit.to_file(path) - + #self.output = kit.to_pdf end - + def layout() # Set page layout to the PDF layout layout = self.data['pdf_layout'] || @settings['layout'] - + # 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") - layout = self.data['layout'] + "_pdf" + layout = self.data['layout'] + "_pdf" end - + layout || 'pdf' end - + end - + end end diff --git a/lib/jekyll/pdf/generator.rb b/lib/jekyll/pdf/generator.rb index 69fe6c8..dafaa25 100644 --- a/lib/jekyll/pdf/generator.rb +++ b/lib/jekyll/pdf/generator.rb @@ -3,7 +3,7 @@ module Jekyll class Generator < Jekyll::Generator safe true priority :lowest - + def generate(site) # Loop through pages & documents and build PDFs [site.pages, site.documents].each do |items| @@ -12,7 +12,7 @@ module Jekyll end end end - + end end end diff --git a/lib/jekyll/pdf/helper.rb b/lib/jekyll/pdf/helper.rb index f040746..cf12808 100644 --- a/lib/jekyll/pdf/helper.rb +++ b/lib/jekyll/pdf/helper.rb @@ -2,8 +2,7 @@ module Jekyll module PDF module Helper def fix_relative_paths - prefix = "file://#{site.dest}/" - output = output.gsub(/(href|src)=(['"])\/([^\/"']([^\"']*|[^"']*))?['"]/, "\\1=\\2#{prefix}\\3\\2") + output.gsub!(/(href|src)=(['"])\/([^\/"']([^\"']*|[^"']*))?['"]/, "\\1=\\2file://#{site.dest}/\\3\\2") if output != nil end end end diff --git a/lib/jekyll/pdf/hooks.rb b/lib/jekyll/pdf/hooks.rb index db10670..a9ca945 100644 --- a/lib/jekyll/pdf/hooks.rb +++ b/lib/jekyll/pdf/hooks.rb @@ -2,7 +2,7 @@ Jekyll::Hooks.register :site, :post_write do |jekyll, payload| if jekyll.data[:jekyll_pdf_partials] jekyll.data[:jekyll_pdf_partials].each do |partial| - partial.clean + File.delete(partial) if File.exist?(partial) end jekyll.data.delete(:jekyll_pdf_partials) end diff --git a/lib/jekyll/pdf/partial.rb b/lib/jekyll/pdf/partial.rb index e79e197..4f12472 100644 --- a/lib/jekyll/pdf/partial.rb +++ b/lib/jekyll/pdf/partial.rb @@ -5,16 +5,16 @@ module Jekyll module PDF class Partial extend Forwardable - + attr_accessor :doc attr_accessor :partial attr_accessor :write attr_accessor :content, :ext attr_writer :output - + def_delegators :@doc, :site, :name, :ext, :relative_path, :extname, :render_with_liquid?, :collection, :related_posts - + # Initialize this Partial instance. # # doc - The Document. @@ -25,7 +25,7 @@ module Jekyll self.partial = partial self.content = build_partial(partial) end - + # Fetch YAML front-matter data from related doc, without layout key # # Returns Hash of doc data @@ -34,101 +34,97 @@ module Jekyll @data.delete("layout") @data end - + def trigger_hooks(*) end - + def path File.join(doc.path, partial) end - - # Returns the file name for the temporary file - def filename + + def id File.basename(path, File.extname(path)) + "-" + Digest::MD5.hexdigest(to_s) + File.extname(path) end - + # Returns the cache directory def dir @dir ||= cache_dir end - + def to_s output || content end - + def to_liquid doc.data[partial] = nil @to_liquid ||= doc.to_liquid doc.data[partial] = self @to_liquid end - + # Returns the shorthand String identifier of this doc. def inspect "" end - + def output @output ||= Renderer.new(doc.site, self, site.site_payload).run end - + # generate temp file & set output to it's path def write - tempfile = File.join(dir, filename) + tempfile = File.absolute_path(File.join(dir, id)) unless File.exist?(tempfile) FileUtils.mkdir_p(File.dirname(tempfile)) unless File.exist?(File.dirname(tempfile)) File.open(tempfile, 'w') {|f| f.write(to_s) } end - site.data[:jekyll_pdf_partials] ||= [] - site.data[:jekyll_pdf_partials] << self @output = tempfile + + # store path for cleanup + site.data[:jekyll_pdf_partials] ||= [] + site.data[:jekyll_pdf_partials] << "#{self}" end - - # delete temp file - def clean - File.delete(@output) - end - + def place_in_layout? false end - + protected - + def cache_dir return site.config["pdf"]["cache"] if site.config["pdf"] != nil && site.config["pdf"].has_key?('cache') - + # Use jekyll-assets cache directory if it exists cache_dir = site.config["assets"]["cache"] || '.asset-cache' if site.config["assets"] != nil - + File.join(cache_dir || Dir.tmpdir(), 'pdf') end - + # Internal: Generate partial html # # Partials are rendered same time as content is rendered. # # Returns partial html String def build_partial(path) - + # vars to insert into partial vars = ['frompage','topage','page','webpage','section','subsection','subsubsection'] doc.data["pdf"] = {} vars.each { |var| doc.data["pdf"][var] = "" } - + # JavaScript to replace var placeholders with content script = "\n" - + # Parse & render content = File.read(File.join("_includes", path)) - + # Add replacer script to body if content =~ /<\/body>/i content[/(<\/body>)/i] = script + content[/(<\/body>)/i] else Jekyll.logger.warn <<-eos Couldn't find in #{path}. Make sure your partial is a properly formatted HTML document (including DOCTYPE) e.g. - + @@ -149,9 +145,9 @@ module Jekyll } end - + content - + end end end