diff options
author | Norbert Preining <norbert@preining.info> | 2022-02-19 03:02:56 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2022-02-19 03:02:56 +0000 |
commit | 1db3acf2bbb07034aafc552f322633a96b748cf4 (patch) | |
tree | 01227822acc2f3b2641e108b814d38c64031ff4e /support/make4ht/domfilters | |
parent | 41041c6bdcedcc33698491c2caec4cd725a4fe97 (diff) |
CTAN sync 202202190302
Diffstat (limited to 'support/make4ht/domfilters')
-rw-r--r-- | support/make4ht/domfilters/make4ht-fixinlines.lua | 30 | ||||
-rw-r--r-- | support/make4ht/domfilters/make4ht-mathmlfixes.lua | 129 | ||||
-rw-r--r-- | support/make4ht/domfilters/make4ht-odtfonts.lua | 26 |
3 files changed, 175 insertions, 10 deletions
diff --git a/support/make4ht/domfilters/make4ht-fixinlines.lua b/support/make4ht/domfilters/make4ht-fixinlines.lua index d1b11b123e..02338505b7 100644 --- a/support/make4ht/domfilters/make4ht-fixinlines.lua +++ b/support/make4ht/domfilters/make4ht-fixinlines.lua @@ -41,15 +41,33 @@ local function fix_inlines(obj) local settings = get_filter_settings "fixinlines" local inline_elements = settings.inline_elements or inline_elements local nodes = obj:get_path("html body") + local new = nil obj:traverse_node_list(nodes, function(jej) - if jej._type == "ELEMENT" then - local name = string.lower(jej._name) + if jej._type == "ELEMENT" or jej._type == "TEXT" then + local name = string.lower(jej._name or "") -- local parent = jej:get_parent_node() - if inline_elements[name] then - local new = obj:create_element("p" ) - new:add_child_node(obj:copy_node(jej)) - jej:replace_node(new) + if inline_elements[name] or jej._type == "TEXT" then + if not new then + -- start new paragraph + if jej._type == "TEXT" and jej._text:match("^%s+$") then + -- ignore parts that contain only whitespace and are placed before + -- paragraph start + else + new = obj:create_element("p" ) + new:add_child_node(obj:copy_node(jej)) + jej:replace_node(new) + end + else + -- paragraph already exists + new:add_child_node(obj:copy_node(jej)) + jej:remove_node() + end + else + -- close the current paragraph before new block element + new = nil end + else + new = nil end end) return obj diff --git a/support/make4ht/domfilters/make4ht-mathmlfixes.lua b/support/make4ht/domfilters/make4ht-mathmlfixes.lua index 42f1e55775..12754bedb9 100644 --- a/support/make4ht/domfilters/make4ht-mathmlfixes.lua +++ b/support/make4ht/domfilters/make4ht-mathmlfixes.lua @@ -1,3 +1,4 @@ +local log = logging.new("mathmlfixes") -- <mglyph> should be inside <mi>, so we don't process it -- even though it is a token element local token = {"mi", "mn", "mo", "mtext", "mspace", "ms"} @@ -37,20 +38,57 @@ local function fix_nested_mstyle(el) end end --- if element contains --- wrap everything in <mrow> +local function fix_mathvariant(el) + -- set mathvariant of <mi> that is child of <mstyle> to have the same value + local function find_mstyle(x) + -- 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 + return x:get_attribute("mathvariant") + else + return find_mstyle(x:get_parent()) + end + end + if el:get_element_name() == "mi" then + -- process only <mi> that have mathvariant set + local oldmathvariant = el:get_attribute("mathvariant") + if oldmathvariant then + local mathvariant = find_mstyle(el:get_parent()) + if mathvariant then + el:set_attribute("mathvariant", mathvariant) + end + end + end +end + +-- put <mrow> as child of <math> if it already isn't here +local allowed_top_mrow = { + math=true +} local function top_mrow(math) local children = math:get_children() local put_mrow = false -- don't process elements with one or zero children -- don't process elements that already are mrow - if #children < 2 or math:get_element_name() == "mrow" then return nil end + 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 #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 if v:is_element() and is_token_element(v) then put_mrow = true - break + -- break + elseif v:is_element() and v:get_element_name() == "mrow" then + mrow_count = mrow_count + 1 end end + if not put_mrow and math:get_element_name() == "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") for _, el in ipairs(children) do @@ -122,6 +160,86 @@ local function fix_mo_to_mfenced(el) end end +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 + 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 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" + then + -- join numbers and set it as text content of the current element + local newnumber = el:get_text() .. "." .. x:get_text() + log:debug("Joining numbers: " .. newnumber) + el._children = {} + local newchild = el:create_text_node(newnumber) + el:add_child_node(newchild) + -- remove elements that hold dot and decimal part + n:remove_node() + x:remove_node() + end + end + end +end + + +local function just_operators(list) + -- 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 + end + return mo +end + + +local function fix_operators(x) + -- change <mo> elements that are only children of any element to <mi> + -- 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 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") + else + -- multiple <mo> translate to <mtext> + local text = {} + for _, el in ipairs(siblings) do + text[#text+1] = el:get_text() + end + -- replace first <mo> text with concetanated text content + -- of all <mo> elements + x._children = {} + local newtext = table.concat(text) + local text_el = x:create_text_node(newtext) + log:debug("changing <mo> to <mtext>: " .. newtext) + x:add_child_node(text_el) + -- change <mo> to <mtext> + x._name = "mtext" + -- remove subsequent <mo> + for i = 2, #siblings do + siblings[i]:remove_node() + end + end + end +end + return function(dom) dom:traverse_elements(function(el) if settings.output_format ~= "odt" then @@ -132,6 +250,9 @@ return function(dom) end fix_token_elements(el) fix_nested_mstyle(el) + fix_numbers(el) + fix_operators(el) + fix_mathvariant(el) top_mrow(el) end) return dom diff --git a/support/make4ht/domfilters/make4ht-odtfonts.lua b/support/make4ht/domfilters/make4ht-odtfonts.lua new file mode 100644 index 0000000000..68c8ecadc2 --- /dev/null +++ b/support/make4ht/domfilters/make4ht-odtfonts.lua @@ -0,0 +1,26 @@ +return function(dom, params) + -- fix ODT style for fonts + -- sometimes, fonts have missing size, we need to patch styles + local properties = get_filter_settings "odtfonts" or {} + local fix_lgfile_fonts = params.patched_lg_fonts or properties.patched_lg_fonts or {} + for _, style in ipairs(dom:query_selector "style|style") do + local typ = style:get_attribute("style:family") + if typ == "text" then + -- detect if the style is for font + local style_name = style:get_attribute("style:name") + local name, size, size2, size3 = style_name:match("(.-)%-(%d*)x%-(%d*)x%-(%d+)") + if name then + -- find if the style corresponds to a problematic font (it is set in formats/make4ht-odt.lua) + local used_name = name .. "-" .. size + if fix_lgfile_fonts[used_name] then + -- copy current style and fix the name + local new = style:copy_node() + new:set_attribute("style:name", string.format("%s-x-%sx-%s", name, size2, size3)) + local parent = style:get_parent() + parent:add_child_node(new) + end + end + end + end + return dom +end |