Guest User

code2pdf support for custom css

a guest
Mar 31st, 2020
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 3.32 KB | None | 0 0
  1. require 'cgi'
  2. require 'shellwords'
  3.  
  4. class ConvertToPDF
  5.   PDF_OPTIONS = {
  6.     page_size: 'A4'
  7.   }.freeze
  8.  
  9.   def initialize(params = {})
  10.     if !params.key?(:from) || params[:from].nil?
  11.       raise ArgumentError.new 'where is the codebase you want to convert to PDF?'
  12.     elsif !valid_directory?(params[:from])
  13.       raise LoadError.new "#{params[:from]} not found"
  14.     elsif !params.key?(:to) || params[:to].nil?
  15.       raise ArgumentError.new 'where should I save the generated pdf file?'
  16.     else
  17.       @from, @to, @except = params[:from], params[:to], params[:except].to_s
  18.  
  19.       if File.exist?(@except) && invalid_blacklist?
  20.         raise LoadError.new "#{@except} is not a valid blacklist YAML file"
  21.       end
  22.  
  23.       save
  24.     end
  25.   end
  26.  
  27.   private
  28.  
  29.   def save
  30.     pdf.to_file(@to)
  31.   end
  32.  
  33.   def pdf
  34.     html ||= ''
  35.  
  36.     style = 'size: 12px; font-size: 22px; font-family: Helvetica, sans-serif;'
  37.     codestyle = 'font-size: 22px !important;'
  38.  
  39.     read_files.each do |file|
  40.       html += "<strong style='#{style}'>File: #{file.first}</strong></br></br>"
  41.       html += "<code style='#{codestyle}'>" + prepare_line_breaks(syntax_highlight(file)).to_s + "</code>"
  42.       html += add_space(30)
  43.     end
  44.  
  45.     @kit = PDFKit.new(html, page_size: 'A4')
  46.     @kit.stylesheets << './syntax.css'
  47.     @kit
  48.   end
  49.  
  50.   def syntax_highlight(file)
  51.     file_type = File.extname(file.first)[1..-1]
  52.     file_lexer = Rouge::Lexer.find(file_type)
  53.     return CGI.escapeHTML(file.last) unless file_lexer
  54.      
  55.     formatter = Rouge::Formatters::HTMLLegacy.new({line_numbers: true})
  56.     code_data = file.last.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
  57.     formatter.format(file_lexer.lex(code_data))
  58.   end
  59.  
  60.   def invalid_blacklist?
  61.     return true if FileTest.directory?(@except)
  62.  
  63.     @blacklist = YAML.load_file(@except)
  64.  
  65.     !@blacklist.key?(:directories) || !@blacklist.key?(:files)
  66.   end
  67.  
  68.   def in_directory_blacklist?(item_path)
  69.     @blacklist[:directories].include?(item_path.gsub("#{@from}/", '')) if @blacklist
  70.   end
  71.  
  72.   def in_file_blacklist?(item_path)
  73.     if @blacklist
  74.       @blacklist[:files].include?(item_path.split('/').last) || @blacklist[:files].include?(item_path.gsub("#{@from}/", ''))
  75.     end
  76.   end
  77.  
  78.   def valid_directory?(dir)
  79.     File.exist?(dir) && FileTest.directory?(dir)
  80.   end
  81.  
  82.   def valid_file?(file)
  83.     File.exist?(file) && FileTest.file?(file)
  84.   end
  85.  
  86.   def read_files(path = nil)
  87.     @files ||= []
  88.     path   ||= @from
  89.  
  90.     Dir.foreach(path) do |item|
  91.       item_path = "#{path}/#{item}"
  92.  
  93.       if valid_directory?(item_path) && !%w[. ..].include?(item) && !in_directory_blacklist?(item_path)
  94.         read_files(item_path)
  95.       elsif valid_file?(item_path) && !in_file_blacklist?(item_path)
  96.         @files << [item_path, process_file(item_path)]
  97.       end
  98.     end
  99.  
  100.     @files
  101.   end
  102.  
  103.   def process_file(file)
  104.     puts "Reading file #{file}"
  105.  
  106.     content = ''
  107.     File.open(file, 'r') do |f|
  108.       if `file #{file.shellescape}` !~ /text/
  109.         content << '[binary]'
  110.       else
  111.         f.each_line { |line_content| content << line_content }
  112.       end
  113.     end
  114.     content
  115.   end
  116.  
  117.   def prepare_line_breaks(content)
  118.     content.gsub(/\n/, '<br>')
  119.   end
  120.  
  121.   def add_space(height)
  122.     "<div style='margin-bottom: #{height}px'>&nbsp;</div>"
  123.   end
  124. end
Advertisement
Add Comment
Please, Sign In to add comment