我们的组织已将参考手册以 LaTeX 格式发布。这是一本基本的 300 页参考手册,包含表格、图表和章节。该组织还拥有出版物数据库,用于跟踪文档的提交和流程。数据库中有帮助“窗口”。他们希望将帮助链接到 Latex 参考手册的特定部分,以便当用户单击帮助按钮时,手册的特定部分就会显示出来。我查看过 PDF 目标链接,但我认为这太费力,而且并不总是显示正确的位置。实用htlatex
程序似乎是可行的方法。问题是:
\label
标记 LaTeX 文件以便转换为 HTML属性的最佳方法是什么id
?
下面是我的 LaTeX 文件的示例:
\section{Section heading}\label{sec:intro}
Blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah. Here is a citation\,\cite{EXAMPLE}.
Blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
blah blah blah blah blah blah.
This is a test to link to Section this text is for searching in HTML Karen heading \ref{sec:intro}.
以下是我的 HTML 输出:
<a id="x1-2r1"></a>
<!--l. 80--><p class="noindent" ><span class="phvb8t-x-x-164">1</span>
<span class="phvb8t-x-x-164">Section</span>
<span class="phvb8t-x-x-164">heading</span>
<a id="Q1-1-0"></a><!--l. 80--><p class="noindent">
<!--l. 82--><p class="noindent" >Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah. Here is a citation <span class="cite">[<a href="#XEXAMPLE">1</a>]</span>.
<!--l. 86--><p class="noindent" >Blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah blah.
<!--l. 90--><p class="noindent" >This is a test to link to Section heading
<a href="#x1-2r1">1<!--tex4ht:ref: sec:intro --></a>.
我希望 id<a>
为<a id="sec:intro">
。
答案1
您可以尝试以下配置文件config.cfg
:
\Preamble{xhtml}
\catcode`\:=11
% redefine \label to output link with the current label as id
% \o:label: calls the original label
\def\:tempa#1{\Link{}{#1}\EndLink\o:label:{#1}}
\HLet\label\:tempa
% configure \ref
% \Link{\RefArg}{} starts link. \RefArg contains the label
% we use \:gobble to remove the id generated by TeX4ht, it would
% end in the hyperlinked text otherwise
\Configure{ref}{\Link{\RefArg}{}\:gobble}{\EndLink}{}
\catcode`\:=12
\begin{document}
\EndPreamble
您可以使用以下命令来使用它:
htlatex filename.tex "config"
或者,最好htlatex
使用
make4ht -c config.cfg filename.tex
您可以阅读有关两者的区别这里
在配置文件中,我们重新定义\label
插入额外的<a id="[label]"></a>
标签。它使用\label
参数来构造你可以链接到的id。要使用此id
from\ref
命令,我们需要提供一个\Configure{ref}
命令。详细描述在配置文件中的注释中。
现在有一个问题。由于\label
使用 after \section
,目标链接插入在 section 之后,这将导致用户在单击标签的超链接时将结束 section 下方的页面。查看生成的 HTML 代码:
<h3 class='sectionHead' id='section-heading'><span class='titlemark'>1 </span> <a id='x1-10001'></a>Section heading</h3>
<!-- l. 4 --><p class='noindent'><a id='sec:intro'></a>
...
</p><!-- l. 14 --><p class='indent'> This is a test to link to Section this text is for searching in HTML Karen heading
<a href='#sec:intro'>1</a>. </p>
这个问题在 TeX 级别很难解决,所以我建议另一种选择,即使用make4ht
构建文件。
make4ht
支持 Lua 构建文件。它们可用于对生成的 HTML 文件进行后处理。它甚至支持 LuaXML DOM 对象,因此我们可以轻松遍历文档并更新所有<a>
元素。
我们可以使用.aux
文件中存储的信息。标签与 TeX4ht 分配的之间的映射id
以以下形式存储在这里:
\newlabel{sec:intro}{{\rEfLiNK{x1-10001}{1}}{\rEfLiNK{x1-10001}{1}}}
可以看到标签存放在 的第一个参数中\newlabel
,ID 是 的第一个参数\rEfLiNK
。
这是构建文件build.lua
:
local domfilter = require "make4ht-domfilter"
-- we need to parse the aux file to get mapping between labels and id attribute
-- of the corresponding <a> element
local function parse_aux(aux_filename)
local mapping = {}
local f = io.open(aux_filename, "r")
local content = f:read("*all")
f:close()
-- labels are stored in this form:
-- \newlabel{sec:intro}{{\rEfLiNK{x1-10001}{1}}{\rEfLiNK{x1-10001}{1}}}
for label, id in content:gmatch("newlabel{(.-)}{{.-{(.-)}") do
mapping[id] = label
end
return mapping
end
-- this will hold table with mapping between existing ids and labels
local aux
-- chain of functions that will process all generated HTML files
local process = domfilter {
function(dom, properties)
-- because there can be multiple HTML file, we want to reuse existing
-- mapping when we process subsequent files
aux = aux or parse_aux(properties.input .. ".aux")
-- process all <a> elements and replace ids generated by TeX4ht by original labels
for _, a in ipairs(dom:query_selector("a")) do
-- update id attributes
local id = a:get_attribute("id")
if aux[id] then a:set_attribute("id", aux[id]) end
local href = a:get_attribute("href")
-- fix links
if href then
-- get url and id from the hyperlink
local url, id = href:match("(.*)#(.+)")
if id and aux[id] then
-- update hyperlink
a:set_attribute("href", string.format("%s#%s", url or "", aux[id]))
end
end
end
return dom
end
}
Make:match("html$", process)
此构建文件首先解析 AUX 文件并生成 TeX4ht 指定的 ID 属性与原始标签之间的映射。然后它循环遍历所有<a>
元素并更新 ID 和超链接。
您可以使用以下命令编译您的文档:
make4ht -e build.lua filename.tex
结果如下:
<h3 class='sectionHead'><span class='titlemark'>1 </span> <a id='sec:intro'></a>Section heading</h3>
...
<p class='indent'> This is a test to link to Section this text is for searching in HTML Karen heading
<a href='#sec:intro'>1<!-- tex4ht:ref: sec:intro --></a>. </p>
结束语
我看得出您可能使用了自定义类,因为您的 HTML 代码片段生成的是<p>
元素而不是<h3>
部分。您可能希望为您的类创建一个配置文件,以获得结构更好的 HTML 文件。
当您为章节生成正确的标签时,当前版本的制作4小时(的现代替代品htlatex
)产生以下代码:
<h3 id='section-heading' class='sectionHead'><span class='titlemark'>1 </span> <a id='x1-10001'></a>Section heading</h3>
...
<p class='indent'> This is a test to link to Section this text is for searching in HTML Karen heading
<a href='#section-heading'>1<!-- tex4ht:ref: sec:intro --></a>. </p>
因此,它会根据章节标题生成稳定的超链接目标。“章节标题”变为<h3 id="section-title">
。对于您的用例来说,这可能比使用\label
名称更好。
支持上述功能的版本make4ht
尚未在 CTAN 上,因此您可能确实想使用\label
我建议的方法之一来使用目前生成的所有超链接的标签。
答案2
你给我设定了相当大的挑战!我也觉得 Michal 的方法很有趣,但这个方法不需要 Lua 的额外步骤,只需要htlatex
你一直在使用的。
在你的序言中,添加:
\makeatletter
% We are going to modify \section to include a div with the label as id.
\let\orig@section\section
\renewcommand\section[1]{%
\def\@sectiontitle{#1}%
\futurelet\@aftersectioncommand\resolvesection
}
% In case you disable the code, don't have the aux throw errors.
\def\writeSetHrefFallback{
\write\@auxout{\protect\ifx\protect\sethrefaccessible\protect\undefined
\protect\typeout{HTMLLabels: Fallback was used!}
\protect\def\protect\sethrefaccessible \string##1{}
\protect\fi}%
}
% This is triggered when on previous compilation, a div with the label as id of #1 had been placed.
\def\hrefaccessible{}
\def\sethrefaccessible#1{
\expandafter\global\expandafter\let\csname hrefaccessible@#1\endcsname\hrefaccessible
}
% Check if there is a \label following the \section
\def\resolvesection{%
\let\@storedlabel\relax
\ifx\@aftersectioncommand\label
\typeout{HTMLLabels: Section followed by label}%
\let\orig@label\label
% Consume the label
\def\label##1{%
\def\@storedlabel{##1}%
\def\curhypid{##1}%
\write\@auxout{\protect\sethrefaccessible{##1}}%
% We have acquired the necessary information, now relay everything back to the normal commands
\let\label\orig@label
\expandafter\orig@section\expandafter{\@sectiontitle}%
\label{##1}%
}%
\else
% Fallback: \label not following \section directly
\let\curhypid\relax
\typeout{HTMLLabels: Section not followed by label}%
%
\expandafter\orig@section\expandafter{\@sectiontitle}%
\fi
}
% A variation of ref which can use labels as href to ids
\let\orig@ref\ref
\newcommand\htmllabelref[1]{%
\expandafter\ifx\csname hrefaccessible@#1\endcsname\hrefaccessible
% Upon previous compilation, the label had been assigned as an id to a div. We disable the normal link of \ref, and put one in ourselves.
\begingroup
\def\rEfLiNK##1##2{##2}%
\Link{#1}{}%
\orig@ref{#1}%
\EndLink
\endgroup
\else
\orig@ref{#1}%
\fi
}
\makeatother
并在文档正文中
\makeatletter
\writeSetHrefFallback
\LinkCommand\HeaderTarget{div,href,id}
\def\curhypid{sec:unknown}
\Configure{section}
{}{}
{%
\HCode{<h3>}
\ifx\curhypid\relax
\PackageWarning{HTMLLabels}{Section misses label!}
\else
\HeaderTarget{}{\curhypid}\EndHeaderTarget
\fi
\TitleMark\space}
{\HCode{</h3>}}
\ConfigureMark{section}{\thesection}
%% BEGIN This regions sets all \ref to act as \htmllabelref
\def\ref{\htmllabelref}
\let\orig@T@ref\T@ref
\def\alt@T@ref#1{%
\let\T@ref\orig@T@ref
\htmllabelref{#1}%
\let\T@ref\alt@T@ref
}
\let\T@ref\alt@T@ref
%% END
\makeatother
此设置目前仅适用于\section
-commands。不幸的是,我现在没有时间研究如何全面一致地执行此操作。此外,此方法依赖于\label
紧随其后的\section
(这是您的 MWE 中的情况),因为在放置时\section
,我们需要知道id
要附加在那里的。如果不是\label
紧随其后,那么整个代码就会安全地恢复使用自动生成的 ID。
我使事情正常运行的完整代码:https://pastebin.com/y1rD5yPE