Indenting generated markup in Jekyll/Ruby

前端 未结 2 814
醉话见心
醉话见心 2021-02-02 14:25

Well this is probably kind of a silly question but I\'m wondering if there\'s any way to have the generated markup in Jekyll to preserve the indentation of the Liquid-tag. World

2条回答
  •  傲寒
    傲寒 (楼主)
    2021-02-02 15:15

    Using a Liquid Filter

    I managed to make this work using a liquid filter. There are a few caveats:

    • Your input must be clean. I had some curly quotes and non-printable chars that looked like whitespace in a few files (copypasta from Word or some such) and was seeing "Invalid byte sequence in UTF-8" as a Jekyll error.

    • It could break some things. I was using icons from twitter bootstrap. It replaced the empty tag with and bootstrap did not like that. Additionally, it screws up the octopress {% codeblock %}s in my content. I didn't really look into why.

    • While this will clean the output of a liquid variable such as {{ content }} it does not actually solve the problem in the original post, which is to indent the html in context of the surrounding html. This will provide well formatted html, but as a fragment that will not be indented relative to tags above the fragment. If you want to format everything in context, use the Rake task instead of the filter.

    -

    require 'rubygems'
    require 'json'
    require 'nokogiri'
    require 'nokogiri-pretty'
    
    module Jekyll
      module PrettyPrintFilter
        def pretty_print(input)
          #seeing some ASCII-8 come in
          input = input.encode("UTF-8")
    
          #Parsing with nokogiri first cleans up some things the XSLT can't handle
          content = Nokogiri::HTML::DocumentFragment.parse input
          parsed_content = content.to_html
    
          #Unfortunately nokogiri-pretty can't use DocumentFragments...
          html = Nokogiri::HTML parsed_content
          pretty = html.human
    
          #...so now we need to remove the stuff it added to make valid HTML
          output = PrettyPrintFilter.strip_extra_html(pretty)
          output
        end
    
        def PrettyPrintFilter.strip_extra_html(html)
          #type declaration
          html = html.sub('','')
    
          #second  tag
          first = true
          html = html.gsub('') do |match|
            if first == true
              first = false
              next
            else
              ''
            end
          end
    
          #first  tag
          html = html.sub('','')
    
          #second  tag
          first = true
          html = html.gsub('') do |match|
            if first == true
              first = false
              next
            else
              ''
            end
          end
    
          #first  tag
          html = html.sub('','')
    
          #second  tag
          first = true
          html = html.gsub('') do |match|
            if first == true
              first = false
              next
            else
              ''
            end
          end
    
          #first  tag
          html = html.sub('','')
    
          html
        end
      end
    end
    
    Liquid::Template.register_filter(Jekyll::PrettyPrintFilter)
    

    Using a Rake task

    I use a task in my rakefile to pretty print the output after the jekyll site has been generated.

    require 'nokogiri'
    require 'nokogiri-pretty'
    
    desc "Pretty print HTML output from Jekyll"
    task :pretty_print do
      #change public to _site or wherever your output goes
      html_files = File.join("**", "public", "**", "*.html")
    
      Dir.glob html_files do |html_file|
        puts "Cleaning #{html_file}"
    
        file = File.open(html_file)
        contents = file.read
    
        begin
          #we're gonna parse it as XML so we can apply an XSLT
          html = Nokogiri::XML(contents)
    
          #the human() method is from nokogiri-pretty. Just an XSL transform on the XML.
          pretty_html = html.human
        rescue Exception => msg
          puts "Failed to pretty print #{html_file}: #{msg}"
        end
    
        #Yep, we're overwriting the file. Potentially destructive.
        file = File.new(html_file,"w")
        file.write(pretty_html)
    
        file.close
      end
    end
    

提交回复
热议问题