1
votes

I'm developing a plugin in Jekyll that inserts a new Liquid Tag (a block tag) named latex. It's purpose is to insert a block of LaTeX source code inside a post source file this way:

... post file contents ...
{% latex density=300 usepackages=pstricks-all, %}
\pspicture(5,5)
\psframe(0,0)(5,5) \psline(0,0)(5,5) \psline(0,5)(5,0)
\endpspicture
{% endlatex %}
... post file contents ...

The output post will contain a <img> tag instead of the Liquid Tag block once compiled and the LaTeX source will be compiled by a chained execution of latex, dvips, convert. So it will depend on external programs (TexLive and ImageMagick).

I've not found any issue with the explained so far. I can take the block of LaTeX, put it in a temporary file, and finally compile it to PNG. The rendered files must be put in the same folder of the post.

But just there I'm stuck: I want to put the generated PNG image to this folder inside the destination output folder. No problem defining a site-config variable to define the folder (in fact, I do that), nor put a file there. The problem is simple: I can write to the source folder, but the generated files will not be copied to the destination folder.

I know the reason: Jekyll generates first and renders afterwards. The copy process happens before the render part, so the generated files will not be copied.

I've found this SO entry: "How to generate files from Liquid blocks in Jekyll?", but the answer doesn't feel right: You must make a two-pass build for the files to be copied.

Also found "Generate file inside _site with Jekyll plugin", but this is not applicable because I don't want to render documents by templates.

The solution I've been planning is this:

  • Keep a folder with all the generated files and some index strategy for their final placement.
  • Implement a Sitewide method for the final placement procedure, something like:

    class Site
        def generate_latex_adds
            // Code that copies the generated files to destination folders
        end
    end
    
  • Add self.generate_latex_adds calling that method inside the site_process.rb script just before the self.cleanup and self.write calls.

This will probably solve the problem, but I feel wrong to modify the site_process.rb. I'm considering pull this Liquid Tag to the community as a GitHub project, and as such, I must document this manual edit of site_process.rb to the users of this plugin. I know it's probably a common situation and a common solution, but I wonder if there is a better way to pospone the copy of the generated files without modifying core files. I'd like to keep the plugin simple: just copy the plugin file to the _plugins directory.

Any ideas?

EDIT: I'm more interested in the reasoning that on the actual code. I want to learn, not asking for a code solution.

1

1 Answers

6
votes

As anyone has answered my question up to now, and I had kept investigating the issue. Finally I've got an elegant solution: use the Jekyll::StaticFile class. I have missed that class (sidenote: Read more carefully the docs).

When you add one object of this class to the site.static_files array, you are marking this file as pending for copy after the render process is completed. In fact, the copy of such files is done in the site.write process. Take a look at the site_process.rb file in your Jekyll installation.

The usage of this class is easy. When you need to mark a file for future copy, you simply execute a code like this:

site.static_files << Jekyll::StaticFile.new(site, site.source, path, filename)

Where path and filename depends on the location of your file in the src folder.

And that's all: You generate the files in the src folder, mark them as pending for copy and let Jekyll do the rest. No modification of site_process.rb at all!

You can take a look at the resulting LaTeX -> PNG liquid tag code at GitHub: https://github.com/fgalindo/jekyll-liquid-latex-plugin

I've also implemented a cleanup method there to eliminate orphaned generated files from posts that have been modified and rebuilt.