When converting a document with pandoc to ODT or DOCX it is possible to specify a reference document with --reference-doc=. The produced file will use the styles from the reference document. This leads to a very lean workflow:

  1. Convert your document with pandoc
  2. Adjust the styles in the output document
  3. Use this document as a reference document for future conversions

Now, I was thinking whether this something similar could be done with make4ht.

I know that it is possible to adjust the styles in the resulting ODT file, and that it is now also possible to run lua filters (see this question). Yet, as ODT files are basically just ZIP archives, I thought that there could be a simpler solution: Extract the file styles.xml from an ODT file (the reference document) and add it to the ODT file produced with tex4ht.

Is it be possible to automate this process with make4ht? (Of course, using a simple makefile would be a solution, but I think a more integrated solution might be nice.)

  • I agree that the potential for pandoc to handle the conversion with a reference template is extremely lean and very promising. I've tested the conversion from html to docx with a docx template passed to pandoc, but I've yet to be able to test this with a tex4ht created ODT file (errors about parsing the file are returned). Are you able to go make4ht to ODT to DOCX via pandoc?
    – EngBIRD
    Dec 20 '18 at 2:58
  • If I use the ODT file produced with make4ht I am getting an error message: "couldn't parse odt file'. However, pandoc produces a DOCX if I start pandoc after opening the ODT, changing something and saving it again. However, this is still far from being perfect, e.g. some styles get lost. It might be easier to use libreoffice for the conversion to DOCX, you can even do this from the command line if you wish: soffice --headless --convert-to docx
    – Denis
    Dec 20 '18 at 13:04
  • Indeed this headless Libre office conversion is my current approach. The shear size of Libre office for conversion purposes is a little unfortunate, but it does work. I leave the pandoc conversion with a distinct target file name as part of my compile script so that I'll notice if and when the tex4ht out becomes compatible with pandoc or vice-versa. Thanks for the confirmation. The issue appears similar to one reported with calligra.
    – EngBIRD
    Dec 20 '18 at 14:42


the development version of make4ht has the following code integrated as odttemplate filter and extension. It can be used in the following way:

 make4ht -f odt+odttemplate filename.tex "odttemplate=template.odt"

Original answer:

The following build file extracts the styles.xml from a template ODT file. It acts as a filter on the styles file produced by tex4ht and replaces its contents by the extracted file:

local filter = require "make4ht-filter"
local mkutils = require "mkutils"
local zip = require "zip"

-- filter_settings "odttemplate" {
--   filename = "test.odt"
-- }

local function get_template_filename()
  -- either get the template odt filename from tex4ht.sty options (make4ht filename.tex "odttemplate=test.odt")
  local tex4ht_settings = settings.tex4ht_sty_par
  local templatefile = tex4ht_settings:match("odttemplate=([^%,]+)")
  if templatefile then return templatefile end
  -- read the template odt filename from settings
  local filtersettings = get_filter_settings "odttemplate"
  return filtersettings.filename

local process = filter {function(content)
  local templatefile = get_template_filename()
  -- don't do anything if the template file doesn't exist
  if not templatefile or not mkutils.file_exists(templatefile) then return content end
  local odtfile = zip.open(templatefile)
  local stylesfile = odtfile:open("styles.xml")
  -- just break if the styles cannot be found
  if not stylesfile then return content end
  local styles = stylesfile:read("*all")
  return styles
-- the styles.xml is saved in a file with .4oy extension
Make:match("4oy$", process)

There are two ways how to pass information about the template file to the filter. First one is commented out in the build file. Use the filter_settings function:

 filter_settings "odttemplate" {
   filename = "test.odt"

The second way is to pass it in the tex4ht.sty options. It means either on the command line or in the \Preamble command in a private configuration file. This is how to use it from the command line:

make4ht -f odt -u sample.tex "odttemplate=test.odt"

Here is a sample that uses modified ODT file produced by tex4ht. The headings style had been changed to use a red color:

enter image description here

  • Wow, that looks promising. But where do I save the filter?
    – Denis
    Dec 13 '18 at 20:14
  • Ok, found it out: If my file is called "test.tex" the build file should be called test.mk4; or, if you choose a different name it must be called with the -e command line option.
    – Denis
    Dec 13 '18 at 20:25
  • @Denis yes, you found the correct way :)
    – michal.h21
    Dec 13 '18 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.