1if not modules then modules = { } end modules ['back-exp-imp-mth'] = {
2 version = 1.001,
3 comment = "companion to back-exp.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local sub, gsub = string.sub, string.gsub
10local utfchar, utfvalues = utf.char, utf.values
11local insert = table.insert
12local setmetatableindex, concat = table.setmetatableindex, table.concat
13
14local structurestags = structures.tags
15local specifications = structurestags.specifications
16local locatedtag = structurestags.locatedtag
17
18local backend = structurestags.backend
19
20local setattribute = backend.setattribute
21local extras = backend.extras
22local checks = backend.checks
23local finalizers = backend.finalizers
24
25
26
27local f_em = string.formatters["%.6Nem"]
28
29local implement = interfaces.implement
30
31local mathmlns <const> = "http://www.w3.org/1998/Math/MathML"
32
33do
34
35
36
37
38 local automathstrip = true directives.register("export.math.autostrip", function(v) automathstrip = v end)
39
40 local functions = mathematics.categories.functions
41 local tagging = mathematics.tagging
42 local functiontype = mathematics.functiontype
43
44 local function collapse(di,i,data,ndata,detail,element)
45 local collapsing = di.data
46 if data then
47 di.element = element
48 di.detail = nil
49 i = i + 1
50 while i <= ndata do
51 local dn = data[i]
52 if dn.detail == detail then
53 collapsing[#collapsing+1] = dn.data[1]
54 dn.skip = "ignore"
55 i = i + 1
56 else
57 break
58 end
59 end
60 end
61 return i
62 end
63
64 local function collapse_all_mn(data)
65 local n = #data
66 local f = false
67 local l = false
68 local d = false
69 local p = false
70 for i=1,n do
71 local di = data[i]
72 local tg = di.tg
73 if tg == "mn" then
74 if not f then
75 d = di.data
76 f = i
77 p = false
78 else
79 if p then
80 p.element = "mn"
81 local s = specifications[p.fulltag]
82 s.mathcharacter = nil
83 s.mathclass = nil
84 s.mathgroup = nil
85 s.mathindex = nil
86 end
87 d[#d+1] = di.data[1]
88 data[i] = false
89 p = false
90 end
91 l = i
92 elseif tg == "mi" or tg == "mc" then
93 if p then
94 f = false
95 end
96 if i < n and data[i+1].tg == "mn" then
97 local d1 = di.data[1]
98 if d1 then
99 local c = d1.content
100 local s = specifications[di.fulltag]
101 if s.mathclass == "ordinary" and c and (c == "." or c == ",") then
102 if not f then
103 d = di.data
104 f = i
105 l = i
106 p = di
107 else
108 d[#d+1] = d1
109 data[i] = false
110 end
111 else
112 f = false
113 end
114 else
115 f = false
116 end
117 else
118 f = false
119 end
120 elseif f and (tg == "msub" or tg == "msup" or tg == "msubsup") then
121 local d1 = di.data[1]
122 if d1 and d1.tg == "mn" then
123 d[#d+1] = d1.data[1]
124 d1.data = d
125 data[f] = false
126 end
127 f = false
128 else
129 f = false
130 end
131 end
132 if d then
133 local j = 0
134 for i=1,n do
135 local d = data[i]
136 if d then
137 j = j + 1
138 data[j] = d
139 end
140 end
141 for i=j+1,n do
142 data[i] = nil
143 end
144 end
145 end
146
147 local functioncontent = { }
148
149 setmetatableindex(functioncontent,function(t,k)
150 local v = { { content = k } }
151 t[k] = v
152 return v
153 end)
154
155 local dummy_nucleus = {
156 element = "mtext",
157 data = { content = "" },
158 nature = "mixed",
159 comment = "dummy nucleus",
160 fulltag = "mtext>0"
161 }
162
163 local function accentchar(d)
164 local detail = tonumber(d.detail)
165 if detail then
166 local d1 = d.data[1]
167 if d1 and d1.tg == "mrow" then
168
169 d.element = "mrow"
170 d.detail = nil
171 local s = specifications[d.fulltag]
172 s.detail = nil
173
174 d1.element = "mo"
175
176 d1.attributes = { stretchy = "true" }
177 d1.nature = "mixed"
178 d1.data = { { content = utfchar(detail) } }
179 return d
180 end
181 end
182 end
183
184 local function maybetext(d)
185 if #d.data == 1 and d.data[1].content then
186 d.element = "mtext"
187 else
188 d.element = "mrow"
189 end
190 return d
191 end
192
193 local no_mrow = {
194
195 math = true,
196
197 mrow = true,
198 mfenced = true,
199 mfrac = true,
200 mroot = true,
201 msqrt = true,
202 mtable = true,
203 mi = true,
204 mo = true,
205 mn = true,
206 mspace = true,
207 mtext = true,
208
209
210
211
212
213 }
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 local function checked(d,n)
236 if n == 1 then
237 local di = d[1]
238 if di then
239 local tg = di.tg
240 if tg == "ignore" then
241
242 return 1
243 elseif di.content then
244 return 1
245 else
246 local dd = di.data
247 local nn = #dd
248 if nn > 0 and checked(dd,nn) > 0 then
249 return 1
250 else
251 return 0
252 end
253 end
254 else
255
256 return 0
257 end
258 else
259 local m = 0
260 for i=1,n do
261 local di = d[i]
262 if di then
263 local tg = di.tg
264 if tg == "ignore" then
265
266 elseif di.content then
267 m = m + 1
268 d[m] = di
269 else
270 local dd = di.data
271 local nn = #dd
272 if nn > 0 and checked(dd,nn) > 0 then
273 m = m + 1
274 d[m] = di
275 end
276 end
277 else
278
279 end
280 end
281 if m < n then
282 for i=n,m+1,-1 do
283 d[i] = nil
284 end
285 end
286 return m
287 end
288 end
289
290 local stretched = {
291 operator = "false",
292 open = "false",
293 close = "false",
294 middle = "false",
295 integral = "false",
296 }
297
298 local nbsp <const> = utfchar(0x00A0)
299 local mbsp <const> = utfchar(0x2000)
300
301
302
303 local replacer = lpeg.replacer {
304 [", "] = ",".. mbsp,
305 [". "] = ".".. mbsp,
306 [": "] = ":".. mbsp,
307 ["; "] = ";".. mbsp,
308 [","] = ",".. mbsp,
309 ["."] = ".".. mbsp,
310 [":"] = ":".. mbsp,
311 [";"] = ";".. mbsp,
312 [" "] = nbsp,
313 }
314
315
316 local function checkmath(root)
317 local data = root.data
318 if data then
319 local ndata = #data
320 local roottg = root.tg
321 if roottg == "mo" then
322 local s = specifications[root.fulltag]
323 local class = s.mathclass
324 local group = s.mathgroup
325 local delimiter = s.delimiter
326
327 if class or group then
328 root.attributes = {
329 mathclass = class,
330 mathgroup = group,
331 mathindex = s.mathindex,
332 mathcharacter = s.mathcharacter,
333 mathstack = s.mathstack,
334 stretchy = (delimiter == "true" and "true") or stretched[class] or nil,
335 }
336 else
337
338
339 root.attributes = {
340 mathstack = s.mathstack,
341
342 stretchy = delimiter == "true" and "true" or "false",
343 }
344 end
345 elseif roottg == "mfenced" then
346 local s = specifications[root.fulltag]
347 local o = s.operator
348 if o then
349 root.skip = "comment"
350
351 elseif tagging.mfenced then
352 local l = s.left
353 local m = s.middle
354 local r = s.right
355 if l then
356 l = utfchar(l)
357 end
358 if m then
359 local t = { }
360 for i=1,#m do
361 t[i] = utfchar(m[i])
362 end
363 m = concat(t)
364 end
365 if r then
366 r = utfchar(r)
367 end
368 root.attributes = {
369 open = l,
370 separators = m,
371 close = r,
372 stretchy = "true",
373 }
374 else
375 root.element = "mrow"
376 root.attributes = {
377 mathcategory = s.mathcategory,
378
379 }
380 end
381
382 elseif roottg == "mrow" then
383 ndata = checked(data,ndata)
384 end
385 if ndata == 0 then
386 root.skip = "comment"
387 root.nota = "weird"
388 return
389 elseif ndata == 1 then
390 local d = data[1]
391 if not d or d == "" then
392 root.skip = "comment"
393 return
394 elseif d.content then
395 return
396 elseif roottg == "mrow" or roottg == "mtext" then
397
398
399 local s = specifications[root.fulltag]
400 if s.mathunit then
401 d.attributes = {
402 mathunit = s.mathunit
403 }
404 elseif s.mathdigits then
405 d.attributes = {
406 mathdigits = s.mathdigits
407 }
408 elseif s.mathfunction then
409 d.attributes = {
410 mathfunction = s.mathfunction,
411 mathcategory = s.mathcategory,
412 mathstack = s.mathstack,
413 }
414 elseif no_mrow[d.tg] then
415 root.skip = "comment"
416 else
417 d.attributes = {
418 mathstack = s.mathstack,
419 }
420 end
421 elseif roottg == "mo" then
422 if d.tg == "mo" then
423 root.skip = "comment"
424 end
425 end
426 end
427
428 local i = 1
429 while i <= ndata do
430 local di = data[i]
431 if di and not di.content then
432 local tg = di.tg
433 if tg == "math" then
434
435 di.skip = "comment"
436 checkmath(di)
437 i = i + 1
438 elseif tg == "mover" then
439 local s = specifications[di.fulltag]
440 if s.accent then
441 local t = s.top
442 local d = di.data
443
444 di.attributes = {
445 accent = "true",
446 mathcategory = s.mathcategory,
447 }
448
449 if t then
450
451 if true then
452 local dd = d[1].data
453 if dd then
454 dd[1].content = utfchar(t)
455 end
456 end
457
458 di.data = { d[2], d[1] }
459 end
460 else
461
462 end
463 checkmath(di)
464 i = i + 1
465 elseif tg == "munder" then
466 local s = specifications[di.fulltag]
467 if s.accent then
468 local b = s.bottom
469 local d = di.data
470
471 di.attributes = {
472 accent = "true",
473 mathcategory = s.mathcategory,
474 }
475
476 if b then
477
478 if true then
479 local dd = d[2].data
480 if dd then
481 dd[1].content = utfchar(b)
482 end
483 end
484 end
485 else
486
487 end
488 checkmath(di)
489 i = i + 1
490 elseif tg == "munderover" then
491 local s = specifications[di.fulltag]
492 if s.accent then
493 local t = s.top
494 local b = s.bottom
495 local d = di.data
496
497
498 di.attributes = {
499 accent = "true",
500 accentunder = "true",
501 }
502
503
504 if t and b then
505
506 if true then
507 local dd = d[1].data
508 if dd then
509 dd[1].content = utfchar(t)
510 end
511 local dd = d[3].data
512 if dd then
513 dd[1].content = utfchar(b)
514 end
515 end
516 di.data = { d[2], d[3], d[1] }
517 else
518
519 end
520 else
521
522 end
523 checkmath(di)
524 i = i + 1
525 elseif tg == "mstacker" then
526 local d = di.data
527 local d1 = d[1]
528 local d2 = d[2]
529 local d3 = d[3]
530 local t1 = d1 and d1.tg
531 local t2 = d2 and d2.tg
532 local t3 = d3 and d3.tg
533 local m = nil
534 local t = nil
535 local b = nil
536
537
538 if t1 == "mstackermid" then
539 if t2 == "mstackertop" then
540 if t3 == "mstackerbot" then
541 m = accentchar(d1) or maybetext(d1)
542 t = accentchar(d2) or maybetext(d2)
543 b = accentchar(d3) or maybetext(d3)
544 di.element = "munderover"
545 di.data = { m or d1.data[1], b, t }
546 else
547 m = accentchar(d1) or maybetext(d1)
548 t = accentchar(d2) or maybetext(d2)
549 di.element = "mover"
550 di.data = { m or d1.data[1], t }
551 end
552 elseif t2 == "mstackerbot" then
553 if t3 == "mstackertop" then
554 m = accentchar(d1) or maybetext(d1)
555 b = accentchar(d2) or maybetext(d2)
556 t = accentchar(d3) or maybetext(d3)
557 di.element = "munderover"
558 di.data = { m or d1.data[1], t, b }
559 else
560 m = accentchar(d1) or maybetext(d1)
561 b = accentchar(d2) or maybetext(d2)
562 di.element = "munder"
563 di.data = { m or d1.data[1], b }
564 end
565 else
566 m = accentchar(d1)
567 di.element = "mrow"
568 di.data = { m or d1.data[1] }
569 end
570 end
571 if t or b then
572 di.attributes = {
573 accent = t and "true" or nil,
574 accentunder = b and "true" or nil,
575 }
576 di.detail = nil
577 end
578 checkmath(di)
579 i = i + 1
580 elseif tg == "mroot" then
581 local data = di.data
582 local size = #data
583 if size == 1 then
584
585 di.element = "msqrt"
586 elseif size == 2 then
587 data[1], data[2] = data[2], data[1]
588 end
589 checkmath(di)
590 i = i + 1
591 elseif tg == "mdelimited" then
592 local d = di.data
593 local n = #d
594 for i=1,n do
595 local di = d[i]
596 local properties = specifications[di.fulltag] or { }
597 local location = properties.delimiterlocation
598 if location then
599 if di.attributes then
600 di.attributes.delimiterlocation = location
601 else
602
603 di.attributes = { delimiterlocation = location }
604 end
605 end
606 end
607 di.element = "mrow"
608 checkmath(di)
609 i = i + 1
610 elseif tg == "mstack" then
611 di.element = "mover"
612 local scriptlevel = "1"
613 if di.attributes then
614 di.attributes.scriptlevel = scriptlevel
615 else
616 di.attributes = { scriptlevel = scriptlevel }
617 end
618 checkmath(di)
619 i = i + 1
620 elseif tg == "break" then
621 di.skip = "comment"
622 i = i + 1
623 elseif tg == "mspace" then
624
625 local s = specifications[di.fulltag]
626 local e = s and s.emfactor
627 if e and e ~= 0 then
628 di.element = "mspace"
629 di.attributes = {
630 width = f_em(e),
631 }
632 end
633 i = i + 1
634 elseif tg == "mtext" then
635
636
637 local data = di.data
638 local size = #data
639
640 if size > 1 then
641 for i=1,size do
642 local di = data[i]
643 local content = di.content
644 if content then
645 data[i] = {
646 element = "mtext",
647 nature = "inline",
648 data = { di },
649 n = 0,
650 }
651
652di.content = lpeg.match(replacer,content)
653 elseif di.tg == "math" then
654 local di = di.data[1]
655 if di then
656 data[i] = di
657 checkmath(di)
658 end
659 end
660 end
661 di.element = "mrow"
662
663
664 elseif size > 0 then
665 local di = data[1]
666 local content = di.content
667 if content then
668
669di.content = lpeg.match(replacer,content)
670 end
671 end
672 checkmath(di)
673 i = i + 1
674 elseif tg == "mi" then
675 local s = specifications[di.fulltag]
676 if s.mathclass == "punctuation" then
677 di.element = "mtext"
678 checkmath(di)
679 i = i + 1
680 else
681
682
683
684 local class = s.mathclass
685 local group = s.mathgroup
686
687 if class or group then
688 di.attributes = {
689 mathclass = class,
690 mathgroup = group,
691 mathindex = s.mathindex,
692 mathcharacter = s.mathcharacter,
693 mathstack = s.mathstack,
694 }
695 else
696 di.attributes = {
697 mathstack = s.mathstack,
698 }
699 end
700 checkmath(di)
701 i = i + 1
702 end
703 elseif tg == "mrow" then
704 local d = di.data
705 local n = #d
706 local s = specifications[di.fulltag]
707 if s.mathunit then
708 di.attributes = { mathunit = s.mathunit }
709 i = i + 1
710 elseif s.mathdigits then
711
712 for i=1,n do
713 d[i] = d[i].data[1].content or ""
714 end
715 di.tg = "mn"
716 di.element = "mn"
717 di.nature = "mixed"
718 di.data = { { content = concat(d) } }
719 i = i + 1
720 elseif s.mathfunction then
721 di.attributes = {
722 mathfunction = s.mathfunction,
723 mathstack = s.mathstack
724 }
725 local category = tonumber(s.mathcategory)
726 if functiontype(category) == "function" then
727 local fnc = functions[category]
728 local tag = fnc and fnc.tag
729 if tag then
730 di.tg = "mi"
731 di.element = "mi"
732 di.nature = "mixed"
733 di.data = functioncontent[tag]
734 end
735 end
736 i = i + 1
737 elseif s.mathfunctionstack then
738 di.attributes = {
739 mathfunction = s.mathfunction,
740 mathstack = s.mathstack,
741 mathfunctionstack = s.mathfunctionstack,
742 }
743 checkmath(di)
744 i = i + 1
745 elseif s.mathdelimitedstack then
746 di.attributes = {
747 mathdelimitedstack = s.mathdelimitedstack,
748 }
749 checkmath(di)
750 i = i + 1
751 elseif s.mathfractionstack then
752 di.attributes = {
753 mathfractionstack = s.mathfractionstack,
754 }
755 checkmath(di)
756 i = i + 1
757 else
758 if n > 0 then
759 local d1 = d[1]
760 local tg = d1.tg
761 if tg == "mfrac" then
762 if n == 1 then
763 di = d1
764 data[i] = di
765 elseif n == 2 and d[2].tg == "ignore" then
766
767 di = d1
768 data[i] = di
769 end
770
771
772
773
774 end
775 end
776 checkmath(di)
777 i = i + 1
778 end
779 elseif tg == "formulacaption" then
780 di.tg = "ignore"
781 i = i + 1
782 elseif tg == "subformula" then
783 di.tg = "mrow"
784 checkmath(di)
785 i = i + 1
786 else
787
788 local s = specifications[di.fulltag]
789 if not s then
790
791 elseif tg == "mfrac" then
792 if s.mathfractionrule == "no" then
793 di.attributes = {
794 rulethickness = "0"
795 }
796 end
797 elseif tg == "msup" then
798 if s.limits then
799 di.element = "mover"
800 end
801 elseif tg == "msub" then
802 if s.limits then
803 di.element = "munder"
804 end
805 elseif tg == "msubsup" then
806 if s.limits then
807 di.element = "munderover"
808 end
809 end
810
811 checkmath(di)
812 i = i + 1
813 end
814 else
815 if parenttg ~= "mtext" and di == " " then
816 data[i] = false
817 end
818 i = i + 1
819 end
820 end
821 end
822 end
823
824 local function stripmath(di)
825 if not di then
826
827 elseif di.content then
828 return di
829 else
830 local tg = di.tg
831 if tg == "mtext" or tg == "ms" then
832 return di
833 elseif tg == "mspace" then
834 return di
835 else
836 local data = di.data
837 local ndata = #data
838 local n = 0
839 for i=1,ndata do
840 local d = data[i]
841 if d and not d.content then
842 d = stripmath(d)
843 end
844 if d then
845 local content = d.content
846
847
848
849
850
851
852
853
854
855
856
857
858 n = n + 1
859 data[n] = d
860 if d.tg == "mspace" then
861 d.data = { }
862 elseif not content then
863 d.__i__ = n
864 end
865 end
866 end
867 for i=ndata,n+1,-1 do
868 data[i] = nil
869 end
870
871 collapse_all_mn(data)
872
873 if #data > 0 then
874 return di
875 end
876 end
877 end
878 end
879
880 function checks.math(di)
881
882 if di.skip == "comment" then
883
884
885 else
886 local specification = specifications[di.fulltag]
887 local mode = specification.mode == "display" and "block" or "inline"
888 local domain = specification.domain or "default"
889 local family = specification.family or "regular"
890 local style = specification.style or 2
891 di.attributes = {
892
893 ["xmlns"] = mathmlns,
894 ["display"] = mode,
895 ["alttext"] = specification.input,
896
897 ["displaystyle"] = style < 2 and "true" or "false",
898 ["data-lmtx-blob"] = specification.blob,
899 ["data-lmtx-domain"] = domain ~= "default" and domain or nil,
900 ["data-lmtx-family"] = family ~= "regular" and family or nil,
901 }
902
903 if specification.standalone then
904 di.nature = "display"
905 elseif mode == "inline" then
906
907 di.nature = "inline"
908 else
909 di.nature = "display"
910 end
911 if automathstrip then
912 stripmath(di)
913 end
914 checkmath(di)
915 end
916 end
917
918
919
920 local mprescripts = {
921 element = "mprescripts",
922 data = { content = "" },
923 nature = "inline",
924 fulltag = "mprescripts>0"
925 }
926
927 local function wrapup(d,index,n,prelist,kernel,postlist)
928 local di = d[index]
929 local post = #postlist
930 local pre = #prelist
931 local list = { kernel }
932 local size = 1
933 for i=index+1,n do
934 d[i].skip = "ignore"
935 end
936 if post > 0 then
937 for i=1,post do
938 size = size + 1 ; list[size] = postlist[i]
939 end
940 end
941 if pre > 0 then
942 size = size + 1 ; list[size] = mprescripts
943 for i=1,pre do
944 size = size + 1 ; list[size] = prelist[i]
945 end
946 end
947 di.element = "mmultiscripts"
948
949 di.data = list
950 di.iscontinuation = true
951 di.__i__ = size
952 end
953
954 local function found(d,what)
955 if what then
956 for i=1,#d do
957 local di = d[i]
958 local sp = specifications[di.fulltag]
959 if sp and sp.script == what then
960 return di
961 end
962 end
963 else
964 for i=1,#d do
965 local di = d[i]
966 local sp = specifications[di.fulltag]
967 if not sp or not sp.script then
968 return di
969 end
970 end
971 end
972 end
973
974
975
976 function checks.mrow(di)
977 local d = di.data
978 if d then
979 local postlist = nil
980 local prelist = nil
981 local kernel = nil
982 local index = 0
983 for i=1,#d do
984 local di = d[i]
985 local data = di.data
986 local tg = di and di.tg
987 local sp = specifications[di.fulltag]
988 local continuation = sp and sp.continuation
989 if continuation then
990
991 if postlist and continuation.head then
992 wrapup(d,index,#d,prelist,kernel,postlist)
993 postlist = nil
994 prelist = nil
995 kernel = 0
996 end
997
998 local nd = #data
999 if tg == "msup" then
1000 if not postlist then
1001 index = i
1002 postlist = { }
1003 prelist = { }
1004 kernel = dummy_nucleus
1005 end
1006 local sup = found(data,"sup")
1007 postlist[#postlist+1] = dummy_nucleus
1008 postlist[#postlist+1] = sup
1009 if continuation.kernel then
1010 kernel = data[1] or dummy_nucleus
1011 end
1012 elseif tg == "msub" then
1013 if not postlist then
1014 index = i
1015 postlist = { }
1016 prelist = { }
1017 kernel = dummy_nucleus
1018 end
1019 local sub = found(data,"sub")
1020 postlist[#postlist+1] = sub
1021 postlist[#postlist+1] = dummy_nucleus
1022 if continuation.kernel then
1023 kernel = data[1] or dummy_nucleus
1024 end
1025 elseif tg == "msubsup" then
1026 if not postlist then
1027 index = i
1028 postlist = { }
1029 prelist = { }
1030 kernel = dummy_nucleus
1031 end
1032 local sub = found(data,"sub")
1033 local sup = found(data,"sup")
1034 postlist[#postlist+1] = sub or dummy_nucleus
1035 postlist[#postlist+1] = sup or dummy_nucleus
1036 if continuation.kernel then
1037 kernel = data[1] or dummy_nucleus
1038 end
1039 elseif tg == "mmultiscripts" then
1040
1041 if not postlist then
1042 index = i
1043 postlist = { }
1044 prelist = { }
1045 kernel = dummy_nucleus
1046 end
1047 local prime = found(data,"prime")
1048 local sub = found(data,"sub")
1049 local sup = found(data,"sup")
1050 local presub = found(data,"presub")
1051 local presup = found(data,"presup")
1052 if prime then
1053 postlist[#postlist+1] = dummy_nucleus
1054 postlist[#postlist+1] = prime
1055 end
1056 if sub or sup then
1057 postlist[#postlist+1] = sub or dummy_nucleus
1058 postlist[#postlist+1] = sup or dummy_nucleus
1059 end
1060 if presub or presup then
1061 prelist[#prelist+1] = presub or dummy_nucleus
1062 prelist[#prelist+1] = presup or dummy_nucleus
1063 end
1064 if continuation.kernel then
1065 kernel = data[1] or dummy_nucleus
1066 end
1067 else
1068 postlist = nil
1069 prelist = nil
1070 kernel = nil
1071 end
1072 elseif postlist then
1073 wrapup(d,index,i-1,prelist,kernel,postlist)
1074 postlist = nil
1075 prelist = nil
1076 kernel = nil
1077 end
1078 end
1079 if postlist then
1080 wrapup(d,index,#d,prelist,kernel,postlist)
1081 end
1082 end
1083 end
1084
1085
1086
1087 local function flatten(di)
1088 local r = di.__p__
1089 while r do
1090 local d = r.data
1091 local n = #d
1092 if d and n > 1 then
1093 n = checked(d,n)
1094 end
1095 local tg = r.tg
1096 if n == 1 and (tg == "mtext" or tg == "mrow") then
1097 r.skip = "comment"
1098 r = r.__p__
1099 else
1100 break
1101 end
1102 end
1103 end
1104
1105 function checks.mtable(di)
1106 flatten(di)
1107 local d = di.data
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165 for i=1,#d do
1166 local d = d[i]
1167 if d.tg == "mtr" then
1168 local d = d.data
1169 for i=1,#d do
1170 local d = d[i]
1171 if d.tg == "mtd" then
1172
1173 elseif d.content then
1174 d.content = ""
1175 else
1176 d.skip = "comment"
1177 end
1178 end
1179 elseif d.content then
1180 d.content = ""
1181 else
1182 d.skip = "comment"
1183 end
1184 end
1185 end
1186
1187 function extras.mmultiscripts(di,element,n,fulltag)
1188 if not di.iscontinuation then
1189 local d = di.data
1190 local sup = found(d,"sup")
1191 local sub = found(d,"sub")
1192 local presup = found(d,"presup")
1193 local presub = found(d,"presub")
1194 local prime = found(d,"prime")
1195 local n = 1
1196 if sup or sub then
1197 n = n + 1 ; d[n] = sub or dummy_nucleus
1198 n = n + 1 ; d[n] = sup or dummy_nucleus
1199 end
1200 if prime then
1201 n = n + 1 ; d[n] = dummy_nucleus
1202 n = n + 1 ; d[n] = prime
1203 end
1204 if presup or presub then
1205 n = n + 1 ; d[n] = mprescripts
1206 n = n + 1 ; d[n] = presub or dummy_nucleus
1207 n = n + 1 ; d[n] = presup or dummy_nucleus
1208 end
1209 d.__i__ = n
1210 end
1211 end
1212
1213 function extras.msub(di,element,n,fulltag)
1214 local data = di.data
1215 local nuc = found(data)
1216 local sub = found(data,"sub")
1217 data[1] = nuc or dummy_nucleus
1218 data[2] = sub or dummy_nucleus
1219 data.__i__ = 2
1220 local sp = specifications[di.fulltag]
1221 if attributes then
1222 attributes.mathsubindex = sp.subindexed
1223 else
1224 di.attributes = {
1225 mathsubindex = sp.subindexed,
1226 }
1227 end
1228 end
1229
1230 function extras.msup(di,element,n,fulltag)
1231 local data = di.data
1232 local nuc = found(data)
1233 local sup = found(data,"sup")
1234or found(data,"prime")
1235 data[1] = nuc or dummy_nucleus
1236 data[2] = sup or dummy_nucleus
1237 data.__i__ = 2
1238 local sp = specifications[di.fulltag]
1239 local attributes = di.attributes
1240 if attributes then
1241 attributes.mathsupindex = sp.supindexed
1242 else
1243 di.attributes = {
1244 mathsupindex = sp.supindexed,
1245 }
1246 end
1247 end
1248
1249 function extras.msubsup(di,element,n,fulltag)
1250 local data = di.data
1251 local nuc = found(data)
1252 local sup = found(data,"sup")
1253or found(data,"prime")
1254 local sub = found(data,"sub")
1255 data[1] = nuc or dummy_nucleus
1256 data[2] = sub or dummy_nucleus
1257 data[3] = sup or dummy_nucleus
1258 data.__i__ = 3
1259 local sp = specifications[di.fulltag]
1260 if attributes then
1261 attributes.mathsupindex = sp.supindexed
1262 attributes.mathsubindex = sp.subindexed
1263 else
1264 di.attributes = {
1265 mathsupindex = sp.supindexed,
1266 mathsubindex = sp.subindexed,
1267 }
1268 end
1269 end
1270
1271 function extras.munder(di,element,n,fulltag)
1272 if di.tg == "msub" then
1273 extras.msub(di,element,n,fulltag)
1274 end
1275 end
1276
1277 function extras.mover(di,element,n,fulltag)
1278 if di.tg == "msup" then
1279 extras.msup(di,element,n,fulltag)
1280 end
1281 end
1282
1283 function extras.munderover(di,element,n,fulltag)
1284 if di.tg == "msubsup" then
1285 extras.msubsup(di,element,n,fulltag)
1286 end
1287 end
1288
1289end
1290 |