我可以使用 make4ht/tex4ht 在多个 HTML 页面之间建立交叉引用吗?

我可以使用 make4ht/tex4ht 在多个 HTML 页面之间建立交叉引用吗?

这是我的项目的样子。

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}

现在我尝试将它们转换为 HTML foo.htmlbar.html如下所示:

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

bar.html在浏览器中打开时,MathJax\eqref{truth}会将 呈现为(???)。我理解这种行为,因为 MathJax 无法在同一 HTML 中找到标签truth。有没有办法让make4ht/tex4ht输出bar.html以便它可以链接\label{truth}foo.html

答案1

问题是 TeX4ht 无法访问\labelMathJax 模式下数学内部保存的值。所有数学内容都直接传递给 MathJax,不会发生扩展。如果没有标签值,您就无法支持\eqref。所有数学内容都直接传递给 MathJax,不会发生扩展。如果没有标签值,您就无法支持。

解决此问题的一种方法是重用正常 LaTeX 运行中的值。它们存储在文件中.aux,我们可以提取它们并转换为某种可用形式。我们可以在构建文件aux中使用由 LaTeX 创建的信息表单文件make4ht。我们可以使用 Lua 过滤器对生成的 HTML 文件进行后处理,并插入方程的链接目标以及指向它们的超链接,而不是\eqref

我创建了一个 Lua 脚本,将aux文件转换为可以从make4ht构建文件加载的 Lua 模块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 "}"

应该这样使用:

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

该脚本将aux文件中的信息转换为Lua库labelmapping.lua

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

构建make4ht文件后,build.lua就可以使用这个新模块了:

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)

它基本上使用 Luagsub函数插入链接目的地并用标签的正确值\label替换并链接到它。\eqref

使用以下方法编译为 HTML:

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

所结果的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>

bar.html

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

相关内容