Compare commits

..

No commits in common. "23c6714e97354255991075f89cb8e5010f405c84" and "b83f2c1d8cf009319ea9a14389f205eb674c0a21" have entirely different histories.

12 changed files with 103 additions and 466 deletions

View File

@ -1,84 +0,0 @@
local write_xml = require'luamml-xmlwriter'
local make_root = require'luamml-convert'.make_root
local properties = node.get_properties_table()
local funcid = luatexbase.new_luafunction'luamml_amsmath_add_box_to_row:'
token.set_lua('luamml_amsmath_add_box_to_row:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
-- local box = token.scan_int()
local boxnum = 0
local startmath = tex.box[boxnum].list
assert(startmath.id == node.id"math")
local props = assert(properties[startmath])
local mml = assert(props.saved_mathml_table)
table.insert(mml, 1, {[0] = 'maligngroup'})
if mml[0] == 'mstyle' and mml.displaystyle == true then
mml[0], mml.displaystyle, mml.scriptlevel = 'mtd', nil, nil
else
if mml[0] ~= 'mstyle' then
mml = {[0] = 'mstyle', displaystyle = false, mml}
end
mml = {[0] = 'mtd', mml}
end
local row_temp = tex.nest[tex.nest.ptr-1]
print(row_temp)
props = properties[row_temp]
if not props then
props = {}
properties[row_temp] = props
end
if not props.mathml_row then
props.mathml_row = {[0] = 'mtr'}
end
mml_row = props.mathml_row
table.insert(mml_row, mml)
end
local funcid = luatexbase.new_luafunction'luamml_amsmath_finalize_row:'
token.set_lua('luamml_amsmath_finalize_row:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
local row_temp = tex.nest[tex.nest.ptr-1]
print("final", row_temp)
local props = properties[row_temp]
if not props then return end
if not props.mathml_row then return end
mml_row = props.mathml_row
props = properties[tex.lists.align_head]
if not props then
props = {}
properties[tex.lists.align_head] = props
end
local mml_table = props.mathml_table_node_table
if not mml_table then
mml_table = {[0] = 'mtable', displaystyle = true}
props.mathml_table_node_table = mml_table
end
table.insert(mml_table, mml_row)
end
local funcid = luatexbase.new_luafunction'luamml_amsmath_finalize_table:'
token.set_lua('luamml_amsmath_finalize_table:', funcid)
lua.get_functions_table()[funcid] = function()
-- TODO: Error handling etc
local props = properties[tex.lists.align_head]
if not props then return end
local mml_table = props.mathml_table_node_table
if not mml_table then return end
print(write_xml(make_root(mml_table, 2)))
end
funcid = luatexbase.new_luafunction'luamml_last_math_alignmark:'
token.set_lua('luamml_last_math_alignmark:', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
local n = tex.nest.top.tail
n = n.nucleus or n
local props = properties[n]
if not props then
props = {}
properties[n] = props
end
props.mathml_table = {[0] = 'malignmark'}
end

View File

@ -1,51 +0,0 @@
-- local remap_ot1 = {
-- 0x0393, 0x0394, 0x0398, 0x039B, 0x039E, 0x03A0, 0x03A3, 0x03A5,
-- 0x03A6, 0x03A8, 0x03A9, nil, nil, nil, nil, nil,
-- }
local remap_oml = { [0] =
-- Greek italic
0x1D6E4, 0x1D6E5, 0x1D6E9, 0x1D6EC, 0x1D6EF, 0x1D6F1, 0x1D6F4, 0x1D6F6,
0x1D6F7, 0x1D6F9, 0x1D6FA, 0x1D6FC, 0x1D6FD, 0x1D6FE, 0x1D6FF, 0x1D716,
0x1D701, 0x1D702, 0x1D703, 0x1D704, 0x1D705, 0x1D706, 0x1D707, 0x1D708,
0x1D709, 0x1D70B, 0x1D70C, 0x1D70E, 0x1D70F, 0x1D710, 0x1D719, 0x1D712,
0x1D713, 0x1D714, 0x1D700, 0x1D717, 0x1D71B, 0x1D71A, 0x1D70D, 0x1D711,
-- Symbols. (The nils are hook parts)
0x21BC, 0x21BD, 0x21C0, 0x21C1, nil, nil, 0x22BB, 0x22BC,
-- old style numerals (nobody should ever use these in math) and some punctuation
nil, nil, nil, nil, nil, nil, nil, nil,
nil, nil, 0x2E, 0x2C, 0x3C, 0x2F, 0x3E, 0x226D,
-- letters filled up with symbols
0x2202, 0x1D434, 0x1D435, 0x1D436, 0x1D437, 0x1D438, 0x1D439, 0x1D43A,
0x1D43B, 0x1D43C, 0x1D43D, 0x1D43E, 0x1D43F, 0x1D440, 0x1D441, 0x1D442,
0x1D443, 0x1D444, 0x1D445, 0x1D446, 0x1D447, 0x1D448, 0x1D449, 0x1D44A,
0x1D44B, 0x1D44C, 0x1D44D, 0x266D, 0x266E, 0x266F, 0x2323, 0x2322,
0x2113, 0x1D44E, 0x1D44F, 0x1D450, 0x1D451, 0x1D452, 0x1D453, 0x1D454,
0x210E, 0x1D456, 0x1D457, 0x1D458, 0x1D459, 0x1D45A, 0x1D45B, 0x1D45C,
0x1D45D, 0x1D45E, 0x1D45F, 0x1D460, 0x1D461, 0x1D462, 0x1D463, 0x1D464,
0x1D465, 0x1D466, 0x1D467, 0x1D6A4, 0x1D6A5, 0x2118, 0x2192, nil,
}
local remap_oms = { [0] =
0x2212, 0x22C5, 0xD7, 0x2A, 0xF7, 0x22C4, 0xB1, 0x2213,
0x2295, 0x2296, 0x2297, 0x2298, 0x2299, 0x25CB, 0x2218, 0x2219,
0x224D, 0x2261, 0x2286, 0x2287, 0x2264, 0x2265, 0x2AAF, 0x2AB0,
0x223C, 0x2248, 0x2282, 0x2283, 0x226A, 0x226B, 0x227A, 0x227B,
0x2190, 0x2192, 0x2191, 0x2193, 0x2194, 0x2197, 0x2198, 0x2243,
0x21D0, 0x21D2, 0x21D1, 0x21D3, 0x21D4, 0x2196, 0x2199, 0x221D,
0x2032, 0x221E, 0x2208, 0x220B, 0x25B3, 0x25BD, 0x0338, 0x21A6,
0x2200, 0x2203, 0xAC, 0x2205, 0x211C, 0x22A9, 0x22A4, 0x22A5,
0x2135, 0x1D49C, 0x212C, 0x1D49E, 0x1D49F, 0x2130, 0x2131, 0x1D4A2,
0x210B, 0x2110, 0x1D4A5, 0x1D4A6, 0x2112, 0x2133, 0x1D4A9, 0x1D4AA,
0x1D4AB, 0x1D4AC, 0x211B, 0x1D4AE, 0x1D4AF, 0x1D4B0, 0x1D4B1, 0x1D4B2,
0x1D4B3, 0x1D4B4, 0x1D4B5, 0x222A, 0x2229, 0x228E, 0x2227, 0x2228,
0x22A2, 0x22A3, 0x230A, 0x230B, 0x2308, 0x2309, 0x7B, 0x7D,
0x27E8, 0x27E9, 0x7C, 0x2016, 0x2195, 0x21D5, 0x5C, 0x2240,
0x221A, 0x2210, 0x2207, 0x222B, 0x2294, 0x2293, 0x2291, 0x2292,
0xA7, 0x2020, 0x2021, 0xB6, 0x2663, 0x2662, 0x2661, 0x2660,
}
return {
oml = remap_oml,
oms = remap_oms,
}

View File

@ -1,99 +0,0 @@
\ProvidesExplPackage {luamml-patches-amsmath} {2021-04-23} {0.0.1-alpha}
{Feel free to add a description here}
\lua_now:n { require'luamml-amsmath' }
\cs_set:Npn \align@preamble {
&
\hfil
\strut@
\setboxz@h {
\@lign
$
\m@th
\displaystyle {
##
}
\ifmeasuring@
\luamml_flag_ignore:
\else
\luamml_flag_alignment_left:
\fi
$
}
\ifmeasuring@
\savefieldlength@
\fi
\set@field
\tabskip\z@skip
&
\setboxz@h {
\@lign
$
\m@th
\displaystyle
{
{}
\luamml_last_math_alignmark:
##
}
\ifmeasuring@
\luamml_flag_ignore:
\else
\luamml_flag_alignment_right:
\fi
$
}
\ifmeasuring@
\savefieldlength@
\else
\luamml_amsmath_add_box_to_row:
\fi
\set@field
\hfil
\tabskip\alignsep@
}
\cs_set:Npn \math@cr@@@align {
\ifst@rred
\nonumber
\fi
\if@eqnsw
\global \tag@true
\fi
\global \advance \row@ \@ne
\add@amps \maxfields@
\omit
\kern -\alignsep@
\luamml_amsmath_finalize_row:
\iftag@
\setboxz@h {
\@lign
\strut@
{ \make@display@tag }
}
\place@tag
\fi
\ifst@rred
\else
\global \@eqnswtrue
\fi
\global \lineht@ \z@
\cr
}
\cs_set:Npn \endalign {
\math@cr
\black@ \totwidth@
\luamml_amsmath_finalize_table:
\egroup
\ifingather@
\restorealignstate@
\egroup
\nonumber
\ifnum0={\fi\iffalse}\fi
\else
$$
\fi
\ignorespacesafterend
}

View File

@ -1,75 +0,0 @@
local mlist_to_mml = require'luamml-convert'
local process_mlist = mlist_to_mml.process
local make_root = mlist_to_mml.make_root
local register_family = mlist_to_mml.register_family
local mappings = require'luamml-legacy-mappings'
local write_xml = require'luamml-xmlwriter'
local properties = node.get_properties_table()
local funcid = luatexbase.new_luafunction'RegisterFamilyMapping'
token.set_lua('RegisterFamilyMapping', funcid, 'protected')
lua.get_functions_table()[funcid] = function()
local fam = token.scan_int()
local mapping = token.scan_string()
if mappings[mapping] then
register_family(fam, mappings[mapping])
else
tex.error(string.format('Unknown font mapping %q', mapping))
end
end
-- Possible flag values:
-- 0: Normal (This is the only supported one in display mode)
-- 1: Like 0, result is display math
-- 2: Generate MathML, but only save it for later usage in startmath node
-- 3: Skip
-- 4: Prepend node list from buffer before generating
-- 5: Like 5, result is display math
-- 6: 2+4
-- 7: Skip but save copy of node list in buffer
--
-- In other words:
-- Bit 1: Suppress output
-- Bit 0: Force display if 1 isn't set, if it is then skip MathML generation
-- Bit 2: Integrate with table mechanism
local mlist_buffer
luatexbase.add_to_callback('pre_mlist_to_hlist_filter', function(mlist, style)
local flag = tex.count.l__luamml_flag_int
if flag & 3 == 3 then
if flag & 4 == 4 then
assert(mlist_buffer == nil)
mlist_buffer = node.copy_list(mlist)
end
return true
end
local new_mlist, buffer_tail
if flag & 4 == 4 then
new_mlist, buffer_tail = assert(mlist_buffer), node.tail(mlist_buffer)
mlist.prev, buffer_tail.next = buffer_tail, mlist
mlist_buffer = nil
else
new_mlist = mlist
end
local xml = process_mlist(new_mlist, style == 'display' and 0 or 2)
if flag & 2 == 0 then
print(write_xml(make_root(xml, (style == 'display' or flag & 1 == 1) and 0 or 2)) .. '\n')
else
assert(style == 'text')
local startmath = tex.nest.top.tail
local props = properties[startmath]
if not props then
props = {}
properties[startmath] = props
end
props.saved_mathml_table = xml
end
if buffer_tail then
mlist.prev, buffer_tail.next = nil, nil
node.flush_list(new_mlist)
end
return true
end, 'dump_list')

View File

@ -1,17 +0,0 @@
\ProvidesExplPackage {luamml} {2021-04-23} {0.0.1-alpha}
{Feel free to add a description here}
\int_new:N \l__luamml_flag_int
\lua_now:n { require'luamml-tex' }
\cs_new:Nn \luamml_flag_ignore: {
\int_set:Nn \l__luamml_flag_int { 3 }
}
\cs_new:Nn \luamml_flag_alignment_left: {
\int_set:Nn \l__luamml_flag_int { 7 }
}
\cs_new:Nn \luamml_flag_alignment_right: {
\int_set:Nn \l__luamml_flag_int { 6 }
}
\RequirePackage { luamml-patches-amsmath }

View File

@ -1,5 +1,5 @@
local remap_comb = require'luamml-data-combining'
local stretchy = require'luamml-data-stretchy'
local remap_comb = require'remap_comb'
local stretchy = require'stretchy'
local properties = node.get_properties_table()
@ -14,38 +14,18 @@ local noad_sub = node.subtypes'noad'
local radical_sub = node.subtypes'radical'
local fence_sub = node.subtypes'fence'
local remap_lookup = setmetatable({}, {__index = function(t, k)
local ch = utf8.char(k & 0x1FFFFF)
t[k] = ch
return ch
end})
local digit_map = {["0"] = true, ["1"] = true,
["2"] = true, ["3"] = true, ["4"] = true,
["5"] = true, ["6"] = true, ["7"] = true,
["8"] = true, ["9"] = true,}
-- Two marker tables. They are used instead of an embellished operator to mark space-like or user provided constructs
local user_provided, space_like = {}, {}
local nodes_to_table
local function sub_style(s) return s//4*2+5 end
local function sup_style(s) return s//4*2+4+s%2 end
-- The _to_table functions generally return a second argument which is
-- could be (if it were a <mo>) a core operator of the embellishe operator
-- or space_like/user_provided
-- The delim_to_table and acc_to_table are special since their return value should
-- always be considered a core operator
-- We ignore large_... since they aren't used for modern fonts
local function delim_to_table(delim)
if not delim then return end
local props = properties[delim] props = props and props.mathml_table
if props then return props end
local fam = delim.small_fam
local char = remap_lookup[fam << 21 | delim.small_char]
return {[0] = 'mo', char, ['tex:family'] = fam ~= 0 and fam or nil, stretchy = not stretchy[char] or nil }
return {[0] = 'mo', utf8.char(delim.small_char), ['tex:family'] = fam ~= 0 and fam or nil, stretchy = not stretchy[delim.small_char] or nil }
end
-- Like kernel_to_table but always a math_char_t. Also creating a mo and potentially remapping to handle combining chars
@ -56,9 +36,9 @@ local function acc_to_table(acc, cur_style, stretch)
if acc.id ~= math_char_t then
error'confusion'
end
local fam = acc.fam
local char = remap_lookup[fam << 21 | acc.char]
local char = utf8.char(acc.char)
char = remap_comb[char] or char
local fam = acc.fam
if stretch ~= not stretchy[char] then -- Handle nil gracefully in stretchy
stretch = nil
end
@ -68,21 +48,15 @@ end
local function kernel_to_table(kernel, cur_style)
if not kernel then return end
local props = properties[kernel] props = props and props.mathml_table
if props then return props, user_provided end
if props then return props end
local id = kernel.id
if id == math_char_t then
local char = kernel.char
local elem = char >= 0x30 and char < 0x39 and 'mn' or 'mi'
local fam = kernel.fam
local char = remap_lookup[fam << 21 | kernel.char]
local elem = digit_map[char] and 'mn' or 'mi'
local result = {[0] = elem,
char,
['tex:family'] = fam ~= 0 and fam or nil,
mathvariant = #char == 1 and elem == 'mi' and utf8.codepoint(char) < 0x10000 and 'normal' or nil
}
return result, result
return {[0] = elem, utf8.char(char), ['tex:family'] = fam ~= 0 and fam or nil, mathvariant = char < 0x10000 and 'normal' or nil }
elseif id == sub_box_t then
local result = {[0] = 'mi', {[0] = 'mglyph', ['tex:box'] = kernel.list}}
return result, result
return {[0] = 'mi', {[0] = 'mglyph', ['tex:box'] = kernel.list}}
elseif id == sub_mlist_t then
return nodes_to_table(kernel.list, cur_style)
else
@ -90,34 +64,34 @@ local function kernel_to_table(kernel, cur_style)
end
end
local function do_sub_sup(t, core, n, cur_style)
local function do_sub_sup(t, n, cur_style)
local sub = kernel_to_table(n.sub, sub_style(cur_style))
local sup = kernel_to_table(n.sup, sup_style(cur_style))
if sub then
if sup then
return {[0] = 'msubsup', t, sub, sup}, core
return {[0] = 'msubsup', t, sub, sup}
else
return {[0] = 'msub', t, sub}, core
return {[0] = 'msub', t, sub}
end
elseif sup then
return {[0] = 'msup', t, sup}, core
return {[0] = 'msup', t, sup}
else
return t, core
return t
end
end
local function noad_to_table(noad, sub, cur_style)
local class = noad_sub[sub]
local nucleus, core = kernel_to_table(noad.nucleus, class == 'over' and cur_style//2*2+1 or cur_style)
local nucleus = kernel_to_table(noad.nucleus, class == 'over' and cur_style//2*2+1 or cur_style)
if class == 'ord' then
elseif class == 'opdisplaylimits' or class == 'oplimits' or class == 'opnolimits' or class == 'bin' or class == 'rel' or class == 'open'
or class == 'close' or class == 'punct' or class == 'inner' then
if not core or not core[0] then
if nucleus[0] == 'mrow' then
-- TODO
else
core[0] = 'mo'
if stretchy[core[1]] then core.stretchy = false end
if core.mathvariant == 'normal' then core.mathvariant = nil end
nucleus[0] = 'mo'
if stretchy[nucleus[1]] then nucleus.stretchy = false end
if nucleus.mathvariant == 'normal' then nucleus.mathvariant = nil end
end
nucleus['tex:class'] = class
@ -129,35 +103,35 @@ local function noad_to_table(noad, sub, cur_style)
nucleus,
sub or sup,
sub and sup,
}, core
}
end
elseif class == 'under' then
return {[0] = 'munder',
nucleus,
{[0] = 'mo', '_',},
}, core
}
elseif class == 'over' then
return {[0] = 'mover',
nucleus,
{[0] = 'mo', '\u{203E}',},
}, core
}
elseif class == 'vcenter' then
nucleus['tex:TODO'] = class
else
error[[confusion]]
end
return do_sub_sup(nucleus, core, noad, cur_style)
return do_sub_sup(nucleus, noad, cur_style)
end
local function accent_to_table(accent, sub, cur_style)
local nucleus, core = kernel_to_table(accent.nucleus, cur_style//2*2+1)
local nucleus = kernel_to_table(accent.nucleus, cur_style//2*2+1)
local top_acc = acc_to_table(accent.accent, cur_style, sub & 1 == 1)
local bot_acc = acc_to_table(accent.bot_accent, cur_style, sub & 2 == 2)
return {[0] = top_acc and (bot_acc and 'munderover' or 'mover') or 'munder',
nucleus,
bot_acc or top_acc,
bot_acc and top_acc,
}, core
}
end
local style_table = {
@ -174,19 +148,19 @@ style_table.crampedscript, style_table.crampedscriptscript =
local function radical_to_table(radical, sub, cur_style)
local kind = radical_sub[sub]
local nucleus, core = kernel_to_table(radical.nucleus, cur_style//2*2+1)
local nucleus = kernel_to_table(radical.nucleus, cur_style//2*2+1)
local left = delim_to_table(radical.left)
local elem
if kind == 'radical' or kind == 'uradical' then
-- FIXME: Check that this is really a square root
elem, core = {[0] = 'msqrt', nucleus}, nil
elem = {[0] = 'msqrt', nucleus}
elseif kind == 'uroot' then
-- FIXME: Check that this is really a root
elem, core = {[0] = 'msqrt', nucleus, kernel_to_table(radical.degree)}, nil
elem = {[0] = 'msqrt', nucleus, kernel_to_table(radical.degree)}
elseif kind == 'uunderdelimiter' then
elem, core = {[0] = 'munder', left, nucleus}, left
elem = {[0] = 'munder', left, nucleus}
elseif kind == 'uoverdelimiter' then
elem, core = {[0] = 'mover', left, nucleus}, left
elem = {[0] = 'mover', left, nucleus}
elseif kind == 'udelimiterunder' then
elem = {[0] = 'munder', nucleus, left}
elseif kind == 'udelimiterover' then
@ -194,11 +168,11 @@ local function radical_to_table(radical, sub, cur_style)
else
error[[confusion]]
end
return do_sub_sup(elem, core, radical, cur_style)
return do_sub_sup(elem, radical, cur_style)
end
local function fraction_to_table(fraction, sub, cur_style)
local num, core = kernel_to_table(fraction.num, sup_style(cur_style))
local num = kernel_to_table(fraction.num, sup_style(cur_style))
local denom = kernel_to_table(fraction.denom, sub_style(cur_style))
local left = delim_to_table(fraction.left)
local right = delim_to_table(fraction.right)
@ -220,24 +194,23 @@ local function fraction_to_table(fraction, sub, cur_style)
right,
}
else
return mfrac, core
return mfrac
end
end
local function fence_to_table(fence, sub, cur_style)
local delim = delim_to_table(fence.delimiter)
delim.fence = 'true'
return delim, delim
return delim
end
local function space_to_table(amount, sub, cur_style)
if amount == 0 then return end
-- FIXME: What does MathML do in subscripts etc.? Probably we have to "unscale" in the non mu case...
if sub == 99 then -- TODO magic number
-- 18*2^16=1179648
return {[0] = 'mspace', width = string.format("%.2fem", amount/1179648)}, space_like
return {[0] = 'mspace', width = string.format("%.2fem", amount/18)}
else
-- 65781.76=tex.sp'100bp'/100
return {[0] = 'mspace', width = string.format("%.2fpt", amount/65781.76)}, space_like
return {[0] = 'mspace', width = string.format("%.2fem", amount/tex.sp'1em')}
end
end
@ -245,93 +218,64 @@ function nodes_to_table(head, cur_style)
local t = {[0] = "mrow"}
local result = t
local nonscript
local core = space_like
for n, id, sub in node.traverse(head) do
local new_core
local props = properties[n] props = props and props.mathml_table
if props then
t[#t+1], new_core = props, user_provided
t[#t+1] = props
elseif id == noad_t then
t[#t+1], new_core = noad_to_table(n, sub, cur_style)
t[#t+1] = noad_to_table(n, sub, cur_style)
elseif id == accent_t then
t[#t+1], new_core = accent_to_table(n, sub, cur_style)
t[#t+1] = accent_to_table(n, sub, cur_style)
elseif id == style_t then
if sub ~= cur_style then
if #t == 0 then
t[0] = 'mstyle'
else
local new_t = {[0] = 'mstyle'}
t[#t+1] = new_t
t = new_t
end
if sub < 2 then
t.displaystyle, t.scriptlevel = true, 0
else
t.displaystyle, t.scriptlevel = false, sub//2 - 1
end
cur_style = sub
if #t ~= 0 then
local new_t = {[0] = 'mstyle'}
t[#t+1] = new_t
t = new_t
end
new_core = space_like
if sub < 2 then
t.displaystyle, t.scriptlevel = true, 0
else
t.displaystyle, t.scriptlevel = false, sub//2 - 1
end
cur_style = sub
elseif id == choice_t then
local size = cur_style//2
t[#t+1], new_core = nodes_to_table(n[size == 0 and 'display'
or size == 1 and 'text'
or size == 2 and 'script'
or size == 3 and 'scriptscript'
or assert(false)], 2*size), space_like
t[#t+1] = nodes_to_table(n[size == 0 and 'display' or size == 1 and 'text'
or size == 2 and 'script'
or size == 3 and 'scriptscript' or assert(false)], 2*size)
elseif id == radical_t then
t[#t+1], new_core = radical_to_table(n, sub, cur_style)
t[#t+1] = radical_to_table(n, sub, cur_style)
elseif id == fraction_t then
t[#t+1], new_core = fraction_to_table(n, sub, cur_style)
t[#t+1] = fraction_to_table(n, sub, cur_style)
elseif id == fence_t then
t[#t+1], new_core = fence_to_table(n, sub, cur_style)
t[#t+1] = fence_to_table(n, sub, cur_style)
elseif id == kern_t then
if not nonscript then
t[#t+1], new_core = space_to_table(n.kern, sub, cur_style)
t[#t+1] = space_to_table(n.kern, sub, cur_style)
end
elseif id == glue_t then
if cur_style >= 4 or not nonscript then
if sub == 98 then -- TODO magic number
nonscript = true
else
t[#t+1], new_core = space_to_table(n.width, sub, cur_style)
t[#t+1] = space_to_table(n.width, sub, cur_style)
end
end
else
new_core = {[0] = 'tex:TODO', other = n}
t[#t+1] = new_core
t[#t+1] = {[0] = 'tex:TODO', other = n}
end
nonscript = nil
if core and new_core ~= space_like then
core = new_core
end
end
return result, core
return result
end
local function register_remap(family, mapping)
family = family << 21
for from, to in next, mapping do
remap_lookup[family | from] = utf8.char(to)
return function(head, style)
local result = nodes_to_table(head, style or 0)
result[0] = 'math'
result.xmlns = 'http://www.w3.org/1998/Math/MathML'
result['xmlns:tex'] = 'http://typesetting.eu/2021/LuaMathML'
if style == 2 then
result.display = 'block'
end
return result
end
local function to_math(root, style)
if root[0] == 'mrow' then
root[0] = 'math'
else
root = {[0] = 'math', root}
end
root.xmlns = 'http://www.w3.org/1998/Math/MathML'
root['xmlns:tex'] = 'http://typesetting.eu/2021/LuaMathML'
if style < 2 then
root.display = 'block'
end
return root
end
return {
register_family = register_remap,
process = function(head, style) return nodes_to_table(head, style or 2) end,
make_root = to_math,
}

14
test_tex.lua Normal file
View File

@ -0,0 +1,14 @@
local inspect = require'inspect'
local function show(t) return print(inspect(t)) end
local mlist_to_table = require'mlist_to_mml'
local write_xml = require'write_xml'
luatexbase.add_to_callback('pre_mlist_to_hlist_filter', function(mlist, style)
print'\n\n'
local xml = mlist_to_table(mlist, style == 'display' and 2 or 0)
print(write_xml(xml))
-- print(write_xml(xml, '\n'))
print'\n'
return true
end, 'dump_list')

View File

@ -1,12 +1,9 @@
\documentclass{article}
\usepackage{unicode-math}
\usepackage{amsmath}
\usepackage{luamml}
\RegisterFamilyMapping\symsymbols{oms}
\RegisterFamilyMapping\symletters{oml}
\directlua{require'test_tex'}
\begin{document}
\[
ax^2+bx+c=0
ax^2+b+c=0
\]
\[
x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}.
@ -15,11 +12,5 @@
\sum_a\underline c\dot bc'
\]
\begin{align}
abc&=def\\
1+2&=3\\
5
\end{align}
Es gilt $\sin(x)-\sin(x+2\pi)=0$.
\end{document}

16
test_xml.lua Normal file
View File

@ -0,0 +1,16 @@
local write_xml = require'write_xml'
print(write_xml{[0] = "math", xmlns = "http://www.w3.org/1998/Math/MathML",
{[0] = "mi", "a"},
{[0] = "msup",
{[0] = "mi", "x"},
{[0] = "mn", "2"},
},
{[0] = "mo", "+"},
{[0] = "mi", "b"},
{[0] = "mi", "x"},
{[0] = "mo", "+"},
{[0] = "mi", "c"},
{[0] = "mo", "="},
{[0] = "mn", "0"},
})

View File

@ -3,6 +3,7 @@ local function escape_name(name)
return name
end
-- FIXME: Not sure yet if this will be needed
local escapes = {
['"'] = "&quot;",
['<'] = "&lt;",
@ -40,7 +41,4 @@ local function write_elem(tree, indent)
return out .. '</' .. escaped_name .. '>'
end
return function(element, indent, version)
return (version == '11' and '<?xml version="1.1"?>' or '') ..
write_elem(element, indent and '' or nil)
end
return write_elem