diff options
Diffstat (limited to 'support/make4ht/domfilters/make4ht-mathmlfixes.lua')
-rw-r--r-- | support/make4ht/domfilters/make4ht-mathmlfixes.lua | 67 |
1 files changed, 67 insertions, 0 deletions
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) |