2

I have a two column html output, in one column the text, in the other the TOC to navigate. However, my complete TOC has 100 entries and is thus confusing. How can I get the minitoc for each part only or better see a list of all parts and only for the currently viewed part the detailed TOC. Below is my Code.

So, while in part 1 the left side TOC should show P1, C1, C2, S1, S2, P2, P3. In part 2 it should show P1, P2, C12, C22, S12, S22, P3.

\documentclass[12pt,a4paper,notitlepage,twoside]{book}%

\usepackage{minitoc}

\begin{document}
\addcontentsline{toc}{part}{Start} 
\dominitoc
\doparttoc

START

\part{P1}

\chapter{C1}
\chapter{C2}
\section{S1}
\section{S2}
\part{P2}
\chapter{C12}
\chapter{C22}
\section{S12}
\section{S22}
\part{P3}

\end{document}

and the cfg file:

\Preamble{xhtml,mathml}
\Configure{VERSION}{}
\Configure{DOCTYPE}{\HCode{<!DOCTYPE html>\Hnewline}}
\Configure{HTML}{\HCode{<html>\Hnewline}}{\HCode{\Hnewline</html>}}
\Configure{@HEAD}{\HCode{
   <link type="text/css" rel="stylesheet" href="protex/style.css" />\Hnewline %Eigenes Stylesheet für notwendige Anpassungen.
}}

%Einfügen der Navigationssidebar/des Inhaltsverzeichnisses auf jeder Seite
\Configure{@BODY}{\HCode{<div class="mainnavigation"><a href="http://dynamische-vwl.de/"><img src="protex/images/logo.png" /></a>}\TableOfContents\HCode{</div>}}
    % Der gesamte Text wird in das Blockelement "textkoerper" gepackt, um ihn sauber vom Inhaltsverzeichnis trennen zu können.
    \Configure{@BODY}{\HCode{<div class="textkoerper">}}

\CutAt{part,likepart,appendix}
\CutAt{chapter,appendix,part,likepart}
% \Configure{endchapter}{chapter,section}
\CutAt{section,likesection}
\CutAt{subsection,likesubsection}

\Configure{paragraph}{}{}{\HCode{<div class="paragraphHead">}}{\HCode{</div>}}

\TocAt{chapter,section}
% \def\Tocchapter{\TableOfContents[chapter]}
\TocAt{section,subsection}

 \begin{document}
 \EndPreamble


and the css
body {
  background: #f1f1f1 url("protex/images/bg.png") repeat;
  font: normal 12px/21px Arial, Helvetica, sans-serif;
  color: #404040;
}
/*div.partTOCS{
  width: 25%;
  float:left;
  margin-left:-25%;
}
div.chapterTOCS{
  width: 25%;
  float:left;
  margin-left:-25%;
}
div.sectionTOCS{
  width: 25%;
  float:left;
  margin-left:-25%;
}*/
div.mainnavigation{
  width: 20%;
  float:left;
  margin-left:5%;
  background:  #333;
  color: #ececec;
  padding-left:1%;
  padding-right:1%;
  padding-top:2%;
  padding-bottom:2%;
  margin-bottom:2%;
/*   margin-right:5%; */
}

div.mainnavigation a{
  color: #ececec;
}

div.textkoerper{
  margin-left:27%;
  width: 66%;
  background: #f9f9f9;
  padding-left:2%;
  padding-top:2%;
  padding-right:2%;
  border-bottom: 1px solid #e7e5e5;
  border-top-right-radius: 4px;
}

div#fusszeile{
/*   float:left; */
}
2

This task can be solved with post-processing the HTML output in the easiest way. make4ht, build system for tex4ht support modifying of the output HTML files using external utilities, or using Lua functions.

Development version of LuaXML, which isn't on CTAN yet, contains simple DOM like library, which can be used for simple HTML manipulations. I will post the complete build file first and some comments later. Name the build file mybuild.mk4:

local domobject = require "luaxml-domobject"

local filter = require "make4ht-filter"

-- return toc element type and it's id
local function get_id(el)
  local name =  el:get_attribute "class"
  local a = el:query_selector "a" or {}
  local first = a[1]
  local href = first:get_attribute "href"
  local id = href:match("#(.+)$")
  return name, id
end

local function remove_sections(part_elements, currentpart)
  -- we need to remove toc entries from the previous part if the 
  -- current document isn't part of it
  if currentpart == false then
    for _, part in ipairs(part_elements) do
      part:remove_node()
    end
  end
end



local process = filter{ function(s)
  local dom = domobject.parse(s)
  -- search sectioning elements
  local titles = dom:query_selector(".partHead a, .chapterHead a, .sectionHead a")
  local section_ids = {}
  for _, x in ipairs(titles) do
    -- get their id attributes and save them in a table
    section_ids[#section_ids+1] = x:get_attribute("id")
  end
  -- we need to retrieve the first table of contents
  local toctables = dom:query_selector(".tableofcontents") or {}
  -- process only when we got a TOC
  if #toctables > 0 then
    local tableofcontents = toctables[1]
    -- all toc entries are in span elements
    local toc = tableofcontents:query_selector("span")
    local currentpart = false
    local part_elements = {}
    for _, el in ipairs(toc) do
      -- get sectioning level and id of the current TOC entry
      local name, id = get_id(el)
      -- change span to div
      el._name = "div"
      if name == "partToc" then
        remove_sections(part_elements,currentpart)
        -- resert toc list
        currentpart = false
        part_elements = {}
      else
        -- add child elements of part to table
        part_elements[#part_elements+1] = el
      end
      for _, sectid in ipairs(section_ids) do
        -- detect if the current TOC entry match some sectioning element in the current document
        if id == sectid then
          currentpart = true
          print("match", id)
        end
      end
    end
    -- remove sections from the last part
    remove_sections(part_elements,currentpart)
    -- remove unneeded br elements
    local br = tableofcontents:query_selector("br")
    for _, el in ipairs(br) do el:remove_node() end
    -- remove unneded whitespace
    for _, el in ipairs(tableofcontents:get_children()) do
      if el:is_text() then el:remove_node() end
    end
  end
  return dom:serialize()
end }

Make:match("html$", process)

Compile your document using

make4ht -c configname.cfg -e mybuild.mk4 filename.tex

This produces the following result:

enter image description here

Now follows some explanation:

The DOM library is named in "luaxml-domobject". The most important function is domobject:query_selector it search the DOM for CSS query and returns table with all matched elements. So if you want to search for all chapters commands, which may have chapterHead class, then you can use

 domobject:query_selector(".chapterHead") 

and it will select all chapters inside the current page. We use more advanced selector to get all links to sectioning commands in the page, using

local titles = dom:query_selector(".partHead a, .chapterHead a, .sectionHead a")

the links are stored in id attribute of a element which is child of sectioning elements. We use these IDs to check whether TOC elements links to the current page or not.

The process is following:

We loop over all TOC elements, check whether it links to the current page or to some different part and set boolean variable if it links to the current page. When the current element is part, we check whether the boolean variable is false, so chapters and sections in the previous part link to different part. In this case we remove all links to sections and chapters. We then do some more cleanup and the result is TOC containing links only to the current part sections and to other parts.

As last step, we can save it back to text form using domobject:serialize. We use make4ht-filter library to load the HTML files, call our processing function and to save the result back to the HTML file. The process is called on all produced HTML files using

Make:match("html$", process)
  • Sorry for the late answer. I tried just c&p your answer and got the following error message: [string "local domobject = require "luaxml-domobject"..."]:1: module 'luaxml-domobject' not found: no field package.preload['luaxml-domobject'] [kpse lua searcher] file not found: 'luaxml-domobject' [kpse C searcher] file not found: 'luaxml-domobject' Can you see from that what I did wrong? I'd really appreciate, if you would have an idea. Best, Christian – ChristianB Feb 4 at 0:42
  • @ChristianB what TeX distribution do you use? It seems that LuaXML package is missing or broken on your system. What is the output of the following command: kpsewhich luaxml-mod-handler.lua? – michal.h21 Feb 4 at 10:34
  • Thanks for the hint. I installed the package. I use miktex. However, it still doesn't work. Sent you the code by mail. Help really appreciated. – ChristianB Feb 4 at 12:02

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.