From 23c6714e97354255991075f89cb8e5010f405c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Fabian=20Kr=C3=BCger?= Date: Sat, 24 Apr 2021 16:53:50 +0200 Subject: [PATCH] align support and fixes --- luamml-amsmath.lua | 84 ++++++++++++++++++++++++++++++++ luamml-convert.lua | 48 ++++++++++-------- luamml-patches-amsmath.sty | 99 ++++++++++++++++++++++++++++++++++++++ luamml-tex.lua | 57 ++++++++++++++++++++-- luamml.sty | 17 +++++++ test_tex.tex | 13 +++-- 6 files changed, 291 insertions(+), 27 deletions(-) create mode 100644 luamml-amsmath.lua create mode 100644 luamml-patches-amsmath.sty create mode 100644 luamml.sty diff --git a/luamml-amsmath.lua b/luamml-amsmath.lua new file mode 100644 index 0000000..c03fb35 --- /dev/null +++ b/luamml-amsmath.lua @@ -0,0 +1,84 @@ +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 diff --git a/luamml-convert.lua b/luamml-convert.lua index c1d8458..c7b312c 100644 --- a/luamml-convert.lua +++ b/luamml-convert.lua @@ -77,7 +77,7 @@ local function kernel_to_table(kernel, cur_style) local result = {[0] = elem, char, ['tex:family'] = fam ~= 0 and fam or nil, - mathvariant = #char == 1 and utf8.codepoint(char) < 0x10000 and 'normal' or nil + mathvariant = #char == 1 and elem == 'mi' and utf8.codepoint(char) < 0x10000 and 'normal' or nil } return result, result elseif id == sub_box_t then @@ -256,17 +256,21 @@ function nodes_to_table(head, cur_style) elseif id == accent_t then t[#t+1], new_core = accent_to_table(n, sub, cur_style) elseif id == style_t then - if #t ~= 0 then - local new_t = {[0] = 'mstyle'} - t[#t+1] = new_t - t = new_t + 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 end - if sub < 2 then - t.displaystyle, t.scriptlevel = true, 0 - else - t.displaystyle, t.scriptlevel = false, sub//2 - 1 - end - cur_style = sub new_core = space_like elseif id == choice_t then local size = cur_style//2 @@ -312,18 +316,22 @@ local function register_remap(family, mapping) end end -local function to_mml(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' +local function to_math(root, style) + if root[0] == 'mrow' then + root[0] = 'math' + else + root = {[0] = 'math', root} end - return result + 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 = to_mml, + process = function(head, style) return nodes_to_table(head, style or 2) end, + make_root = to_math, } diff --git a/luamml-patches-amsmath.sty b/luamml-patches-amsmath.sty new file mode 100644 index 0000000..15565fe --- /dev/null +++ b/luamml-patches-amsmath.sty @@ -0,0 +1,99 @@ +\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 +} diff --git a/luamml-tex.lua b/luamml-tex.lua index 3b77139..ad9c176 100644 --- a/luamml-tex.lua +++ b/luamml-tex.lua @@ -1,10 +1,13 @@ 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() @@ -17,10 +20,56 @@ lua.get_functions_table()[funcid] = function() 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) - print'' - local xml = process_mlist(mlist, style == 'display' and 2 or 0) - print(write_xml(xml)) - print'' + 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') diff --git a/luamml.sty b/luamml.sty new file mode 100644 index 0000000..f95c505 --- /dev/null +++ b/luamml.sty @@ -0,0 +1,17 @@ +\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 } diff --git a/test_tex.tex b/test_tex.tex index af6dd48..b4bc7ca 100644 --- a/test_tex.tex +++ b/test_tex.tex @@ -1,11 +1,12 @@ \documentclass{article} -% \usepackage{unicode-math} -\directlua{require'luamml-tex'} +\usepackage{unicode-math} +\usepackage{amsmath} +\usepackage{luamml} \RegisterFamilyMapping\symsymbols{oms} \RegisterFamilyMapping\symletters{oml} \begin{document} \[ - ax^2+b+c=0 + ax^2+bx+c=0 \] \[ x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}. @@ -14,5 +15,11 @@ \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}