jgm / pandoc

Universal markup converter
https://pandoc.org
Other
34.54k stars 3.38k forks source link

Enhancement: Add a template variable that refers to the template location itself #6519

Open MrJohz opened 4 years ago

MrJohz commented 4 years ago

I'm trying to write a set of templates that can be shared between my team members, so that we can generate reports that have a consistent style. These templates include assets such as images and fonts that can't easily be included via the existing template partials mechanism. What I would like is a way to reference these assets in as cross-platform a way as possible.

Problem

For example, I have a template folder structure like this:

|--+ assets/
|  |-- Company_Font.ttf
|  `-- Company_Logo.eps
`-- template.latex

... and a LaTeX template that looks something like this:

% ...
\setmainfont[Path=assets/]{Company_Font}
\includegraphics{assets/Company_Logo}
% ...

If I use this template directly, this line will be executed in the context of the working directory of the user running pandoc, which means that the person generating these documents needs to have the entire assets directory in every folder that they want to run pandoc in - this is obviously a bit ridiculous.

Alternatively, I could hard-code the path to the location that I want to install these templates. For example, on my Linux system, I might do something like:

% ...
\setmainfont[Path=/usr/share/pandoc/data/templates/assets/]{Company_Font}
\includegraphics{/usr/share/pandoc/data/templates/assets/Company_Logo}
% ...

Then as part of the install step, I can just run:

$ cp template.latex /usr/share/pandoc/data/templates/my-style.latex
$ cp assets/ /usr/share/pandoc/data/templates/assets/

This works, but it's very fragile:

Suggested Solution

I suggest adding template variables like $__file__$ and $__dir__$ that will always refer to the location of the file being templated, as it's being templated. So:

This way, I can write my template to look something like this:

% ...
\setmainfont[Path=$__dir__$/assets/]{Company_Font}
\includegraphics{$__dir__$/assets/Company_Logo}
% ...

Now, as long as I install my template to a location together with the assets directory, I don't need to know where that location is.

jgm commented 4 years ago

which means that the person generating these documents needs to have the entire assets directory in every folder that they want to run pandoc in - this is obviously a bit ridiculous.

A good use case for symbolic links!

jgm commented 4 years ago

I suppose the most straightforward way to implement this would be to modify Text.Pandoc.App.OutputSettings, so that if getTemplate succeeds we add variables template-path and template-dir to writerVariables. I fear that __file__ and __dir__ will be construed as referring to the file path rather than the template path, but maybe not.

mhwombat commented 1 year ago

I also want this feature very much.

mhwombat commented 1 year ago

I developed a collection of company-branded Pandoc/LaTeX templates for my colleagues to use, so I have the same problem. At the moment, I'm using an ugly hack for this.

In the directory where Pandoc is invoked, the user must create a file called config.yaml which sets the value of template-dir to the location of the directory where they installed my custom templates.

For each template, I have a YAML file that includes the line metadata-file: config.yaml, allowing it access to the $template-dir$ variable.

All of my templates then specify the path of the resources they need relative to $template-dir$ .

The users invoke pandoc with a command like this:

pandoc myfile.md -o myfile.pdf --data-dir=/path/to/the/templates --defaults=mycustomtemplate

But now I want to create a Nix / NixOS package for my templates, and this hack becomes very impractical.