texlive[66130] trunk: make4ht (24feb23)

commits+karl at tug.org commits+karl at tug.org
Fri Feb 24 22:33:48 CET 2023


Revision: 66130
          http://tug.org/svn/texlive?view=revision&revision=66130
Author:   karl
Date:     2023-02-24 22:33:48 +0100 (Fri, 24 Feb 2023)
Log Message:
-----------
make4ht (24feb23)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/make4ht/make4ht
    trunk/Master/texmf-dist/doc/support/make4ht/README
    trunk/Master/texmf-dist/doc/support/make4ht/changelog.tex
    trunk/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf
    trunk/Master/texmf-dist/doc/support/make4ht/readme.tex
    trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-joincharacters.lua
    trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-mathmlfixes.lua
    trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua
    trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua
    trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-tidy.lua
    trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-jats.lua
    trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua
    trunk/Master/texmf-dist/scripts/make4ht/make4ht
    trunk/Master/texmf-dist/scripts/make4ht/make4ht-indexing.lua
    trunk/Master/texmf-dist/scripts/make4ht/mkutils.lua

Added Paths:
-----------
    trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-inlinecss.lua
    trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-inlinecss.lua

Modified: trunk/Build/source/texk/texlive/linked_scripts/make4ht/make4ht
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/make4ht/make4ht	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Build/source/texk/texlive/linked_scripts/make4ht/make4ht	2023-02-24 21:33:48 UTC (rev 66130)
@@ -29,7 +29,7 @@
 
 -- set version number. the template should be replaced by the
 -- actual version number by the build script
-local version = "v0.3l"
+local version = "v0.3m"
 mkparams.version_number = version
 
 local args = mkparams.get_args()
@@ -120,7 +120,13 @@
 
 make:match(".*",function(filename,par)
 	local outdir =  '' --par["outdir"] and par["outdir"] .."/" or ''
-	if par['outdir'] ~= "" then outdir = par['outdir'] .. '/' end
+	if par['outdir'] ~= "" then 
+    outdir = par['outdir'] .. '/' 
+  else
+    -- don't run unnecessary copy without output dir
+    log:info("No output directory")
+    return true
+  end
 	log:info("outdir: "..outdir)
 	local outfilename = outdir .. filename
 	mkutils.copy(filename,outfilename)

Modified: trunk/Master/texmf-dist/doc/support/make4ht/README
===================================================================
--- trunk/Master/texmf-dist/doc/support/make4ht/README	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/doc/support/make4ht/README	2023-02-24 21:33:48 UTC (rev 66130)
@@ -278,9 +278,13 @@
 :    efficient generation of SVG pictures using Dvisvgm. It can utilize
 multiple processor cores and generates only changed images.
 
+inlinecss
+
+:    load the `inlinecss` DOM filter.
+
 join\_colors
 
-:    load the `joincolors` domfilter for all HTML files.
+:    load the `joincolors` DOM filter for all HTML files.
 
 latexmk\_build
 
@@ -646,6 +650,11 @@
 
 :  replace the colon (`:`) character in internal links and `id` attributes. They cause validation issues.
 
+inlinecss
+
+:  remove CSS rules that target elements with unique attributes, such as color boxes, table rules, or inline math pictures,
+   and insert their properties as a inline `style` attribute in the HTML document.
+
 joincharacters
 
 :  join consecutive `<span>` or `<mn>` elements. This DOM filter supersedes the `cleanspan` filter.
@@ -655,7 +664,8 @@
 :  many `<span>` elements with unique `id` attributes are created when \LaTeX\ colors are being used in the document.
    A CSS rule is added for each of these elements, which may result in
    substantial growth of the CSS file. This filter replaces these rules with a
-   common one for elements with the same color value.
+   common one for elements with the same color value. See also the `inlinecss` DOM filter and extension, which provides an
+   alternative using inline styles.
 
 odtfonts
 

Modified: trunk/Master/texmf-dist/doc/support/make4ht/changelog.tex
===================================================================
--- trunk/Master/texmf-dist/doc/support/make4ht/changelog.tex	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/doc/support/make4ht/changelog.tex	2023-02-24 21:33:48 UTC (rev 66130)
@@ -3,11 +3,186 @@
 
 \begin{itemize}
 \item
-  2022/02/22
+  2023/02/24
 
   \begin{itemize}
   \tightlist
   \item
+    version \texttt{0.3k} released.
+  \end{itemize}
+\item
+  2023/01/09
+
+  \begin{itemize}
+  \tightlist
+  \item
+    fixed detection of image file names in \texttt{mkutils.parse\_lg()}
+  \end{itemize}
+\item
+  2022/11/25
+
+  \begin{itemize}
+  \tightlist
+  \item
+    reverted change of index page numbers, it was buggy
+  \item
+    test if the \texttt{.idx} file exists.
+  \end{itemize}
+\item
+  2022/11/24
+
+  \begin{itemize}
+  \tightlist
+  \item
+    \texttt{make4ht-indexing}: fixed handling of numbers in index
+    entries text.
+  \end{itemize}
+\item
+  2022/11/01
+
+  \begin{itemize}
+  \tightlist
+  \item
+    remove empty last rows in MathML tables.
+  \end{itemize}
+\item
+  2022/10/21
+
+  \begin{itemize}
+  \tightlist
+  \item
+    added the \texttt{inlinecss} DOM filter and extension with the same
+    name.
+  \end{itemize}
+\item
+  2022/09/29
+
+  \begin{itemize}
+  \tightlist
+  \item
+    the \texttt{join\_characters} DOM filter now shouldn't produce extra
+    \texttt{\textless{}span\textgreater{}} elements after white space.
+  \end{itemize}
+\item
+  2022/09/16
+
+  \begin{itemize}
+  \tightlist
+  \item
+    use the \texttt{no\^{}} option to compile the \texttt{make4ht} HTML
+    docs, to prevent clash with the Doc package.
+  \end{itemize}
+\item
+  2022/07/22
+
+  \begin{itemize}
+  \tightlist
+  \item
+    \texttt{mathmlfixes} DOM filter:
+
+    \begin{itemize}
+    \tightlist
+    \item
+      don't change \texttt{\textless{}mo\textgreater{}} to
+      \texttt{\textless{}mtext\textgreater{}} if the element contain the
+      \texttt{stretchy} attribute.
+    \item
+      add \texttt{\textless{}mtext\textgreater{}} to
+      \texttt{\textless{}mstyle\textgreater{}} if it contains only plain
+      text
+    \end{itemize}
+  \end{itemize}
+\item
+  2022/07/08
+
+  \begin{itemize}
+  \tightlist
+  \item
+    configure elements used in \texttt{join\_characters} DOM filter.
+  \item
+    added support for the \texttt{mml:} prefix in \texttt{mathml\_fixes}
+    DOM filter.
+  \end{itemize}
+\item
+  2022/06/28
+
+  \begin{itemize}
+  \tightlist
+  \item
+    handle \texttt{\textbackslash{}maketitle} in JATS.
+  \end{itemize}
+\item
+  2022/06/24
+
+  \begin{itemize}
+  \tightlist
+  \item
+    handle internal and external links in the JATS output.
+  \item
+    better detection of empty paragraphs.
+  \end{itemize}
+\item
+  2022/06/16
+
+  \begin{itemize}
+  \tightlist
+  \item
+    use DOM filters to fix JATS output.
+  \end{itemize}
+\item
+  2022/04/22
+
+  \begin{itemize}
+  \tightlist
+  \item
+    use more explicit options for \texttt{latexmk}.
+  \end{itemize}
+\item
+  2022/04/19
+
+  \begin{itemize}
+  \tightlist
+  \item
+    remove all \texttt{htlatex} calls from the build sequence when the
+    \texttt{latexmk\_build} extension is used.
+  \item
+    fixed other issues that caused spurious executions of
+    \texttt{latexmk}.
+  \end{itemize}
+\item
+  2022/04/01
+
+  \begin{itemize}
+  \tightlist
+  \item
+    don't copy files to the output dir if it wasn't requested
+  \item
+    fixed copying of the ODT file to the output dir.
+  \end{itemize}
+\item
+  2022/03/29
+
+  \begin{itemize}
+  \tightlist
+  \item
+    check if tidy return non-empty string in the \texttt{tidy}
+    extension.
+  \end{itemize}
+\item
+  2022/03/24
+
+  \begin{itemize}
+  \tightlist
+  \item
+    don't use totally random names in the \texttt{preprocess\_input}
+    extension, in order to support images correctly.
+  \end{itemize}
+\item
+  2022/03/22
+
+  \begin{itemize}
+  \tightlist
+  \item
     version \texttt{0.3l} released.
   \item
     fixed issues with filenames on Windows.

Modified: trunk/Master/texmf-dist/doc/support/make4ht/make4ht-doc.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/make4ht/readme.tex
===================================================================
--- trunk/Master/texmf-dist/doc/support/make4ht/readme.tex	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/doc/support/make4ht/readme.tex	2023-02-24 21:33:48 UTC (rev 66130)
@@ -358,8 +358,10 @@
 \item[dvisvgm\_hashes]
 efficient generation of SVG pictures using Dvisvgm. It can utilize
 multiple processor cores and generates only changed images.
+\item[inlinecss]
+load the \texttt{inlinecss} DOM filter.
 \item[join\_colors]
-load the \texttt{joincolors} domfilter for all HTML files.
+load the \texttt{joincolors} DOM filter for all HTML files.
 \item[latexmk\_build]
 use \href{https://ctan.org/pkg/latexmk?lang=en}{Latexmk} for the
 \LaTeX~compilation.
@@ -724,6 +726,10 @@
 \item[idcolons]
 replace the colon (\texttt{:}) character in internal links and
 \texttt{id} attributes. They cause validation issues.
+\item[inlinecss]
+remove CSS rules that target elements with unique attributes, such as
+color boxes, table rules, or inline math pictures, and insert their
+properties as a inline \texttt{style} attribute in the HTML document.
 \item[joincharacters]
 join consecutive \texttt{\textless{}span\textgreater{}} or
 \texttt{\textless{}mn\textgreater{}} elements. This DOM filter
@@ -733,7 +739,9 @@
 \texttt{id} attributes are created when \LaTeX~colors are being used in
 the document. A CSS rule is added for each of these elements, which may
 result in substantial growth of the CSS file. This filter replaces these
-rules with a common one for elements with the same color value.
+rules with a common one for elements with the same color value. See also
+the \texttt{inlinecss} DOM filter and extension, which provides an
+alternative using inline styles.
 \item[odtfonts]
 fix styles for fonts that were wrongly converted by \texttt{Xtpipes} in
 the ODT format.

Added: trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-inlinecss.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-inlinecss.lua	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-inlinecss.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -0,0 +1,83 @@
+local cssquery  = require "luaxml-cssquery"
+
+local log = logging.new("inlinecss")
+
+local cssrules = {}
+local cssobj   = cssquery()
+
+local function parse_rule(line)
+  -- parse CSS selector and attributes
+  -- they are always on one line in the CSS file produced by TeX4ht
+  local selector, values = line:match("%s*(.-)%s*(%b{})")
+  if values then
+    values = values:sub(2,-2)
+  end
+  return selector, values
+end
+
+local function join_values(old, new)
+  -- correctly joins two attribute lists, depending on the ending
+  local separator = ";"
+  if not old then return new end
+  -- if old already ends with ;, then don't use semicolon as a separator
+  if old:match(";%s*$") then separator = "" end
+  return old .. separator .. new
+end
+
+local function parse_css(filename)
+  local css_file = io.open(filename, "r")
+  if not css_file then return nil, "cannot load css file: " .. (filename or "") end
+  local newlines = {}
+  for line in css_file:lines() do
+    -- match lines that contain # or =, as these can be id or attribute selectors
+    if line:match("[%#%=].-{") then
+      -- update attributes for the current selector
+      local selector, value = parse_rule(line)
+      local oldvalue = cssrules[selector] 
+      cssrules[selector] = join_values(oldvalue, value)
+    else
+      newlines[#newlines+1] = line
+    end
+  end
+  -- we need to add css rules
+  for selector, value in pairs(cssrules) do
+    cssobj:add_selector(selector, function(dom) end, {value=value})
+  end
+  css_file:close()
+  -- write new version of the CSS file, without rules for ids and attributes
+  local css_file = io.open(filename, "w")
+  css_file:write(table.concat(newlines, "\n"))
+  css_file:close()
+  return true
+end
+
+local processed = false
+
+-- process the HTML file and insert inline CSS for id and attribute selectors
+return function(dom, par)
+  if not processed then 
+    -- process the CSS file before everything else, but only once
+    processed = true
+    local css_file = par.input .. ".css"
+    local status, msg = parse_css(css_file)
+    if not status then log:warning(msg) end
+  end
+  -- loop over all elements in the current page
+  dom:traverse_elements(function(curr)
+    -- use CSS object to match if the current element
+    -- is matched by id attribute selector
+    local matched = cssobj:match_querylist(curr)
+    if #matched > 0 then
+      -- join possible already existing style attribute with values from the CSS file
+      local values = curr:get_attribute("style")
+      -- join values of all matched rules
+      for _,rule in ipairs(matched) do
+        values = join_values(values, rule.params.value)
+      end
+      curr:set_attribute("style", values)
+    end
+
+  end)
+  return dom
+end
+


Property changes on: trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-inlinecss.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-joincharacters.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-joincharacters.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-joincharacters.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -107,7 +107,7 @@
           -- we must create a new node
           el:add_child_node(el:create_text_node(s))
           next_el:remove_node()
-          real_next = nil
+          -- real_next = nil
         else
           real_next = nil
         end

Modified: trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-mathmlfixes.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-mathmlfixes.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/domfilters/make4ht-mathmlfixes.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -5,8 +5,43 @@
 local token_elements = {}
 for _, tok in ipairs(token) do token_elements[tok] = true end
 
+-- helper functions to support MathML elements with prefixes (<mml:mi> etc).
+--
+local function get_element_name(el)
+  -- return element name and xmlns prefix
+  local name = el:get_element_name()
+  if name:match(":") then
+    local prefix, real_name =  name:match("([^%:]+):?(.+)")
+    return real_name, prefix
+  else
+    return name
+  end
+end
+
+local function get_attribute(el, attr_name)
+  -- attributes can have the prefix, but sometimes they don't have it
+  -- so we need to catch both cases
+  local _, prefix = get_element_name(el)
+  prefix = prefix or ""
+  return el:get_attribute(attr_name) or el:get_attribute(prefix .. ":" .. attr_name)
+end
+
+local function get_new_element_name(name, prefix)
+  return prefix and prefix .. ":" .. name or name
+end
+
+local function update_element_name(el, name, prefix)
+  local newname = get_new_element_name(name, prefix)
+  el._name = newname
+end
+
+local function create_element(el, name, prefix)
+  return el:create_element(newname)
+end
+
 local function is_token_element(el)
-  return token_elements[el:get_element_name()]
+  local name, prefix = get_element_name(el)
+  return token_elements[name], prefix
 end
 
 local function fix_token_elements(el)
@@ -13,9 +48,10 @@
   -- find token elements that are children of other token elements
   if is_token_element(el) then
     local parent = el:get_parent()
-    if is_token_element(parent) then
+    local is_parent_token, prefix = is_token_element(parent)
+    if is_parent_token then
       -- change top element in nested token elements to mstyle
-      parent._name = "mstyle"
+      update_element_name(parent, "mstyle", prefix)
     end
   end
 end
@@ -23,7 +59,8 @@
 local function fix_nested_mstyle(el)
   -- the <mstyle> element can be child of token elements
   -- we must exterminate it
-  if el:get_element_name() == "mstyle" then
+  local el_name = get_element_name(el)
+  if el_name == "mstyle" then
     local parent = el:get_parent()
     if is_token_element(parent) then
       -- if parent doesn't have the mathvariant attribute copy it from <mstyle>
@@ -44,13 +81,13 @@
     -- find if element has <mstyle> parent, and its value of mathvariant
     if not x:is_element() then
       return nil
-    elseif x:get_element_name() == "mstyle" then 
+    elseif get_element_name(x) == "mstyle" then 
       return x:get_attribute("mathvariant")
     else
       return find_mstyle(x:get_parent())
     end
   end
-  if el:get_element_name() == "mi" then
+  if get_element_name(el) == "mi" then
     -- process only <mi> that have mathvariant set
     local oldmathvariant = el:get_attribute("mathvariant")
     if oldmathvariant then
@@ -62,6 +99,74 @@
   end
 end
 
+local function contains_only_text(el)
+  -- detect if element contains only text
+  local elements = 0
+  local text     = 0
+  local children = el:get_children() or {}
+  for _ , child in ipairs(children) do
+    if child:is_text() then text = text + 1
+    elseif child:is_element() then elements = elements + 1
+    end
+  end
+  return text > 0 and elements == 0
+end
+
+-- check if <mstyle> element contains direct text. in that case, add
+-- <mtext>
+local function fix_missing_mtext(el)
+  if el:get_element_name() == "mstyle" and contains_only_text(el) then
+    -- add child <mtext>
+    log:debug("mstyle contains only text: " .. el:get_text())
+    -- copy the current mode, change it's element name to mtext and add it as a child of <mstyle>
+    local copy = el:copy_node()
+    copy._name = "mtext"
+    copy._parent = el
+    el._children = {copy}
+  end
+end
+
+local function is_radical(el)
+  local radicals = {msup=true, msub=true, msubsup=true}
+  return radicals[el:get_element_name()]
+end
+
+local function get_mrow_child(el)
+  local get_first = function(x) 
+    local children = x:get_children() 
+    return children[1]
+  end
+  local first = get_first(el)
+  -- either return first child, and if the child is <mrow>, return it's first child
+  if first and first:is_element() then
+    if first:get_element_name() == "mrow" then
+      return get_first(first), first
+    else
+      return first
+    end
+  end
+end
+
+local function fix_radicals(el)
+  if is_radical(el) then
+    local first_child, mrow = get_mrow_child(el)
+    -- if the first child is only one character long, it is possible that there is a problem
+    if first_child and string.len(first_child:get_text()) == 1 then
+      local name = first_child:get_element_name() 
+      local siblings = el:get_siblings()
+      local pos = el:find_element_pos()
+      -- it doesn't make sense to do any further processing if the element is at the beginning
+      if pos == 1 then return end
+      if name == "mo" then
+        for i = pos, 1,-1 do
+        end
+
+      end
+    end
+
+  end
+end
+
 -- put <mrow> as child of <math> if it already isn't here
 local allowed_top_mrow = {
   math=true
@@ -73,8 +178,8 @@
   -- don't process elements that already are mrow
   local parent = math:get_parent()
   local parent_name
-  if parent then parent_name = parent:get_element_name() end
-  local current_name = math:get_element_name()
+  if parent then parent_name = get_element_name(parent) end
+  local current_name, prefix = get_element_name(math)
   if #children < 2 or not allowed_top_mrow[current_name] or current_name == "mrow" or parent_name == "mrow" then return nil end
   local mrow_count = 0
   for _,v in ipairs(children) do
@@ -81,16 +186,17 @@
     if v:is_element() and is_token_element(v) then
       put_mrow = true
       -- break
-    elseif v:is_element() and v:get_element_name() == "mrow" then
+    elseif v:is_element() and get_element_name(v) == "mrow" then
       mrow_count = mrow_count + 1
     end
   end
-  if not put_mrow and math:get_element_name() == "math" and mrow_count == 0 then
+  if not put_mrow and get_element_name(math) == "math" and mrow_count == 0 then
     -- put at least one <mrow> to each <math>
     put_mrow = true
   end
   if put_mrow then
-    local mrow = math:create_element("mrow")
+    local newname = get_new_element_name("mrow", prefix)
+    local mrow = math:create_element(newname)
     for _, el in ipairs(children) do
       mrow:add_child_node(el)
     end
@@ -106,7 +212,9 @@
   local char = el:get_attribute(attr)
   local mo 
   if char then
-    mo = el:create_element("mo", {fence="true", form = form})
+    local name, prefix = get_element_name(el)
+    local newname = get_new_element_name("mo", prefix)
+    mo = el:create_element(newname, {fence="true", form = form})
     mo:add_child_node(mo:create_text_node(char))
   end
   return mo
@@ -116,13 +224,15 @@
 local function fix_mfenced(el)
   -- TeX4ht uses in some cases <mfenced> element which is deprecated in MathML.
   -- Firefox doesn't support it already.
-  if el:get_element_name() == "mfenced" then
+  local name, prefix = get_element_name(el)
+  if name == "mfenced" then
     -- we must replace it by <mrow><mo>start</mo><mfenced children...><mo>end</mo></mrow>
     local open = get_fence(el, "open", "prefix")
     local close = get_fence(el, "close", "postfix")
     -- there can be also separator attribute, but it is not used in TeX4ht
     -- change <mfenced> to <mrow> and remove all attributes
-    el._name = "mrow"
+    local newname = get_new_element_name("mrow", prefix)
+    el._name = newname
     el._attr = {}
     -- open must be first child, close needs to be last
     if open then el:add_child_node(open, 1) end
@@ -131,7 +241,7 @@
 end
 
 local function is_fence(el)
-  return el:get_element_name() == "mo" and el:get_attribute("fence") == "true"
+  return get_element_name(el) == "mo" and el:get_attribute("fence") == "true"
 end
 
 local function fix_mo_to_mfenced(el)
@@ -155,7 +265,9 @@
       end 
     end
     -- convert parent <mrow> to <mfenced>
-    parent._name = "mfenced"
+    local _, prefix = get_element_name(parent)
+    local newname = get_new_element_name("mfenced", prefix)
+    parent._name = newname
     parent._attr = {open = open, close = close}
   end
 end
@@ -162,18 +274,18 @@
 
 local function fix_numbers(el)
   -- convert <mn>1</mn><mo>.</mo><mn>3</mn> to <mn>1.3</mn>
-  if el:get_element_name() == "mn" then
+  if get_element_name(el) == "mn" then
     local n = el:get_sibling_node(1)
     -- test if next  element is <mo class="MathClass-punc">.</mo>
     if n and n:is_element() 
-         and n:get_element_name() == "mo" 
-         and n:get_attribute("class") == "MathClass-punc" 
+         and get_element_name(n) == "mo" 
+         and get_attribute(n, "class") == "MathClass-punc" 
          and n:get_text() == "." 
     then
       -- get next element and test if it is <mn>
       local x = el:get_sibling_node(2)
       if x and x:is_element() 
-           and x:get_element_name() == "mn" 
+           and get_element_name(x) == "mn" 
       then
         -- join numbers and set it as text content of the current element
         local newnumber = el:get_text() .. "." .. x:get_text()
@@ -194,7 +306,7 @@
   -- count <mo> and return true if list contains just them
   local mo = 0
   for _, x in ipairs(list) do
-    if x:get_element_name() == "mo" then mo = mo + 1 end
+    if get_element_name(x) == "mo" then mo = mo + 1 end
   end
   return mo
 end
@@ -205,18 +317,22 @@
   -- this fixes issues in LibreOffice with a^{*}
   -- I hope it doesn't introduce different issues
   -- process only <mo>
-  if x:get_element_name() ~= "mo" then return nil end
+  local el_name, prefix = get_element_name(x)
+  if el_name ~= "mo" then return nil end
 	local siblings = x:get_siblings()
 	-- test if current element list contains only <mo>
 	if just_operators(siblings) == #siblings then
 		if #siblings == 1 then
-			-- one <mo> translates to <mtext>
-			x._name = "mtext"
-      log:debug("changing one <mo> to <mtext>: " .. x:get_text())
-      -- I think we should use <mi>, but LO incorrectly renders it in <msubsup>,
-      -- even if we use the mathvariant="normal" attribute. <mtext> works, so
-      -- we use that instead.
-			-- x:set_attribute("mathvariant", "normal")
+      if not x:get_attribute("stretchy") then
+        -- one <mo> translates to <mtext>
+        local newname = get_new_element_name("mtext", prefix)
+        x._name = newname
+        log:debug("changing one <mo> to <mtext>: " .. x:get_text())
+        -- I think we should use <mi>, but LO incorrectly renders it in <msubsup>,
+        -- even if we use the mathvariant="normal" attribute. <mtext> works, so
+        -- we use that instead.
+        -- x:set_attribute("mathvariant", "normal")
+      end
 		else
 			-- multiple <mo> translate to <mtext>
 			local text = {}
@@ -231,7 +347,8 @@
       log:debug("changing <mo> to <mtext>: " .. newtext)
       x:add_child_node(text_el)
       -- change <mo> to <mtext>
-      x._name = "mtext"
+      local newname = get_new_element_name("mtext", prefix)
+      x._name = newname
       -- remove subsequent <mo>
       for i = 2, #siblings do
         siblings[i]:remove_node()
@@ -240,6 +357,47 @@
   end
 end
 
+local function is_last_element(el)
+  local siblings = el:get_siblings()
+  -- return true only if the current element is the last in the parent's children
+  for i = #siblings, 1, -1 do
+    local curr = siblings[i]
+    if curr == el then
+      return true
+    elseif curr:is_element() then
+      return false
+    end
+  end
+  return false
+end
+
+local function is_empty_row(el)
+  -- empty row should contain only one <mtd>
+  local count = 0
+  if el:get_text():match("^%s*$") then
+    for _, child in ipairs(el:get_children()) do
+      if child:is_element() then count = count + 1 end
+    end
+  end
+  -- if there is one or zero childrens, then it is empty row
+  return count < 2
+end
+
+
+local function delete_last_empty_mtr(el)
+  -- arrays sometimes contain last empty row, which causes rendering issues,
+  -- so we should remove them
+  local el_name, prefix = get_element_name(el)
+  if el_name == "mtr" 
+    and get_attribute(el, "class") == "array-row" 
+    and is_last_element(el)
+    and is_empty_row(el)
+  then
+    el:remove_node()
+  end
+
+end
+
 return function(dom)
   dom:traverse_elements(function(el)
     if settings.output_format ~= "odt" then
@@ -248,12 +406,15 @@
     else
       fix_mo_to_mfenced(el)
     end
+    fix_radicals(el)
     fix_token_elements(el)
     fix_nested_mstyle(el)
+    fix_missing_mtext(el)
     fix_numbers(el)
     fix_operators(el)
     fix_mathvariant(el)
     top_mrow(el)
+    delete_last_empty_mtr(el)
   end)
   return dom
 end

Added: trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-inlinecss.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-inlinecss.lua	                        (rev 0)
+++ trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-inlinecss.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -0,0 +1,16 @@
+local M = {}
+
+local filter = require "make4ht-domfilter"
+
+-- filters support only html formats
+function M.test(format)
+  if format:match("html") then return true end
+  return false
+end
+
+function M.modify_build(make)
+  local process = filter({"inlinecss"}, "inlinecss")
+  make:match("html?$", process)
+  return make
+end
+return M


Property changes on: trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-inlinecss.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-latexmk_build.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -12,8 +12,31 @@
       first = pos
     end
   end
+  -- we need to save contents of the .tmp file, to prevent extra executions from latexmk
+  -- tex4ht command overwrites content that was set by LaTeX with it's own stuff
+  local tmp_file 
+  make:add("save_tmp", function(par)
+    local f = io.open(par.input .. ".tmp", "r")
+    if f then
+      tmp_file = f:read("*all")
+      f:close()
+    end
+    return 0
+  end)
+  make:add("load_tmp", function(par)
+    if tmp_file then
+      local f = io.open(par.input .. ".tmp", "w")
+      if f then
+        f:write(tmp_file)
+      end
+    end
+    return 0
+  end)
   -- if htlatex was found
   if first then
+    -- handle tmp file
+    make:load_tmp {}
+    make:save_tmp {}
     -- add dummy latexmk call to the build sequence
     make:latexmk {}
     -- replace name, command and type in the first htlatex
@@ -26,6 +49,21 @@
     -- remove the dummy latexmk
     table.remove(build_seq)
   end
+  -- remove htlatex calls from the build sequence, they are unnecessary
+  local new_build_seq = {}
+  for pos, v in ipairs(build_seq) do
+    if v.name ~= "htlatex" and v.name ~= "tex4ht" then
+      table.insert(new_build_seq, v)
+    elseif v.name == "tex4ht" then
+      -- insert save_tmp before tex4ht
+      table.insert(new_build_seq, build_seq[#build_seq])
+      -- remove save_tmp from the end
+      table.remove(build_seq)
+      -- and now insert tex4ht
+      table.insert(new_build_seq, v)
+    end
+  end
+  make.build_seq = new_build_seq
   return make
 end
 return M

Modified: trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-preprocess_input.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -6,7 +6,7 @@
 local commands = {
   knitr = { command = 'Rscript -e "library(knitr); knit(\'${tex_file}\', output=\'${tmp_file}\')"'},
   pandoc = { command = 'pandoc -f ${input_format} -s -o \'${tmp_file}\' -t latex \'${tex_file}\''},
-  render = { command = 'Rscript -e "library(rmarkdown); render(\'${tex_file}\', output_file=\'${tmp_file}\')"'}
+  render = { command = 'Rscript -e "library(rmarkdown); render(\'${tex_file}\', output_file=\'${tmp_file}\',output_format = \'latex_document\')"'}
 }
 local filetypes = {
   rnw = {sequence = {"knitr"} },
@@ -17,7 +17,22 @@
   rst = {sequence = {"pandoc"}, options = {input_format = "rst"}},
 }
 
+local function get_temp_name(arg,curr, length)
+  -- we don't want to use the temp dir, because graphics would be then generated outside of 
+  -- the directory of the source document. so we will make
+  local tmp_name = os.tmpname()
+  if pos == sequence then
+    -- base tmp_name on the input name in the last step of sequence
+    -- so the generated images won't have random names
+    tmp_name = arg.input .. "-preprocess_input"
+  else
+    tmp_name = tmp_name:match("([^/\\]+)$")
+  end
+  return tmp_name
+end
 
+
+
 local function execute_sequence(sequence, arg, make)
   -- keep track of all generated tmp files
   local temp_files = {}
@@ -25,8 +40,8 @@
   -- should become the tex_file for the next one. It doesn't
   -- matter that it isn't TeX file in some cases
   local previous_temp 
-  for _, cmd_name in ipairs(sequence) do
-    local tmp_name = os.tmpname()
+  for pos, cmd_name in ipairs(sequence) do
+    local tmp_name = get_temp_name(arg,pos, #sequence)
     temp_files[#temp_files+1] = tmp_name
     -- make the temp file name accessible to the executed commands
     arg.tmp_file = tmp_name

Modified: trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-tidy.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-tidy.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/extensions/make4ht-ext-tidy.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -44,9 +44,13 @@
     local command = "tidy ${options}  ${filename}" % par
     log:info("running tidy: ".. command)
     -- os.execute(command)
-    local run = io.popen(command, "r")
+    local run, msg = io.popen(command, "r")
     local result = run:read("*all")
     run:close()
+    if not result or  result == "" then
+      log:warning("Cannot execute Tidy command")
+      return nil
+    end
     result = close_tags(result)
     local f = io.open(filename, "w")
     f:write(result)

Modified: trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-jats.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-jats.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-jats.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -1,6 +1,169 @@
 local M = {}
 local xtpipeslib = require "make4ht-xtpipes"
+local domfilter = require "make4ht-domfilter"
 
+
+-- some elements need to be moved from the document flow to the document meta
+local article_meta 
+local elements_to_move_to_meta = {}
+local function move_to_meta(el)
+  -- we don't move elements immediatelly, because it would prevent them from further 
+  -- processing in the filter. so we save them in an array, and move them once 
+  -- the full DOM was processed
+  table.insert(elements_to_move_to_meta, el)
+end
+
+local elements_to_move_to_title = {}
+local function move_to_title_group(el)
+  -- there can be only one title and subtitle
+  local name = el:get_element_name()
+  if not elements_to_move_to_title[name] then
+    elements_to_move_to_title[name] = el
+  end
+end
+
+local elements_to_move_to_contribs = {}
+local function move_to_contribs(el)
+  table.insert(elements_to_move_to_contribs, el)
+end
+
+
+
+local function process_moves()
+  if article_meta then
+    if elements_to_move_to_title["article-title"] 
+      and #article_meta:query_selector("title_group") == 0 then -- don't move anything if user added title_group from a config file
+      local title_group = article_meta:create_element("title_group")
+      for _, name in ipairs{ "article-title", "subtitle" } do
+        local v = elements_to_move_to_title[name] 
+        if v then
+          title_group:add_child_node(v:copy_node())
+          v:remove_node()
+        end
+      end
+      article_meta:add_child_node(title_group)
+    end
+    if #elements_to_move_to_contribs > 0 then
+      local contrib_group = article_meta:create_element("contrib-group")
+      for _, el in ipairs(elements_to_move_to_contribs) do
+        contrib_group:add_child_node(el:copy_node())
+        el:remove_node()
+      end
+      article_meta:add_child_node(contrib_group)
+    end
+    for _, el in ipairs(elements_to_move_to_meta) do
+      -- move elemnt's copy, and remove the original
+      article_meta:add_child_node(el:copy_node())
+      el:remove_node()
+    end
+  end
+end
+
+local function has_no_text(el)
+  -- detect if element contains only whitespace
+  if el:get_text():match("^%s*$") then
+    --- if it contains any elements, it has text
+    for _, child in ipairs(el:get_children()) do
+      if child:is_element() then return false end
+    end
+    return true
+  end
+  return false
+end
+
+local function is_xref_id(el)
+  return el:get_element_name() == "xref" and el:get_attribute("id") and el:get_attribute("rid") == nil and has_no_text(el)
+end
+-- set id to parent element for <xref> that contain only id
+local function xref_to_id(el)
+  local parent = el:get_parent()
+  -- set id only if it doesn't exist yet
+  if parent:get_attribute("id") == nil then
+    parent:set_attribute("id", el:get_attribute("id"))
+    el:remove_node()
+  end
+end
+
+local function make_text(el)
+  local text = el:get_text():gsub("^%s*", ""):gsub("%s*$", "")
+  local text_el = el:create_text_node(text)
+  el._children = {text_el}
+end
+
+local function is_empty_par(el)
+  return el:get_element_name() == "p" and has_no_text(el)
+end
+
+local function handle_links(el, params)
+  -- we must distinguish between internal links in the document, and external links
+  -- to websites etc. these needs to be changed to the <ext-link> element.
+  local link = el:get_attribute("rid") 
+  if link then
+    -- try to remove \jobname.xml from the beginning of the link
+    -- if the rest starts with #, then it is an internal link
+    local local_link = link:gsub("^" .. params.input .. ".xml", "")
+    if local_link:match("^%#") then
+      el:set_attribute("rid", local_link)
+    else
+      -- change element to ext-link for extenal links
+      el._name = "ext-link"
+      el:set_attribute("rid", nil)
+      el:set_attribute("xlink:href", link)
+    end
+  end
+end
+
+local function handle_maketitle(el)
+  -- <maketitle> is special element produced by TeX4ht from LaTeX's \maketitle
+  -- we need to pick interesting info from there, and move it to the header
+  local function is_empty(selector)
+    return #article_meta:query_selector(selector) == 0
+  end
+  -- move <aff> to <contrib>
+  local affiliations = {}
+  for _, aff in ipairs(el:query_selector("aff")) do
+    local id = aff:get_attribute("id") 
+    if id then 
+      for _,mark in ipairs(aff:query_selector("affmark")) do mark:remove_node() end
+      affiliations[id] = aff:copy_node() 
+    end
+  end
+  if is_empty("contrib") then
+    for _, contrib in ipairs(el:query_selector("contrib")) do
+      for _, affref in ipairs(contrib:query_selector("affref")) do
+        local id = affref:get_attribute("rid") or ""
+        -- we no longer need this node
+        affref:remove_node()
+        local linked_affiliation = affiliations[id]
+        if linked_affiliation then
+          contrib:add_child_node(linked_affiliation)
+        end
+      end
+      for _, string_name in ipairs(contrib:query_selector("string-name")) do
+        make_text(string_name)
+      end
+      move_to_contribs(contrib:copy_node())
+      -- we need to remove it from here, even though we remove <maketitle> later
+      -- we got doubgle contributors without that
+      contrib:remove_node()
+    end
+  end
+  if is_empty("pub-date") then
+    for _, date in ipairs(el:query_selector("date")) do
+      date._name = "pub-date"
+      for _, s in ipairs(date:query_selector("string-date")) do
+        make_text(s)
+      end
+      move_to_meta(date:copy_node())
+    end
+  end
+  el:remove_node()
+end
+
+
+
+
+
 function M.prepare_parameters(settings, extensions)
   settings.tex4ht_sty_par = settings.tex4ht_sty_par ..",jats"
   settings = mkutils.extensions_prepare_parameters(extensions, settings)
@@ -11,4 +174,49 @@
   return extensions
 end
 
+function M.modify_build(make)
+  filter_settings("joincharacters", {charclasses = {italic=true, bold=true}})
+
+  local process =  domfilter {
+    function(dom, params)
+      dom:traverse_elements(function(el)
+        -- some elements need special treatment
+        local el_name = el:get_element_name()
+        if is_xref_id(el) then
+          xref_to_id(el)
+        elseif el_name == "article-meta" then
+          -- save article-meta element for further processig
+          article_meta = el
+        elseif el_name == "article-title" then
+          move_to_title_group(el)
+        elseif el_name == "subtitle" then
+          move_to_title_group(el)
+        elseif el_name == "abstract" then
+          move_to_meta(el)
+        elseif el_name == "string-name" then
+          make_text(el)
+        elseif el_name == "contrib" then
+          move_to_contribs(el)
+        elseif is_empty_par(el) then
+          -- remove empty paragraphs
+          el:remove_node()
+        elseif el_name == "xref" then
+          handle_links(el, params)
+        elseif el_name == "maketitle" then
+          handle_maketitle(el)
+        elseif el_name == "div" and el:get_attribute("class") == "maketitle" then
+          el:remove_node()
+        end
+
+      end)
+      -- move elements that are marked for move
+      process_moves()
+      return dom
+    end, "joincharacters","mathmlfixes", "tablerows","booktabs"
+  }
+  local charclasses = {["mml:mi"] = true, ["mml:mn"] = true , italic = true, bold=true, roman = true, ["mml:mtext"] = true, mi=true, mn=true}
+  make:match("xml$", process, {charclasses = charclasses})
+  return make
+end
+
 return M

Modified: trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/formats/make4ht-odt.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -291,6 +291,9 @@
   local fixentities = filter {"entities-to-unicode", remove_xtpipes}
   make:match("4oo", fixentities)
   make:match("4om", fixentities)
+  -- we must handle outdir. make4ht copies the ODT file before it was packed, so
+  -- we will copy it again after packing later in this format file
+  local outdir = make.params["outdir"]
 
   -- build the ODT file. This match must be executed as a last one
   -- this will be executed as a first match, just to find the last filename 
@@ -305,7 +308,7 @@
       local lastfile = escape_file(lgfiles[#lgfiles]) .."$"
       -- make match for the last file
       -- odt packing will be done here
-      make:match(lastfile, function()
+      make:match(lastfile, function(filename, par)
         local groups = prepare_output_files(make.lgfile.files)
         local basename = groups.odt[1]
         local odtname = basename .. ".odt"
@@ -367,6 +370,12 @@
         end)
 
         odt:pack()
+        if outdir and outdir ~= "" then
+          local filename = odt.name
+          local outfilename = outdir .. "/" .. filename
+          log:info("Copying ODT file to the output dir: " .. outfilename)
+          mkutils.copy(filename,outfilename)
+        end
       end)
     end
     executed = true

Modified: trunk/Master/texmf-dist/scripts/make4ht/make4ht
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/make4ht	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/make4ht	2023-02-24 21:33:48 UTC (rev 66130)
@@ -29,7 +29,7 @@
 
 -- set version number. the template should be replaced by the
 -- actual version number by the build script
-local version = "v0.3l"
+local version = "v0.3m"
 mkparams.version_number = version
 
 local args = mkparams.get_args()
@@ -120,7 +120,13 @@
 
 make:match(".*",function(filename,par)
 	local outdir =  '' --par["outdir"] and par["outdir"] .."/" or ''
-	if par['outdir'] ~= "" then outdir = par['outdir'] .. '/' end
+	if par['outdir'] ~= "" then 
+    outdir = par['outdir'] .. '/' 
+  else
+    -- don't run unnecessary copy without output dir
+    log:info("No output directory")
+    return true
+  end
 	log:info("outdir: "..outdir)
 	local outfilename = outdir .. filename
 	mkutils.copy(filename,outfilename)

Modified: trunk/Master/texmf-dist/scripts/make4ht/make4ht-indexing.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/make4ht-indexing.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/make4ht-indexing.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -80,7 +80,7 @@
     elseif line:match("^\\indexentry") then
       -- replace the page number with the current
       -- index entry number
-      local result = line:gsub("{[0-9]+}", "{"..current_entry .."}")
+      local result = line:gsub("{[0-9]+}$", "{"..current_entry .."}")
       buffer[#buffer+1] = get_utf8(result)
     else
       buffer[#buffer+1] = line
@@ -96,11 +96,14 @@
   local entries = idxobj.map
   for  line in content:gmatch("([^\n]+)")  do
     local line = line:gsub("(%s*\\%a+.-%,)(.+)$", function(start,rest)
+      -- there is a problem when index term itself contains numbers, like Bible verses (1:2),
+      -- because they will be detected as page numbers too. I cannot find a good solution 
+      -- that wouldn't break something else.
       return start .. rest:gsub("(%d+)", function(page)
         local entry = entries[tonumber(page)]
         if entry then
           -- construct link to the index entry
-          return "\\Link[" .. entry.file .."]{".. entry.dest .."}{}" .. page .."\\EndLink{}"
+          return "\\Link[" .. entry.file .."]{".. entry.dest .."}{}" .. page .."\\EndLink{}" 
         else
           return page
         end
@@ -148,6 +151,7 @@
 
 local prepare_tmp_idx = function(par)
   par.idxfile = get_idxname(par)
+  if not par.idxfile or not mkutils.file_exists(par.idxfile) then return nil, "Cannot load idx file " .. (par.idxfile or "''") end
   -- construct the .ind name, based on the .idx name
   par.indfile = par.indfile or par.idxfile:gsub("idx$", "ind")
   load_enc()
@@ -166,6 +170,7 @@
   local idxfiles = {}
   local buffer 
   local idxfile = get_idxname(par)
+  if not idxfile or not mkutils.file_exists(idxfile) then return nil, "Cannot load idx file " .. (idxfile or "''") end
   for line in io.lines(idxfile) do
     local file = line:match("indexentry%[(.-)%]")
     if file then
@@ -198,7 +203,7 @@
   local cmd_name = command:match("^[%a]+") or "indexing"
   local xindylog  = logging.new(cmd_name)
   -- support split index
-  local subindexes = splitindex(par)
+  local subindexes = splitindex(par) or {}
   if #subindexes > 0 then
     -- call the command again on all files produced by splitindex
     for _, subindex in ipairs(subindexes) do

Modified: trunk/Master/texmf-dist/scripts/make4ht/mkutils.lua
===================================================================
--- trunk/Master/texmf-dist/scripts/make4ht/mkutils.lua	2023-02-24 21:33:16 UTC (rev 66129)
+++ trunk/Master/texmf-dist/scripts/make4ht/mkutils.lua	2023-02-24 21:33:48 UTC (rev 66130)
@@ -7,17 +7,17 @@
 local indexing = require("make4ht-indexing")
 --template engine
 function interp(s, tab)
-	local tab = tab or {}
-	return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
+  local tab = tab or {}
+  return (s:gsub('($%b{})', function(w) return tab[w:sub(3, -2)] or w end))
 end
 --print( interp("${name} is ${value}", {name = "foo", value = "bar"}) )
 
 function addProperty(s,prop)
-	if prop ~=nil then
-		return s .." "..prop
-	else
-		return s
-	end
+  if prop ~=nil then
+    return s .." "..prop
+  else
+    return s
+  end
 end
 getmetatable("").__mod = interp
 getmetatable("").__add = addProperty 
@@ -39,27 +39,27 @@
 end
 
 function string:split(sep)
-	local sep, fields = sep or ":", {}
-	local pattern = string.format("([^%s]+)", sep)
-	self:gsub(pattern, function(c) fields[#fields+1] = c end)
-	return fields
+  local sep, fields = sep or ":", {}
+  local pattern = string.format("([^%s]+)", sep)
+  self:gsub(pattern, function(c) fields[#fields+1] = c end)
+  return fields
 end
 
 function remove_extension(path)
-	local found, len, remainder = string.find(path, "^(.*)%.[^%.]*$")
-	if found then
-		return remainder
-	else
-		return path
-	end
+  local found, len, remainder = string.find(path, "^(.*)%.[^%.]*$")
+  if found then
+    return remainder
+  else
+    return path
+  end
 end
 
 -- 
 -- check if file exists
 function file_exists(file)
-	local f = io.open(file, "rb")
-	if f then f:close() end
-	return f ~= nil
+  local f = io.open(file, "rb")
+  if f then f:close() end
+  return f ~= nil
 end
 
 -- check if Lua module exists
@@ -90,18 +90,18 @@
   else
     local usedfiles={}
     for line in io.lines(filename) do
-			--- needs --- pokus.idv[1] ==> pokus0x.png --- 
+      --- needs --- pokus.idv[1] ==> pokus0x.png --- 
       -- line:gsub("needs --- (.+?)[([0-9]+) ==> ([%a%d%p%.%-%_]*)",function(name,page,k) table.insert(outputimages,k)end)
-      line:gsub("needs %-%-%- (.+)%[([0-9]+)%] ==> ([%a%d%p%.%-%_]*)",
-			  function(file,page,output) 
-					local rec = {
-						source = file,
-						page=page,
-						output = output
-					}
-					table.insert(outputimages,rec)
-				end
-			)
+      line:gsub("needs %-%-%- (.+)%[([0-9]+)%] ==> (.*) %-%-%-",
+      function(file,page,output) 
+        local rec = {
+          source = file,
+          page=page,
+          output = output
+        }
+        table.insert(outputimages,rec)
+      end
+      )
       line:gsub("File: (.*)",  function(k) 
         if not usedfiles[k] then
           table.insert(outputfiles,k)
@@ -137,20 +137,20 @@
     -- try to find file using kpse library if it cannot be found
     src = kpse.find_file(src) or src
   end
-	local command = string.format('%s "%s" "%s"', cp_func, src, dest)
-	if cp_func == "copy" then command = command:gsub("/",'\\') end
-	log:info("Copy: "..command)
+  local command = string.format('%s "%s" "%s"', cp_func, src, dest)
+  if cp_func == "copy" then command = command:gsub("/",'\\') end
+  log:info("Copy: "..command)
   if not file_exists(src) then
     log:error("File " .. src .. " doesn't exist")
   end
-	os.execute(command)
+  os.execute(command)
 end
 
 function mv(src, dest)
   local mv_func = os.type == "unix" and "mv " or "move "
-	local command = string.format('%s "%s" "%s"', mv_func, src, dest)
+  local command = string.format('%s "%s" "%s"', mv_func, src, dest)
   -- fix windows paths
-	if mv_func == "move" then command = command:gsub("/",'\\') end
+  if mv_func == "move" then command = command:gsub("/",'\\') end
   log:info("Move: ".. command)
   os.execute(command)
 end
@@ -163,61 +163,61 @@
 local used_dir = {}
 
 function prepare_path(path)
-	--local dirs = path:split("/")
-	local dirs = {}
-	if path:match("^/") then dirs = {""}
-	elseif path:match("^~") then
-		local home = os.getenv "HOME"
-		dirs = home:split "/"
-		path = path:gsub("^~/","")
-		table.insert(dirs,1,"")
-	end
-	if path:match("/$")then path = path .. " " end
-	for _,d in pairs(path:split "/") do
-		table.insert(dirs,d)
-	end
-	table.remove(dirs,#dirs)
-	return dirs,table.concat(dirs,"/")
+  --local dirs = path:split("/")
+  local dirs = {}
+  if path:match("^/") then dirs = {""}
+  elseif path:match("^~") then
+    local home = os.getenv "HOME"
+    dirs = home:split "/"
+    path = path:gsub("^~/","")
+    table.insert(dirs,1,"")
+  end
+  if path:match("/$")then path = path .. " " end
+  for _,d in pairs(path:split "/") do
+    table.insert(dirs,d)
+  end
+  table.remove(dirs,#dirs)
+  return dirs,table.concat(dirs,"/")
 end
 
 -- Find which part of path already exists
 -- and which directories have to be created
 function find_directories(dirs, pos)
-	local pos = pos or #dirs
-	-- we tried whole path and no dir exist
-	if pos < 1 then return dirs end
-	local path = ""
-	-- in the case of unix absolute path, empty string is inserted in dirs
-	if pos == 1 and dirs[pos] == "" then
-		path = "/"
-	else
-		path = table.concat(dirs,"/", 1,pos) .. "/"
-	end
-	if not lfs.chdir(path)  then -- recursion until we succesfully changed dir
-	-- or there are no elements in the dir table
-	return find_directories(dirs,pos - 1)
+  local pos = pos or #dirs
+  -- we tried whole path and no dir exist
+  if pos < 1 then return dirs end
+  local path = ""
+  -- in the case of unix absolute path, empty string is inserted in dirs
+  if pos == 1 and dirs[pos] == "" then
+    path = "/"
+  else
+    path = table.concat(dirs,"/", 1,pos) .. "/"
+  end
+  if not lfs.chdir(path)  then -- recursion until we succesfully changed dir
+  -- or there are no elements in the dir table
+  return find_directories(dirs,pos - 1)
 elseif pos ~= #dirs then -- if we succesfully changed dir
-	-- and we have dirs to create
-	local p = {}
-	for i = pos+1, #dirs do
-		table.insert(p, dirs[i])
-	end
-	return p
+  -- and we have dirs to create
+  local p = {}
+  for i = pos+1, #dirs do
+    table.insert(p, dirs[i])
+  end
+  return p
 else  -- whole path exists
-	return {}
+  return {}
 end
 end
 
 function mkdirectories(dirs)
-	if type(dirs) ~="table" then
-		return false, "mkdirectories: dirs is not table"
-	end
-	for _,d in ipairs(dirs) do
-		local stat,msg = lfs.mkdir(d)
-		if not stat then return false, "makedirectories error: "..msg end
-		lfs.chdir(d)
-	end
-	return true
+  if type(dirs) ~="table" then
+    return false, "mkdirectories: dirs is not table"
+  end
+  for _,d in ipairs(dirs) do
+    local stat,msg = lfs.mkdir(d)
+    if not stat then return false, "makedirectories error: "..msg end
+    lfs.chdir(d)
+  end
+  return true
 end
 
 function copy_filter(src,dest, filter)
@@ -233,22 +233,22 @@
 
 
 function copy(filename,outfilename)
-	local currdir = lfs.currentdir()
-	if filename == outfilename then return true end
-	local parts, path = prepare_path(outfilename)
-	if not used_dir[path] then 
-		local to_create, msg = find_directories(parts)
-		if not to_create then
-			log:warning(msg)
-			return false
-		end
-		used_dir[path] = true
-		local stat, msg = mkdirectories(to_create)
-		if not stat then log:warning(msg) end
-	end
-	lfs.chdir(currdir)
-	cp(filename, path)
-	return true
+  local currdir = lfs.currentdir()
+  if filename == outfilename then return true end
+  local parts, path = prepare_path(outfilename)
+  if not used_dir[path] then 
+    local to_create, msg = find_directories(parts)
+    if not to_create then
+      log:warning(msg)
+      return false
+    end
+    used_dir[path] = true
+    local stat, msg = mkdirectories(to_create)
+    if not stat then log:warning(msg) end
+  end
+  lfs.chdir(currdir)
+  cp(filename, path)
+  return true
 end
 
 function execute(command)
@@ -373,11 +373,14 @@
 env.Make:add("latexmk", function(par)
   local settings = get_filter_settings "htlatex" or {}
   par.interaction = par.interaction or settings.interaction or "batchmode"
-  local command = Make.latex_command
+  local command = Make.latex_command 
+  -- add " %O " after the engine name. it should be filled by latexmk
+  command = command:gsub("%s", " %%O ", 1)
   par.expanded = command % par
   -- quotes in latex_command must be escaped, they cause Latexmk error
   par.expanded = par.expanded:gsub('"', '\\"')
-  local newcommand = 'latexmk -latex="${expanded}" -dvi ${tex_file}' % par
+  local newcommand = 'latexmk  -pdf- -ps- -auxdir=. -outdir=. -latex="${expanded}" -dvi -jobname=${input} ${tex_file}' % par
+  log:info("LaTeX call: " .. newcommand)
   os.execute(newcommand)
   return Make.testlogfile(par)
 end, {correct_exit= 0})
@@ -406,7 +409,7 @@
   log:info("executing: " .. command)
   return execute(command)
 end
- , nil, 1)
+, nil, 1)
 env.Make:add("t4ht","t4ht ${t4ht_par} \"${input}.${ext}\"",{ext="dvi"},1)
 
 env.Make:add("clean", function(par)
@@ -439,7 +442,7 @@
   end
   Make:match("tmp$", function()
     -- remove temporary and auxilary files
-    for _,ext in ipairs {"aux", "xref", "tmp", "4tc", "4ct", "idv", "lg","dvi", "log"} do
+    for _,ext in ipairs {"aux", "xref", "tmp", "4tc", "4ct", "idv", "lg","dvi", "log", "ncx"} do
       remove_file(main_name .. "." .. ext)
     end
   end)



More information about the tex-live-commits mailing list.