从复杂的 latex 文档(如论文)生成 html 网页的最佳工作流程或工具

从复杂的 latex 文档(如论文)生成 html 网页的最佳工作流程或工具

我非常有兴趣将我的论文发布在一个网站上,使用 HTML + CSS(完成后),并辅以工具来注释它,例如哲学网倡议(见这里, 和这里)。

我知道万能转换器潘多克或 latex2html,但我感兴趣的是知道是否存在其他工具,或者是否有些用户已经创建了批处理工作流来自动进行这种转换。

也许它可以成为一个社区维基问题?

更新列表(2015 年 4 月 16 日):

MWE 创作:

我建议第一个链接在复杂的 MWE 上进行协作以测试这些工具,它们包含您想要的所有复杂元素:

链接到 sharelatex 上的公共 MWE

使用一些 js 来转换并最终美化的东西:

  • 数学
  • 复杂侧边字幕
  • 参考书目
  • 公共注释

出色转换的示例:

答案1

我将展示一个解决方案tex4ht。我使用了您的示例文本,并添加了一些来自互联网的数学示例。您可以在我的Github 页面. 所有代码也托管在Github

您有四个愿望,其中一些可以使用外部 Javascript 工具解决,对于其他愿望,我们必须创建自定义 JS 脚本。

tex4ht可以使用.cfg文件进行配置。此文件具有特殊结构:

...
\Preamble{xhtml,list of options}
...
\begin{document}
...
\EndPreamble

我们可以在命令之前 require 一些包\Preamble,这些包可能用于一些辅助包。在我们的示例中,我们可能需要两个包:

  • 一个修复了 Memoir 下的一些问题tex4ht
  • 其他一些辅助宏

您需要最近更新 TeX Live 以获取对tex4htMemoir 支持的最新错误修复,在这种情况下,您只需要使用目录中的双重参考书目条目修复此问题。

可以通过以下方法修复mem4hack.sty

\renewcommand\@memb@bchap{\chapter*{\bibname}\bibmark\prebibhook}

另一个支持包是tools.sty

\newcommand\AddFile[1]{\special{t4ht+@File: #1}}%

\newcommand\AddCss[1]{%
  \AddFile{#1}%
  \Configure{@HEAD}{\HCode{<link rel="stylesheet" type="text/css" href="#1" />}}
}

\newcommand\AddJs[1]{%
  \AddFile{#1}%
\Configure{@HEAD}{\HCode{\Hnewline<script type="text/javascript" src="#1"></script>}}
}

这简化了项目中文件CSS的包含。JS

关于使用的库,我们可以使用它mathjax来提供数学支持和 hypothes.is用于注释。不幸的是,这不适用于本地页面,您必须使用网络服务器(但您可以将其安装在本地计算机上,不需要实际的服务器)。

数学示例:

在此处输入图片描述

注释示例:

在此处输入图片描述 在此处输入图片描述

对于侧边栏,您可以为每一章制作一个独立文件,并为章节和子章节提供本地目录。因此,您可以制作包含此目录以及上一章和下一章链接的侧边栏。

代码在这里js/sidebar.js

document.addEventListener("DOMContentLoaded", function() {
    // Code
    // select local TOC
    var menu = q(".chapterTOCS")[0];
    var menuopened = "^^^";
    var m = createEl("a","menu",menuopened);
    var toolbar = createEl("div","toolbar");
    var sidebar = createEl("div","sidebar","");
    var crosslinks = q(".crosslinks")[0];
    var setText = function(node,a){
      var text = document.createTextNode(a);
      node.removeChild(node.childNodes[0]);
      node.appendChild(text);
    }
    var switchMenu = function(){
      // switch menu state
      menu.className = hiddenswitch ? "chapterTOCS red" : "chapterTOCS hiddentoc";
      var text = hiddenswitch ? menuopened:"TOC"  ;
      // set menu class to changed state
      setText(m, text);

      hiddenswitch = !hiddenswitch;
    }
    // pass reference to new container and crosslinks
    var transfromCrosslinks = function(newcrosslinks,el){
      // find all crosslinks 
      var links = el.querySelectorAll("a");
      var newcrs = {}
     // make table with link text as name
     for(i=0;i!=links.length;i++){
          var text = links[i].firstChild.nodeValue;
          newcrs[text] = links[i];
      }
      // select next, prev and up nodes and replace text with unicode arrows
      // is a node doesn't exist, create span with blanklink class
      var next = newcrs["next"] || createEl("span","blanklink",">")
      setText(next,"⇨");
      var prev = newcrs["prev"]|| createEl("span","blanklink",">")
      setText(prev,"⇦");
      setText(newcrs["up"],"⇧");
      // add crosslinks to a toolbar
      newcrosslinks.appendChild(prev);
      newcrosslinks.appendChild(newcrs["up"]);
      newcrosslinks.appendChild(next);
      crosslinks.remove();
      return newcrosslinks;
    }
    // add elements to the sidebar depending on existence of a local TOC and 
    // crosslinks
    if(crosslinks){
      transfromCrosslinks(toolbar,crosslinks);
      // add sidebat only if it doesn't exist already
      if(!menu) sidebar.appendChild(toolbar);
      //m.appendChild(newcrosslinks);
    }
    if(menu) { 
      toolbar.appendChild(m);
      sidebar.appendChild(toolbar);
      sidebar.appendChild(menu);
    }
    q("body")[0].appendChild(sidebar);
    var hiddenswitch = false
    m.on("click",switchMenu,false);
    //menu.insertBefore(m,menu.childNodes[0]);

 }, false);

它使用标准 Javascript DOM 函数,仅js/fw.js使用小型库:

// basic DOM functions
// based on http://blog.adtile.me/2014/01/16/a-dive-into-plain-javascript/
var q = document.querySelectorAll.bind(document);
Element.prototype.on = Element.prototype.addEventListener;
var createEl = function(el, cls, text){
  var x = document.createElement(el);
  x.setAttribute("class",cls);
  if(text) {
    var t = document.createTextNode(text);
    x.appendChild(t);
  }
  return x;
}

在此处输入图片描述

TOC单击文本即可隐藏^^^

在此处输入图片描述

对于参考书目,我们可以使用 加载参考书目页面AJAX,当您将光标指向引文时,它会在窗口中显示引文。单击文档中的任意位置即可关闭窗口。

文件js/bib.js

var bibdoc = null;

var isBibbox = function(){
  return q("#bibbox").length>0;
}

var makeBibTooltip = function(bib,id,el){
  if(!isBibbox()){
    var xxx = bib.querySelector(id).parentNode.cloneNode(true);
    var parentpos = el.getBoundingClientRect();  
    var tip = document.createElement("div");
    tip.setAttribute("id", "bibbox")
    tip.style.position = "fixed";
    tip.style.top = parentpos.bottom+ 10+"px";
    tip.style.left = parentpos.left+ 10 +"px" ;
    tip.appendChild(xxx);
    document.body.appendChild(tip);
  }
}
var getBibDoc = function(url,id,el){
  if(!bibdoc){
    var ajax = new XMLHttpRequest();
    console.log("Load ajax"+url)
    bibdoc = ajax.open("GET",url,true);
    ajax.send();
    ajax.onreadystatechange = function(){
      if(ajax.readyState == 4 && ajax.status==200 && !bibdoc){
        var res = ajax.responseText;
        bibdoc = createEl("div","bib");
        bibdoc.innerHTML = res;
        makeBibTooltip(bibdoc,id,el);
      }
    }
  }else{
    makeBibTooltip(bibdoc,id,el);
  }
}

document.addEventListener("DOMContentLoaded", function() {
  var bibs = q("span.cite");
  for(i=0;i<bibs.length;i++){
    bibs[i].on("mouseover", function(e){
      var el = e.currentTarget;
      var link = el.querySelector("a");
      var hash = link.hash;
      var href = link.getAttribute("href");
      getBibDoc(href,hash,el);
      //var target = bib.querySelector("body");
      //console.log("nazdar "+ target);
    });
  }
});

document.addEventListener("click",function(){
  if(isBibbox()){
    var bibbox = q("#bibbox");
    for(i=0;i<bibbox.length;i++){
      bibbox[i].remove();
    }
  }
});

在此处输入图片描述

我们还可以制作更好的排版,我真的很喜欢Viljami Salminen 的响应式 CSS 样板. 使用css/scale.css文件。

现在我们可以把它们放在一起,制作文件myconfig.cfg

\RequirePackage{mem4hack}
\RequirePackage{tools}
\Preamble{xhtml,2,mathml}
 \Configure{@HEAD}{\HCode{\Hnewline<script type="text/javascript"\Hnewline
 src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=MML_HTMLorMML"\Hnewline
 ></script>\Hnewline}}
\Configure{@HEAD}{\HCode{\Hnewline<script async defer src="http://hypothes.is/embed.js"></script>}}
\AddCss{css/scale.css}
\AddJs{js/fw.js}
\AddJs{js/sidebar.js}
\AddJs{js/bib.js}

% fix sublist indentation

\Css{li li{margin-left:2em;}}
\Css{dd dl{margin-left:2em;}}

% we can use helper macros to use variables in the CSS
\def\numcalc#1{\the\numexpr #1\relax}
\def\sidebarwidth{18}
% sidebar is on a fixed position. you should play with this
\Css{.sidebar{position:fixed;width:\sidebarwidth em;top:3em;left:100\%;margin-left:-\numcalc{\sidebarwidth+2}em;}}
% fix local TOC formating 
\Css{.sidebar .sectionToc,.sidebar .subsectionToc{display:block;margin-top:-1em;margin-bottom:0px;}}
\Css{.sidebar .chapterTOCS br{display:none;}}
% we can turn off the local TOC 
\Css{.hiddentoc{display:none;}}
% TOC switch formatting
\Css{.menu{margin-left:1em;}}
\Css{.menu red{font-size:0,7em;vertical-align:sub;}}
% toolbar displays links to previous and next chapters and TOC switcher
\Css{.toolbar{font-size:1.3em;background-color:\#fed;}}
% tooltip which displays bibliographic record when you point 
% a cursor on a citation
\Css{\#bibbox{border:1px solid black;background-color:\#fed;width:25em;}}
% make standalone page for each chapter. make local TOC for contained sections
% and subsections
\TocAt{chapter,section,subsection}
\begin{document}
% we can delete normal TOC, it is created automatically by tex4ht and it 
% would be duplicated
\makeatletter
\renewcommand\tableofcontents{\@ifstar{}{}}
\makeatother
\EndPreamble

在命令中,指定了\Preamble选项。请求输出,将文档分成每个独立的网页(会将其分成每个部分、每个节……),请求将数学转换为。tex4htxhtmlxhtml2\chapter13mathmlmathml

配置应该在\Preamble命令之后。

内部js和文件分别使用命令CSS包含\AddJs。并使用指向外部页面的链接包含,使用以下命令进行配置\AddCssmathjaxhypothes.is

\Configure{@HEAD}{...}

此配置将内容添加到 html<head>元素。

您可以CSS使用命令添加样式\Css。所包含的样式非常基础,您可能想要(并且确实应该)修改它们以获得更好的外观,只关注功能,而不是美观)

现在你可以使用以下方式编译你的文件

htlatex thesis myconfig

或者更好的是,使用制作4小时这是 的替代构建系统tex4ht。此构建文件将把所有使用的文件复制到/var/www/html/reyman/目录中,因此您可以在浏览器中打开此地址:本地主机/reyman/thesis.html 一切都应该正常工作。如果您有类 Unix 系统、Apache Web 服务器和对该目录的写入权限。文件thesis.mk4

local mkutils = require "mkutils"
local outdir = "/var/www/html/reyman/"
if mode == "draft" then
  Make:htlatex {}
else
  Make:add("bibtex", "bibtex ${input}")
  Make:htlatex {}
  Make:bibtex {}
  Make:htlatex {}
  Make:htlatex {}
end
Make:match(".*$", function(file, par)
  mkutils.copy(file, outdir .. file)
  return false, "Copy html to destination "..outdir
end)

使用以下方式编译

make4ht -u -c myconfig thesis

为了加速编译,你可以使用

make4ht -um draft -c myconfig thesis

它将仅使用 LaTeX 编译文档一次并且将跳过bibtex

您可以在我的Github 页面

相关内容