summaryrefslogtreecommitdiff
path: root/support/make4ht/domfilters
diff options
context:
space:
mode:
Diffstat (limited to 'support/make4ht/domfilters')
-rw-r--r--support/make4ht/domfilters/make4ht-booktabs.lua82
-rw-r--r--support/make4ht/domfilters/make4ht-joincharacters.lua113
-rw-r--r--support/make4ht/domfilters/make4ht-tablerows.lua14
3 files changed, 179 insertions, 30 deletions
diff --git a/support/make4ht/domfilters/make4ht-booktabs.lua b/support/make4ht/domfilters/make4ht-booktabs.lua
new file mode 100644
index 0000000000..edec8adbd8
--- /dev/null
+++ b/support/make4ht/domfilters/make4ht-booktabs.lua
@@ -0,0 +1,82 @@
+
+local function find_cmidrules(current_rows)
+ -- save rows with cmidrules here
+ local matched_rows = {}
+ local continue = false
+ for row_no, row in ipairs(current_rows) do
+ local columnposition = 1
+ local matched_cmidrule = false
+
+ for _, col in ipairs(row:query_selector("td")) do
+ -- keep track of culumns
+ local span = tonumber(col:get_attribute("colspan")) or 1
+ local cmidrule = col:query_selector(".cmidrule")
+ -- column contain cmidrule
+ if #cmidrule > 0 then
+ -- remove any child elements, we don't need them anymore
+ col._children = {}
+ -- only one cmidrule can be on each row, save the position, column span and all attributes
+ matched_rows[row_no] = {attributes = col._attr, column = columnposition, span = span, continue = continue}
+ matched_cmidrule = true
+ end
+ columnposition = columnposition + span
+ end
+ if matched_cmidrule then
+ -- save the row number of the first cmidrule on the current row
+ continue = continue or row_no
+ else
+ continue = false
+ end
+
+ end
+ -- save the table rows count, so we can loop over them sequentially later
+ matched_rows.length = #current_rows
+ return matched_rows
+end
+
+local function update_row(current_rows, match, newspan, i)
+ local row_to_update = current_rows[match.continue]
+ -- insert spanning column if necessary
+ if newspan > 0 then
+ local td = row_to_update:create_element("td", {colspan=tostring(newspan), span="nazdar"})
+ row_to_update:add_child_node(td)
+ end
+ -- insert the rule column
+ local td = row_to_update:create_element("td", match.attributes)
+ row_to_update:add_child_node(td)
+ -- remove unnecessary row
+ current_rows[i]:remove_node()
+end
+
+local function join_rows(matched_rows,current_rows)
+ for i = 1, matched_rows.length do
+ local match = matched_rows[i]
+ if match then
+ -- we only need to process rows that place subsequent cmidrules on the same row
+ local continue = match.continue
+ if continue then
+ local prev_row = matched_rows[continue]
+ -- find column where the previous cmidrule ends
+ local prev_end = prev_row.column + prev_row.span
+ local newspan = match.column - prev_end
+ update_row(current_rows, match, newspan, i)
+ -- update the current row position
+ prev_row.column = match.column
+ prev_row.span = match.span
+ end
+ end
+ end
+end
+
+local function process_booktabs(dom)
+ local tables = dom:query_selector("table")
+ for _, tbl in ipairs(tables) do
+ local current_rows = tbl:query_selector("tr")
+ local matched_rows = find_cmidrules(current_rows)
+ join_rows(matched_rows, current_rows)
+ end
+ return dom
+end
+
+return process_booktabs
+
diff --git a/support/make4ht/domfilters/make4ht-joincharacters.lua b/support/make4ht/domfilters/make4ht-joincharacters.lua
index 5830eae78e..4493aef023 100644
--- a/support/make4ht/domfilters/make4ht-joincharacters.lua
+++ b/support/make4ht/domfilters/make4ht-joincharacters.lua
@@ -3,14 +3,35 @@ local log = logging.new("joincharacters")
local charclasses = {
span=true,
mn = true,
- mi = true
}
+local function update_mathvariant(curr)
+ -- when we join several <mi> elements, they will be rendered incorrectly
+ -- we must set the mathvariant attribute
+ local parent = curr:get_parent()
+ -- set mathvariant only if it haven't been set by the parent element
+ if not parent:get_attribute("mathvariant") then
+ -- curr._attr = curr._attr or {}
+ local mathvariant = "italic"
+ -- the joined elements don't have attributes
+ curr._attr = curr._attr or {}
+ curr:set_attribute("mathvariant", mathvariant)
+ end
+end
+
+local table_count = function(tbl)
+ local tbl = tbl or {}
+ local i = 0
+ for k,v in pairs(tbl) do i = i + 1 end
+ return i
+end
+
+
local has_matching_attributes = function (el, next_el)
local el_attr = el._attr or {}
local next_attr = next_el._attr or {}
-- if the number of attributes doesn't match, elements don't match
- if #next_attr ~= #el_attr then return false end
+ if table_count(next_attr) ~= table_count(el_attr) then return false end
for k, v in pairs(el_attr) do
-- if any attribute doesn't match, elements don't match
if v~=next_attr[k] then return false end
@@ -18,6 +39,7 @@ local has_matching_attributes = function (el, next_el)
return true
end
+
local function join_characters(obj,par)
-- join adjanced span and similar elements inserted by
-- tex4ht to just one object.
@@ -25,45 +47,48 @@ local function join_characters(obj,par)
local options = get_filter_settings "joincharacters"
local charclasses = options.charclasses or par.charclasses or charclasses
-
- obj:traverse_elements(function(el)
- local get_name = function(curr)
- return string.lower(curr:get_element_name())
- end
- local get_class = function(next_el)
- return next_el:get_attribute("class") or next_el:get_attribute("mathvariant")
- end
- local is_span = function(next_el)
- return charclasses[get_name(next_el)]
+ local get_name = function(curr)
+ return string.lower(curr:get_element_name())
+ end
+ local get_class = function(next_el)
+ return next_el:get_attribute("class") or next_el:get_attribute("mathvariant")
+ end
+ local is_span = function(next_el)
+ return charclasses[get_name(next_el)]
+ 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
+ el:add_child_node(child)
end
+ -- remove the next element
+ next_el:remove_node()
+ end
- local function get_next(curr, class)
- local next_el = curr:get_next_node()
- if next_el and next_el:is_element() and is_span(next_el) then
- return next_el
- -- if the next node is space followed by a matching element, we should add this space
- elseif next_el and next_el:is_text() and get_next(next_el, class) then
- local text = next_el._text
- -- match only text containing just whitespace
- if text:match("^%s+$") then return next_el end
- end
+ local function get_next(curr, class)
+ local next_el = curr:get_next_node()
+ if next_el and next_el:is_element() and is_span(next_el) then
+ return next_el
+ -- if the next node is space followed by a matching element, we should add this space
+ elseif next_el and next_el:is_text() and get_next(next_el, class) then
+ local text = next_el._text
+ -- match only text containing just whitespace
+ if text:match("^%s+$") then return next_el end
end
+ end
+
+ 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
local next_el = get_next(el)
-- loop over the following elements and test whether they are of the same type
-- as the current one
- while next_el do
+ while next_el do
-- save the next element because we will remove it later
local real_next = get_next(next_el)
if get_name(el) == get_name(next_el) and has_matching_attributes(el,next_el) and not el:get_attribute("id") then
- -- it the following element match, copy it's children to the current element
- for _, child in ipairs(next_el:get_children()) do
- el:add_child_node(child)
- end
- -- remove the next element
- next_el:remove_node()
+ join_elements(el, next_el)
-- add the whitespace
elseif next_el:is_text() then
local s = next_el._text
@@ -80,6 +105,36 @@ local function join_characters(obj,par)
end
end)
+ -- process <mi> elements
+ obj:traverse_elements(function(el)
+ local function get_next_mi(curr)
+ local next_el = curr:get_next_node()
+ if next_el and next_el:is_element() then
+ return next_el
+ end
+ end
+ local function has_no_attributes(x)
+ return table_count(x._attr) == 0
+ end
+
+ -- join only subsequential <mi> elements with no attributes
+ if get_name(el) == "mi" and has_no_attributes(el) then
+ local next_el = get_next_mi(el)
+ while next_el do
+ local real_next = get_next_mi(next_el)
+ if get_name(next_el) == "mi" and has_no_attributes(next_el) then
+ join_elements(el, next_el)
+ -- set math variant to italic
+ -- (if the parent <mstyle> element doesn't set it to something else)
+ update_mathvariant(el)
+ else
+ -- break the loop otherwise
+ real_next = nil
+ end
+ next_el = real_next
+ end
+ end
+ end)
-- join text nodes in an element into one
obj:traverse_elements(function(el)
-- save the text
diff --git a/support/make4ht/domfilters/make4ht-tablerows.lua b/support/make4ht/domfilters/make4ht-tablerows.lua
index 155c24529a..3e3931b368 100644
--- a/support/make4ht/domfilters/make4ht-tablerows.lua
+++ b/support/make4ht/domfilters/make4ht-tablerows.lua
@@ -1,5 +1,16 @@
local log = logging.new ("tablerows")
return function(dom)
+ local has_child_elements = function(child)
+ -- detect if the element contains child elements
+ local child_elements = 0
+ local children = child:get_children()
+ for _, el in ipairs(children) do
+ local step = el:is_element() and 1 or 0
+ -- log:info("element name", el._name)
+ child_elements = child_elements + step
+ end
+ return child_elements > 0
+ end
local is_empty_row = function(row)
local not_empty = false
local element_count = 0
@@ -11,7 +22,8 @@ return function(dom)
if child:is_element() then
element_count = element_count + 1
-- empty rows contain only one element, it is not empty otherwise
- if element_count > 1 then return false end
+ if element_count > 1 or has_child_elements(child) then return false end
+
-- detect if it contains only whitespace
not_empty = child:get_text():gsub("%s","") ~= "" or not_empty
end