2

Here is how my project looks.

foo.tex:

\documentclass{article}
\usepackage{amsmath}
\usepackage{hyperref}
\begin{document}
\begin{equation}
\label{truth}
1 + 1 = 2
\end{equation}
\( \eqref{truth} \) refers to an obvious truth.
\end{document}

bar.tex:

\documentclass{article}
\usepackage{amsmath}
\usepackage{hyperref}
\begin{document}
\( \eqref{truth} \) refers to an obvious truth.
\end{document}

Now I try to convert them to HTMLs foo.html and bar.html like this:

make4ht foo.tex mathjax
make4ht foo.tex mathjax
make4ht bar.tex mathjax
make4ht bar.tex mathjax

When bar.html is opened in browser, the \eqref{truth} is rendered as (???) by MathJax. I understand this behavior because MathJax does not find the label truth in the same HTML. Is there a way to make make4ht/tex4ht output a bar.html so that it can link to \label{truth} in foo.html?

2
  • I guess that this could be a feature request for MathJax. But I think that at best, you could be able to obtain the id of the equation so you can construct the link yourself. But at the moment, even this is not possible, AFAIK.
    – michal.h21
    Commented May 15, 2021 at 20:08
  • @michal.h21 I don't understand the full details of the various components involved, but would it be possible that tex4ht resolves the label text and the linked document through xr-hyper, constructs an html hyperlink, then generates the MathJax code for the label text, and outputs this together (something like <a href="foo.html#x1-2r1">[MathJax code for (1)]</a>? Of course this would require that the user adds xr-hyper and \externaldocument, as in regular LaTeX.
    – Marijn
    Commented May 16, 2021 at 12:44

1 Answer 1

4

The problem is that TeX4ht doesn't have access to values saved by \label inside math in the MathJax mode. All math contents are passed literally to MathJax, no expansion happens. Without label values, you cannot support \eqref.

One way how to work around this issue is to reuse values from normal LaTeX run. They are stored in the .aux file, and we can extract them and transform to some usable form. We can use the information form aux files created by LaTeX in a make4ht build file. We can post-process the generated HTML files using Lua filters, and insert link destinations for equations, and hyperlinks pointing to them instead of \eqref.

I've created a Lua script that transform aux files into Lua module that can be loaded from the make4ht build file, getlabels.lua:

-- execute by:
--   texlua getlabels.lua *.aux > labelmapping.lua
-- note that these aux files need to be produced by pdflatex, 
-- as we need preserved value of referenced counters

-- this will contain all labels, their values and files where they were used
local map = {}
-- 
local function load_file(filename)
  local f = io.open(filename, "r")
  if not f then return nil, "cannot open file " .. filename end
  local content = f:read("*all")
  f:close()
  return content
end

local function parse_aux(aux_filename) 
  local content, msg = load_file(aux_filename)
  if not content then
    print("Error: " .. msg)
    return nil
  end
  local jobname = aux_filename:gsub(".aux$", "")
  -- parse aux file for saved \newlabel
  for label, refs in content:gmatch("\\newlabel{(.-)}(%b{})") do
    -- get the first value in brackets. it holds the referenced counter.
    local value = refs:match("{{([^{]-)}")
    -- save mapping between label and correspoing value and file where it was used
    if value then
      map[label] = {value = value, jobname = jobname}
    end
    -- local 
  end


end

for _, filename in ipairs(arg) do
  -- process all aux files and create mapping
  parse_aux(filename)
end

-- print the mapping table in the form that is suitable for 
-- loading by Lua's `require` statement
print "return {"

for label, properties in pairs(map) do
  print('  ["' .. label .. '"] = {')
  print('    value = "' .. properties.value ..  '",')
  print('    jobname = "' .. properties.jobname ..  '"')
  print("  },")
end
print "}"

It should be used like this:

pdflatex foo
pdflatex bar
texlua getlabels.lua *.aux > labelmapping.lua

This script transforms information from aux files into Lua library, labelmapping.lua:

return {
  ["truth"] = {
    value = "1",
    jobname = "sample"
  },
}

The make4ht build file, build.lua then can use this new module:

local filter = require "make4ht-filter"

-- the labelmapping.lua file should be produced using:
-- texlua getlabels.lua *.aux > labelmapping.lua
-- it is necessary that this command is executed on files
-- produced by pdflatex (or lualatex or xelatex). 
local mapping = require "labelmapping"

local process = filter {
  -- add link destinations for \label
  function(content, par)
    -- it inserts destination after the nearest HTML tag that precedes \label
    return content:gsub(">([^>]+)\\label%s*{(.-)}", function(start, label)
      return "><a id='" .. label .. "'></a>" .. start .. "\\label{" .. label .."}"
    end)
  end,
  --- handle \eqref
  function(content, par)
    local function handle_eqref(content, pattern)
      -- this function loops for all \eqref commands and replaces them with 
      -- hyperlinks to the correct location. Hyperlink text is the counter value
      -- as saved by latex.
      return content:gsub(pattern, function(label)
        local map = mapping[label]
        -- don't process eqrefs that are not in the mapping table
        if not map then return nil end
        local htmlfile = map.jobname .. ".html"
        -- don't use path to the html file if the link points inside the same file
        if map.jobname == par.input then htmlfile = "" end
        return string.format('(<a href="%s#%s">%s</a>)', htmlfile, label, map.value)
      end)
    end
    -- \(\eqref{label}\)
    local content = handle_eqref(content, "\\%(%s*\\eqref%s*{(.-)}%s*\\%)")
    -- $\eqref{label}$
    local content = handle_eqref(content,"%$%s*\\eqref%s*{(.-)}%s*%$")
    return content
  end

}

-- execute the filter chain for all generated HTML files
Make:match("html$", process)

It basically uses Lua gsub function to insert link destinations to \label and to replace \eqref with correct value of the label and link to it.

Compile to HTML using:

make4ht -e build.lua foo "mathjax"
make4ht -e build.lua bar "mathjax"

The resulting foo.html:

<p class='noindent'><a id='truth'></a>\begin {equation} \label{truth} 1 + 1 = 2 \end {equation}
</p><!-- l. 10 --><p class='noindent'>(<a href='#truth'>1</a>) refers to an obvious truth.
</p>

and bar.html:

<p class='noindent'>(<a href='sample.html#truth'>1</a>) refers to an obvious truth. </p> 
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .