summaryrefslogtreecommitdiff
path: root/support/make4ht/domfilters
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-03-20 03:01:11 +0000
committerNorbert Preining <norbert@preining.info>2021-03-20 03:01:11 +0000
commitd3b06b2254431c03e127876a07ae654091314c72 (patch)
tree4fa5e40c55aae3ceeeab0048fabbb778ee06e284 /support/make4ht/domfilters
parent6ad1cf68ae6add67e56faf5ec4390fead04e31b4 (diff)
CTAN sync 202103200301
Diffstat (limited to 'support/make4ht/domfilters')
-rw-r--r--support/make4ht/domfilters/make4ht-joincharacters.lua16
-rw-r--r--support/make4ht/domfilters/make4ht-mathmlfixes.lua67
2 files changed, 81 insertions, 2 deletions
diff --git a/support/make4ht/domfilters/make4ht-joincharacters.lua b/support/make4ht/domfilters/make4ht-joincharacters.lua
index 4493aef023..34737f921a 100644
--- a/support/make4ht/domfilters/make4ht-joincharacters.lua
+++ b/support/make4ht/domfilters/make4ht-joincharacters.lua
@@ -56,6 +56,18 @@ local function join_characters(obj,par)
local is_span = function(next_el)
return charclasses[get_name(next_el)]
end
+ local has_children = function(curr)
+ -- don't process spans that have child elements
+ local children = curr:get_children() or {}
+ -- if there is more than one child, we can be sure that it has child elements
+ if #children > 1 then
+ return true
+ elseif #children == 1 then
+ -- test if the child is an element
+ return children[1]:is_element()
+ end
+ return false
+ end
local join_elements = function(el, next_el)
-- it the following element match, copy it's children to the current element
for _, child in ipairs(next_el:get_children()) do
@@ -79,8 +91,8 @@ local function join_characters(obj,par)
obj:traverse_elements(function(el)
-- loop over all elements and test if the current element is in a list of
- -- processed elements (charclasses)
- if is_span(el) then
+ -- processed elements (charclasses) and if it doesn't contain children
+ if is_span(el) and not has_children(el) then
local next_el = get_next(el)
-- loop over the following elements and test whether they are of the same type
-- as the current one
diff --git a/support/make4ht/domfilters/make4ht-mathmlfixes.lua b/support/make4ht/domfilters/make4ht-mathmlfixes.lua
index 3e044b9445..55c0da379b 100644
--- a/support/make4ht/domfilters/make4ht-mathmlfixes.lua
+++ b/support/make4ht/domfilters/make4ht-mathmlfixes.lua
@@ -37,8 +37,75 @@ local function fix_nested_mstyle(el)
end
end
+local function get_fence(el, attr, form)
+ -- convert fence attribute to <mo> element
+ -- attr: open | close
+ -- form: prefix | postfix
+ local char = el:get_attribute(attr)
+ local mo
+ if char then
+ mo = el:create_element("mo", {fence="true", form = form})
+ mo:add_child_node(mo:create_text_node(char))
+ end
+ return mo
+end
+
+
+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
+ -- 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"
+ el._attr = {}
+ -- open must be first child, close needs to be last
+ if open then el:add_child_node(open, 1) end
+ if close then el:add_child_node(close) end
+ end
+end
+
+local function is_fence(el)
+ return el:get_element_name() == "mo" and el:get_attribute("fence") == "true"
+end
+
+local function fix_mo_to_mfenced(el)
+ -- LibreOffice NEEDS <mfenced> element. so we need to convert <mrow><mo fence="true">
+ -- to <mfenced>. ouch.
+ if is_fence(el) then
+ local parent = el:get_parent()
+ local open = el:get_text():gsub("%s*", "") -- convert mo content to text, so it can be used in
+ -- close needs to be the last element in the sibling list of the current element
+ local siblings = el:get_siblings()
+ el:remove_node() -- we don't need this element anymore
+ local close
+ for i = #siblings, 1, -1 do
+ last = siblings[i]
+ if last:is_element() then
+ if is_fence(last) then -- set close attribute only if the last element is fence
+ close = last:get_text():gsub("%s*", "")
+ last:remove_node() -- remove <mo>
+ end
+ break -- break looping over elements once we find last element
+ end
+ end
+ -- convert parent <mrow> to <mfenced>
+ parent._name = "mfenced"
+ parent._attr = {open = open, close = close}
+ end
+end
+
return function(dom)
dom:traverse_elements(function(el)
+ if settings.output_format ~= "odt" then
+ -- LibreOffice needs <mfenced>, but Firefox doesn't
+ fix_mfenced(el)
+ else
+ fix_mo_to_mfenced(el)
+ end
fix_token_elements(el)
fix_nested_mstyle(el)
end)