diff options
Diffstat (limited to 'Master/texmf-dist/tex/context/base/mkxl/back-exp-imp-mth.lmt')
-rw-r--r-- | Master/texmf-dist/tex/context/base/mkxl/back-exp-imp-mth.lmt | 883 |
1 files changed, 570 insertions, 313 deletions
diff --git a/Master/texmf-dist/tex/context/base/mkxl/back-exp-imp-mth.lmt b/Master/texmf-dist/tex/context/base/mkxl/back-exp-imp-mth.lmt index 4df109b54f5..8357ad7d5fe 100644 --- a/Master/texmf-dist/tex/context/base/mkxl/back-exp-imp-mth.lmt +++ b/Master/texmf-dist/tex/context/base/mkxl/back-exp-imp-mth.lmt @@ -8,6 +8,7 @@ if not modules then modules = { } end modules ['back-exp-imp-mth'] = { local sub = string.sub local utfchar, utfvalues = utf.char, utf.values +local insert = table.insert local setmetatableindex, concat = table.setmetatableindex, table.concat local structurestags = structures.tags @@ -29,12 +30,14 @@ local implement = interfaces.implement do - local automathrows = true directives.register("export.math.autorows", function(v) automathrows = v end) - local automathapply = true directives.register("export.math.autoapply", function(v) automathapply = v end) - local automathnumber = true directives.register("export.math.autonumber", function(v) automathnumber = v end) + ----- automathrows = true directives.register("export.math.autorows", function(v) automathrows = v end) + ----- automathapply = true directives.register("export.math.autoapply", function(v) automathapply = v end) + ----- automathnumber = true directives.register("export.math.autonumber", function(v) automathnumber = v end) local automathstrip = true directives.register("export.math.autostrip", function(v) automathstrip = v end) local functions = mathematics.categories.functions + local tagging = mathematics.tagging + local functiontype = mathematics.functiontype local function collapse(di,i,data,ndata,detail,element) local collapsing = di.data @@ -56,48 +59,89 @@ do return i end - local function collapse_mn(di,i,data,ndata) - -- this is tricky ... we need to make sure that we wrap in mrows if we want - -- to bypass this one - local collapsing = di.data - if data then - i = i + 1 - while i <= ndata do - local dn = data[i] - local tg = dn.tg - if tg == "mn" then - collapsing[#collapsing+1] = dn.data[1] - dn.skip = "ignore" - i = i + 1 - elseif tg == "mo" then - local d = dn.data[1] - if d == "." then - collapsing[#collapsing+1] = d - dn.skip = "ignore" - i = i + 1 + local function collapse_all_mn(data) + local n = #data + local f = false + local l = false + local d = false + local p = false + for i=1,n do + local di = data[i] + local tg = di.tg + if tg == "mn" then + if not f then + d = di.data + f = i + p = false + else + if p then + p.element = "mn" + local s = specifications[p.fulltag] + s.mathcharacter = nil + s.mathclass = nil + s.mathgroup = nil + s.mathindex = nil + end + d[#d+1] = di.data[1] + data[i] = false + p = false + end + l = i + elseif tg == "mi" or tg == "mc" then + if p then + f = false + end + if i < n and data[i+1].tg == "mn" then + local d1 = di.data[1] + if d1 then + local c = d1.content + local s = specifications[di.fulltag] + if s.mathclass == "ordinary" and c and (c == "." or c == ",") then + if not f then + d = di.data + f = i + l = i + p = di + else + d[#d+1] = d1 + data[i] = false + end + else + f = false + end else - break + f = false end else - break + f = false + end + elseif f and (tg == "msub" or tg == "msup" or tg == "msubsup") then + local d1 = di.data[1] + if d1 and d1.tg == "mn" then + d[#d+1] = d1.data[1] + d1.data = d + data[f] = false end + f = false + else + f = false + end + end + if d then + local j = 0 + for i=1,n do + local d = data[i] + if d then + j = j + 1 + data[j] = d + end + end + for i=j+1,n do + data[i] = nil end end - return i end - -- maybe delay __i__ till we need it - - local apply_function = { - { - element = "mo", - -- comment = "apply function", - -- data = { utfchar(0x2061) }, - data = { "⁡" }, - nature = "mixed", - } - } - local functioncontent = { } setmetatableindex(functioncontent,function(t,k) @@ -109,59 +153,114 @@ do local dummy_nucleus = { element = "mtext", data = { content = "" }, - nature = "inline", + nature = "mixed", comment = "dummy nucleus", fulltag = "mtext>0" } - local function accentchar(d) - for i=1,3 do - d = d.data - if not d then - return + local function accentchar(d) -- see mkiv for old one + local detail = tonumber(d.detail) + if detail then + local d1 = d.data[1] + if d1 and d1.tg == "mrow" then + -- + d.element = "mrow" -- used + d.detail = nil + local s = specifications[d.fulltag] -- hm, used when not set + s.detail = nil + -- + d1.element = "mo" -- used + -- d1.detail = nil + d1.nature = "mixed" + d1.data = { { content = utfchar(detail) } } + return d end - d = d[1] - if not d then - return + end + end + + local no_mrow = { + mrow = true, + mfenced = true, + mfrac = true, + mroot = true, + msqrt = true, + mtable = true, + mi = true, + mo = true, + mn = true, + mspace = true, + mtext = true, + -- mmultiscripts = true, + -- mstacker = true, + -- mextensible = true, + } + + -- we could make a stupid xml and then just use lpath to clean it up + + -- local separator <const> = utfchar(0x2061) + + -- local function markapplicationof(di,data,i) + -- if i > 1 then + -- local d0 = data[i-1] + -- local at = d0.attributes + -- if at then + -- at.mathapplication = true + -- else + -- d0.attributes = { + -- mathapplication = true, + -- } + -- end + -- end + -- -- di.tg = "ignore" + -- -- di.skip = "ignore" + -- end + + local function checked(d,n) + if n == 1 then + local di = d[1] + local tg = di.tg + if tg == "ignore" then + -- todo: we can move ignore's data one level up + return 1 + elseif di.content then + return 1 + else + local dd = di.data + local nn = #dd + if nn > 0 and checked(dd,nn) > 0 then + return 1 + else + return 0 + end end - local tg = d.tg - if tg == "mover" then - local s = specifications[d.fulltag] - local t = s.top - if t then - d = d.data[1] - local d1 = d.data[1] - d1.content = utfchar(t) - d.data = { d1 } - return d + else + local m = 0 + for i=1,n do + local di = d[i] + local tg = di.tg + if tg == "ignore" then + -- skip + elseif di.content then + m = m + 1 + d[m] = di + else + local dd = di.data + local nn = #dd + if nn > 0 and checked(dd,nn) > 0 then + m = m + 1 + d[m] = di + end end - elseif tg == "munder" then - local s = specifications[d.fulltag] - local b = s.bottom - if b then - d = d.data[1] - local d1 = d.data[1] - d1.content = utfchar(b) - d.data = { d1 } - return d + end + if m < n then + for i=n,m+1,-1 do + d[i] = nil end end + return m end end - local no_mrow = { - mrow = true, - mfenced = true, - mfrac = true, - mroot = true, - msqrt = true, - mtable = true, - mi = true, - mo = true, - mn = true, - mspace = true, - } - local function checkmath(root) -- we can provide utf.toentities as an option local data = root.data if data then @@ -169,61 +268,27 @@ do local roottg = root.tg if roottg == "mo" then local s = specifications[root.fulltag] - local c = s.class - if c == "open" or c == "close" or c == "middle" then + -- maybe just via metatable + if s.mathgroup then root.attributes = { - maxsize = 1 + mathclass = s.mathclass, + mathgroup = s.mathgroup, + mathindex = s.mathindex, + mathcharacter = s.mathcharacter, + mathstack = s.mathstack, } - end - elseif roottg == "msubsup" then - -- kind of tricky: we have a different order in display mode - local nucleus, superscript, subscript - if ndata > 3 then - -- error else - for i=1,ndata do - local di = data[i] - if not di then - -- weird - elseif di.content then - -- text - else - local s = specifications[di.fulltag] - if s.subscript then - subscript = i - elseif s.superscript then - superscript = i - else - nucleus = i - end - end - end - if superscript or subscript then - -- we probably always have 3 anyway ... needs checking - local nuc = nucleus and data[nucleus] - local sub = subscript and data[subscript] - local sup = superscript and data[superscript] - local n = 0 -- play safe - if nuc then n = n + 1 ; data[n] = nuc end - if sub then n = n + 1 ; data[n] = sub end - if sup then n = n + 1 ; data[n] = sup end - end + root.attributes = { + mathstack = s.mathstack, + } end - -- elseif roottg == "msup" or roottg == "msub" then - -- -- m$^2$ - -- if ndata == 1 then - -- local d = data[1] - -- data[2] = d - -- d.__i__ = 2 - -- data[1] = dummy_nucleus - -- end elseif roottg == "mfenced" then local s = specifications[root.fulltag] local o = s.operator if o then root.skip = "comment" -- root.content = utfchar(o) -- use embedded for now - else + elseif tagging.mfenced then local l = s.left local m = s.middle local r = s.right @@ -245,7 +310,15 @@ do separators = m, close = r, } + else + root.element = "mrow" + root.attributes = { + mathcategory = s.mathcategory + } end + -- elseif roottg == "mstacker" then + elseif roottg == "mrow" then +ndata = checked(data,ndata) end if ndata == 0 then root.skip = "comment" -- get rid of weird artefacts @@ -258,21 +331,38 @@ do return elseif d.content then return - else -- if ndata == 1 then - local tg = d.tg - if automathrows and (roottg == "mrow" or roottg == "mtext") then - -- maybe just always ! check spec first - -- or we can have checks.* for each as we then can flatten - if no_mrow[tg] then - root.skip = "comment" - end - elseif roottg == "mo" then - if tg == "mo" then - root.skip = "comment" - end + elseif roottg == "mrow" or roottg == "mtext" then + -- maybe just always ! check spec first + -- or we can have checks.* for each as we then can flatten + local s = specifications[root.fulltag] + if s.mathunit then + d.attributes = { + mathunit = s.mathunit + } + elseif s.mathdigits then + d.attributes = { + mathdigits = s.mathdigits + } + elseif s.mathfunction then + d.attributes = { + mathfunction = s.mathfunction, + mathcategory = s.mathcategory, + mathstack = s.mathstack, + } + elseif no_mrow[d.tg] then + root.skip = "comment" + else + d.attributes = { + mathstack = s.mathstack, + } + end + elseif roottg == "mo" then + if d.tg == "mo" then + root.skip = "comment" end end end + -- todo local i = 1 while i <= ndata do -- -- -- TOO MUCH NESTED CHECKING -- -- -- local di = data[i] @@ -290,12 +380,13 @@ do local d = di.data -- todo: accent = "false" (for scripts like limits) di.attributes = { - accent = "true", + accent = "true", + mathcategory = s.mathcategory, } -- todo: p.topfixed if t then -- mover - if true then -- we don't go here any more + if true then local dd = d[1].data if dd then dd[1].content = utfchar(t) @@ -316,12 +407,13 @@ do local d = di.data -- todo: accent = "false" (for scripts like limits) di.attributes = { - accent = "true", + accent = "true", + mathcategory = s.mathcategory, } -- todo: p.bottomfixed if b then -- munder - if true then -- we don't go here any more + if true then local dd = d[2].data if dd then dd[1].content = utfchar(b) @@ -474,82 +566,105 @@ do end checkmath(di) i = i + 1 - elseif tg == "mrow" and detail then -- hm, falls through - di.detail = nil - checkmath(di) - di = { - element = "maction", - nature = "display", - attributes = { actiontype = detail }, - data = { di }, - n = 0, - } - data[i] = di - i = i + 1 - else - local category = di.mathcategory - if category then - -- no checkmath(di) here - if category == 1 then -- mo - i = collapse(di,i,data,ndata,detail,"mo") - elseif category == 2 then -- mi - i = collapse(di,i,data,ndata,detail,"mi") - elseif category == 3 then -- mn - i = collapse(di,i,data,ndata,detail,"mn") - elseif category == 4 then -- ms - i = collapse(di,i,data,ndata,detail,"ms") - elseif category >= 1000 then - local apply = category >= 2000 - if apply then - category = category - 1000 - end - if tg == "mi" then -- function - if roottg == "mrow" then - root.skip = "comment" - root.element = "function" - end - i = collapse(di,i,data,ndata,detail,"mi") - local tag = functions[category] - if tag then - di.data = functioncontent[tag] - end - if apply then - di.after = apply_function - elseif automathapply then -- make function - local following - if i <= ndata then - -- normally not the case - following = data[i] - else - local parent = di.__p__ -- == root - if parent.tg == "mrow" then - parent = parent.__p__ - end - local index = parent.__i__ - following = parent.data[index+1] - end - if following then - local tg = following.tg - if tg == "mrow" or tg == "mfenced" then -- we need to figure out the right condition - di.after = apply_function - end - end - end - else -- some problem - checkmath(di) - i = i + 1 - end + elseif tg == "mi" then + local s = specifications[di.fulltag] + if s.mathclass == "punctuation" then + di.element = "mtext" + checkmath(di) + i = i + 1 + else + -- if di.data[1].content == separator then + -- markapplicationof(di,data,i) + -- end + local category = s.mathcategory + if s.mathgroup then + di.attributes = { + mathclass = s.mathclass, + mathgroup = s.mathgroup, + mathindex = s.mathindex, + mathcharacter = s.mathcharacter, + mathstack = s.mathstack, + } else - checkmath(di) - i = i + 1 + di.attributes = { + mathstack = s.mathstack, + } end - elseif automathnumber and tg == "mn" then checkmath(di) - i = collapse_mn(di,i,data,ndata) + i = i + 1 + end + elseif tg == "mrow" then + local d = di.data + local n = #d + local s = specifications[di.fulltag] + if s.mathunit then + di.attributes = { mathunit = s.mathunit } + elseif s.mathdigits then + for i=1,n do + d[i] = d[i].data[1].content or "" + end + di.tg = "mn" + di.element = "mn" + di.nature = "mixed" + di.data = { { content = concat(d) } } + elseif s.mathfunction then + di.attributes = { + mathfunction = s.mathfunction, + mathstack = s.mathstack + } + local category = tonumber(s.mathcategory) + if functiontype(category) == "function" then + local fnc = functions[category] -- functions[s.mathfunction] + local tag = fnc and fnc.tag + if tag then + di.tg = "mi" + di.element = "mi" + di.nature = "mixed" + di.data = functioncontent[tag] + end + end + i = i + 1 + elseif s.mathfunctionstack then + di.attributes = { + mathfunction = s.mathfunction, + mathstack = s.mathstack, + mathfunctionstack = s.mathfunctionstack, + } + checkmath(di) + i = i + 1 + -- maybe fall through + elseif s.mathfractionstack then + di.attributes = { + mathfractionstack = s.mathfractionstack, + } + checkmath(di) + i = i + 1 + -- maybe fall through else + if n > 0 then + local d1 = d[1] + local tg = d1.tg + if tg == "mfrac" then + if n == 1 then -- simple one + di = d1 + data[i] = di + elseif n == 2 and d[2].tg == "ignore" then -- simple one with nilled middle fence + -- already wiped anyway + di = d1 + data[i] = di + end +-- elseif tg == "mo" then +-- if i > 1 and d1.data[1].content == separator then +-- markapplicationof(di,data,i) +-- end + end + end checkmath(di) i = i + 1 end + else + checkmath(di) + i = i + 1 end else -- can be string or boolean if parenttg ~= "mtext" and di == " " then @@ -583,52 +698,33 @@ do end if d then local content = d.content +-- if d.tg == "mspace" then +-- n = n + 1 +-- data[n] = d +-- d.data = { } +-- elseif not content then +-- n = n + 1 +-- data[n] = d +-- d.__i__ = n -- hm +-- else +-- n = n + 1 +-- data[n] = d +-- end + n = n + 1 + data[n] = d if d.tg == "mspace" then - n = n + 1 - data[n] = d d.data = { } elseif not content then --- if not content then - n = n + 1 - d.__i__ = n - data[n] = d --- elseif content == " " or content == "" then --- if d.tg == "mspace" then --- -- we append or prepend a space to a preceding or following mtext --- local parent = di.__p__ --- local index = di.__i__ -- == i --- local data = parent.data --- if index > 1 then --- local d = data[index-1] --- if d.tg == "mtext" then --- local dd = d.data --- local dn = dd[#dd] --- local dc = dn.content --- if dc then --- dn.content = dc .. content --- end --- end --- elseif index < ndata then --- local d = data[index+1] --- if d.tg == "mtext" then --- local dd = d.data --- local dn = dd[1] --- local dc = dn.content --- if dc then --- dn.content = content .. dc --- end --- end --- end --- end - else - n = n + 1 - data[n] = d + d.__i__ = n -- hm end end end for i=ndata,n+1,-1 do data[i] = nil end + -- maybe integrate the above and this one: + collapse_all_mn(data) + -- if #data > 0 then return di end @@ -642,14 +738,19 @@ do -- issue that i need to look into else local specification = specifications[di.fulltag] - local mode = specification and specification.mode == "display" and "block" or "inline" + local mode = specification.mode == "display" and "block" or "inline" + local domain = specification.domain or "default" di.attributes = { ["display"] = mode, + ["domain"] = domain, + ["alttext"] = specification.input, -- bonus ["xmlns:m"] = mathmlns, ["xmlns:math"] = mathmlns, } -- can be option if needed: - if mode == "inline" then + if specification.standalone then + di.nature = "display" + elseif mode == "inline" then -- di.nature = "mixed" -- else spacing problem (maybe inline) di.nature = "inline" -- we need to catch x$X$x and x $X$ x else @@ -664,58 +765,169 @@ do -- this one can replace some of the previous code .. todo (test on mathmatrix) - -- ignore with no data can be removed + local mprescripts = { + element = "mprescripts", + data = { content = "" }, + nature = "inline", -- mixed + fulltag = "mprescripts>0" + } - local function checked(d) - local n = #d - if n == 1 then - local di = d[1] - local tg = di.tg - if tg == "ignore" then - -- todo: we can move ignore's data one level up - return 1 - elseif di.content then - return 1 - else - local dd = di.data - if #dd > 0 and checked(dd) > 0 then - return 1 - else - return 0 - end + local function wrapup(d,index,n,prelist,kernel,postlist) + local di = d[index] + local post = #postlist + local pre = #prelist + local list = { kernel } + local size = 1 + for i=index+1,n do + d[i].skip = "ignore" + end + if post > 0 then + for i=1,post do + size = size + 1 ; list[size] = postlist[i] end - else - local m = 0 - for i=1,n do + end + if pre > 0 then + size = size + 1 ; list[size] = mprescripts + for i=1,pre do + size = size + 1 ; list[size] = prelist[i] + end + end + di.element = "mmultiscripts" + -- di.tg = "mmultiscripts" + di.data = list + di.iscontinuation = true + di.__i__ = size + end + + local function found(d,what) + if what then + for i=1,#d do local di = d[i] - local tg = di.tg - if tg == "ignore" then - -- skip - elseif di.content then - m = m + 1 - d[m] = di - else - local dd = di.data - if #dd > 0 and checked(dd) > 0 then - m = m + 1 - d[m] = di - end + local sp = specifications[di.fulltag] + if sp and sp.script == what then + return di end end - if m < n then - for i=n,m+1,-1 do - d[i] = nil + else + for i=1,#d do + local di = d[i] + local sp = specifications[di.fulltag] + if not sp or not sp.script then + return di end end - return m end end + -- todo: pick up kernel + function checks.mrow(di) - -- local d = di.data - -- if d then - -- checked(d) - -- end + local d = di.data + if d then + local postlist = nil + local prelist = nil + local kernel = nil + local index = 0 + for i=1,#d do + local di = d[i] + local data = di.data + local tg = di and di.tg + local sp = specifications[di.fulltag] + local continuation = sp and sp.continuation + if continuation then + -- head kernel next + if postlist and continuation.head then + wrapup(d,index,#d,prelist,kernel,postlist) + postlist = nil + prelist = nil + kernel = 0 + end + -- play safe as we can have empty ones (so maybe move the extra code here) + local nd = #data + if tg == "msup" then + if not postlist then + index = i + postlist = { } + prelist = { } + kernel = dummy_nucleus + end + local sup = found(data,"sup") + postlist[#postlist+1] = dummy_nucleus + postlist[#postlist+1] = sup + if continuation.kernel then + kernel = data[1] or dummy_nucleus + end + elseif tg == "msub" then + if not postlist then + index = i + postlist = { } + prelist = { } + kernel = dummy_nucleus + end + local sub = found(data,"sub") + postlist[#postlist+1] = sub + postlist[#postlist+1] = dummy_nucleus + if continuation.kernel then + kernel = data[1] or dummy_nucleus + end + elseif tg == "msubsup" then + if not postlist then + index = i + postlist = { } + prelist = { } + kernel = dummy_nucleus + end + local sub = found(data,"sub") + local sup = found(data,"sup") + postlist[#postlist+1] = sub or dummy_nucleus + postlist[#postlist+1] = sup or dummy_nucleus + if continuation.kernel then + kernel = data[1] or dummy_nucleus + end + elseif tg == "mmultiscripts" then + -- we know that we only have one set + if not postlist then + index = i + postlist = { } + prelist = { } + kernel = dummy_nucleus + end + local prime = found(data,"prime") + local sub = found(data,"sub") + local sup = found(data,"sup") + local presub = found(data,"presub") + local presup = found(data,"presup") + if prime then + postlist[#postlist+1] = dummy_nucleus + postlist[#postlist+1] = prime + end + if sub or sup then + postlist[#postlist+1] = sub or dummy_nucleus + postlist[#postlist+1] = sup or dummy_nucleus + end + if presub or presup then + prelist[#prelist+1] = presub or dummy_nucleus + prelist[#prelist+1] = presup or dummy_nucleus + end + if continuation.kernel then + kernel = data[1] or dummy_nucleus + end + else + postlist = nil + prelist = nil + kernel = nil + end + elseif postlist then + wrapup(d,index,i-1,prelist,kernel,postlist) + postlist = nil + prelist = nil + kernel = nil + end + end + if postlist then + wrapup(d,index,#d,prelist,kernel,postlist) + end + end end -- we can move more checks here @@ -726,7 +938,7 @@ do local d = r.data local n = #d if d and n > 1 then - n = checked(d) + n = checked(d,n) end local tg = r.tg if n == 1 and (tg == "mtext" or tg == "mrow") then @@ -763,39 +975,84 @@ do end end - do - - local a, z, A, Z = 0x61, 0x7A, 0x41, 0x5A - - function extras.mi(di,element,n,fulltag) -- check with content - local str = di.data[1].content - if str and sub(str,1,1) ~= "&" then -- hack but good enough (maybe gsub op eerste) - for v in utfvalues(str) do - if (v >= a and v <= z) or (v >= A and v <= Z) then - local a = di.attributes - if a then - a.mathvariant = "normal" - else - di.attributes = { mathvariant = "normal" } - end - end - end + function extras.mmultiscripts(di,element,n,fulltag) + if not di.iscontinuation then + local d = di.data + local sup = found(d,"sup") + local sub = found(d,"sub") + local presup = found(d,"presup") + local presub = found(d,"presub") + local prime = found(d,"prime") + local n = 1 + if sup or sub then + n = n + 1 ; d[n] = sub or dummy_nucleus + n = n + 1 ; d[n] = sup or dummy_nucleus + end + if prime then + n = n + 1 ; d[n] = dummy_nucleus + n = n + 1 ; d[n] = prime end + if presup or presub then + n = n + 1 ; d[n] = mprescripts + n = n + 1 ; d[n] = presub or dummy_nucleus + n = n + 1 ; d[n] = presup or dummy_nucleus + end + d.__i__ = n end - end function extras.msub(di,element,n,fulltag) - -- m$^2$ local data = di.data if #data == 1 then - local d = data[1] - data[2] = d - d.__i__ = 2 - data[1] = dummy_nucleus + insert(data,1,dummy_nucleus) + data.__i__ = 2 + end + local sp = specifications[di.fulltag] + if attributes then + attributes.mathsubindex = sp.subshifted + else + di.attributes = { + mathsubindex = sp.subshifted, + } end end - extras.msup = extras.msub + function extras.msup(di,element,n,fulltag) + local data = di.data + if #data == 1 then + insert(data,1,dummy_nucleus) + data.__i__ = 2 + end + local sp = specifications[di.fulltag] + local attributes = di.attributes + if attributes then + attributes.mathsupindex = sp.supshifted + else + di.attributes = { + mathsupindex = sp.supshifted, + } + end + end + + function extras.msubsup(di,element,n,fulltag) + local data = di.data + local nuc = found(data) + local sup = found(data,"sup") + local sub = found(data,"sub") + data[1] = nuc or dummy_nucleus + data[2] = sub or dummy_nucleus + data[3] = sup or dummy_nucleus + data.__i__ = 3 + local sp = specifications[di.fulltag] + if attributes then + attributes.mathsupindex = sp.supshifted + attributes.mathsubindex = sp.subshifted + else + di.attributes = { + mathsupindex = sp.supshifted, + mathsubindex = sp.subshifted, + } + end + end end |