1if not modules then modules = { } end modules [ ' back-exp ' ] = {
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
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36local next , type , tonumber = next , type , tonumber
37local sub , gsub , match = string . sub , string . gsub , string . match
38local validstring = string . valid
39local lpegmatch = lpeg . match
40local utfchar , utfvalues , utflen = utf . char , utf . values , utf . len
41local concat , insert , remove , merge , sort = table . concat , table . insert , table . remove , table . merge , table . sort
42local sortedhash , sortedkeys = table . sortedhash , table . sortedkeys
43local formatters = string . formatters
44local todimen = number . todimen
45local replacetemplate = utilities . templates . replace
46
47local trace_export = false trackers . register ( " export.trace " , function ( v ) trace_export = v end )
48local trace_spacing = false trackers . register ( " export.trace.spacing " , function ( v ) trace_spacing = v end )
49local trace_details = false trackers . register ( " export.trace.details " , function ( v ) trace_details = v end )
50
51local less_state = false directives . register ( " export.lessstate " , function ( v ) less_state = v end )
52local show_comment = true directives . register ( " export.comment " , function ( v ) show_comment = v end )
53
54show_comment = false
55
56
57
58
59
60
61
62
63local report_export = logs . reporter ( " backend " , " export " )
64
65local nodes = nodes
66local attributes = attributes
67
68local variables = interfaces . variables
69local v_yes = variables . yes
70local v_no = variables . no
71local v_xml = variables . xml
72local v_hidden = variables . hidden
73
74local implement = interfaces . implement
75
76local included = backends . included
77
78local settings_to_array = utilities . parsers . settings_to_array
79local settings_to_hash = utilities . parsers . settings_to_hash
80
81local setmetatableindex = table . setmetatableindex
82local tasks = nodes . tasks
83local fontchar = fonts . hashes . characters
84local fontquads = fonts . hashes . quads
85local languagenames = languages . numbers
86
87local texgetcount = tex . getcount
88
89local references = structures . references
90local structurestags = structures . tags
91local taglist = structurestags . taglist
92local specifications = structurestags . specifications
93local properties = structurestags . properties
94local locatedtag = structurestags . locatedtag
95
96structurestags . usewithcare = { }
97
98local starttiming = statistics . starttiming
99local stoptiming = statistics . stoptiming
100
101local characterdata = characters . data
102local overloads = fonts . mappings . overloads
103
104
105
106local exportversion = " 0.35 "
107local mathmlns = " http://www.w3.org/1998/Math/MathML "
108local contextns = " http://www.contextgarden.net/context/export "
109local cssnamespaceurl = " @namespace context url('%namespace%') ; "
110local cssnamespace = " context| "
111
112
113local usecssnamespace = false
114
115local nofcurrentcontent = 0
116local currentcontent = { }
117local currentnesting = nil
118local currentattribute = nil
119local last = nil
120local currentparagraph = nil
121
122local noftextblocks = 0
123
124
125local hyphen = utfchar ( 0xAD )
126local tagsplitter = structurestags . patterns . splitter
127
128
129local threshold = 65536
130local indexing = false
131local keephyphens = false
132local exportproperties = false
133
134local finetuning = { }
135
136local treestack = { }
137local nesting = { }
138local currentdepth = 0
139
140local wrapups = { }
141
142local tree = { data = { } , fulltag = = " root " }
143local treeroot = tree
144local treehash = { }
145local extras = { }
146local checks = { }
147local fixes = { }
148local finalizers = { }
149local nofbreaks = 0
150local used = { }
151local exporting = false
152local restart = false
153local specialspaces = { [ 0x20 ] = " " }
154local somespace = { [ 0x20 ] = true , [ " " ] = true }
155local entities = { [ " & " ] = " & " , [ " > " ] = " > " , [ " < " ] = " < " }
156local attribentities = { [ " & " ] = " & " , [ " > " ] = " > " , [ " < " ] = " < " , [ ' " ' ] = " quot; " }
157
158local p_entity = lpeg . replacer ( entities )
159local p_attribute = lpeg . replacer ( attribentities )
160local p_stripper = lpeg . patterns . stripper
161local p_escaped = lpeg . patterns . xml . escaped
162
163local f_tagid = formatters [ " %s-%04i " ]
164
165
166
167
168
169
170
171local defaultnature = " mixed "
172
173setmetatableindex ( used , function ( t , k )
174 if k then
175 local v = { }
176 t [ k ] = v
177 return v
178 end
179end )
180
181local f_entity = formatters [ " &#x%X; " ]
182local f_attribute = formatters [ " %s=%q " ]
183local f_property = formatters [ " %s%s=%q " ]
184
185setmetatableindex ( specialspaces , function ( t , k )
186 local v = utfchar ( k )
187 t [ k ] = v
188 entities [ v ] = f_entity ( k )
189 somespace [ k ] = true
190 somespace [ v ] = true
191 return v
192end )
193
194
195local namespaced = {
196
197}
198
199local namespaces = {
200 msubsup = " m " ,
201 msub = " m " ,
202 msup = " m " ,
203 mn = " m " ,
204 mi = " m " ,
205 ms = " m " ,
206 mo = " m " ,
207 mtext = " m " ,
208 mrow = " m " ,
209 mfrac = " m " ,
210 mroot = " m " ,
211 msqrt = " m " ,
212 munderover = " m " ,
213 munder = " m " ,
214 mover = " m " ,
215 merror = " m " ,
216 math = " m " ,
217 mrow = " m " ,
218 mtable = " m " ,
219 mtr = " m " ,
220 mtd = " m " ,
221 mfenced = " m " ,
222 maction = " m " ,
223 mspace = " m " ,
224
225 mstacker = " m " ,
226 mstackertop = " m " ,
227 mstackermid = " m " ,
228 mstackerbot = " m " ,
229}
230
231setmetatableindex ( namespaced , function ( t , k )
232 if k then
233 local namespace = namespaces [ k ]
234 local v = namespace and namespace . . " : " . . k or k
235 t [ k ] = v
236 return v
237 end
238end )
239
240local function attribute ( key , value )
241 if value and value ~ = " " then
242 return f_attribute ( key , lpegmatch ( p_attribute , value ) )
243 else
244 return " "
245 end
246end
247
248local function setattribute ( di , key , value , escaped )
249 if value and value ~ = " " then
250 local a = di . attributes
251 if escaped then
252 value = lpegmatch ( p_escaped , value )
253 end
254 if not a then
255 di . attributes = { [ key ] = value }
256 else
257 a [ key ] = value
258 end
259 end
260end
261
262local listdata = { }
263
264function wrapups . hashlistdata ( )
265 local c = structures . lists . collected
266 for i = 1 , # c do
267 local ci = c [ i ]
268 local tag = ci . references . tag
269 if tag then
270 local m = ci . metadata
271 local t = m . kind . . " > " . . tag
272 listdata [ t ] = ci
273 end
274 end
275end
276
277function structurestags . setattributehash ( attr , key , value )
278 local specification = taglist [ attr ]
279 if specification then
280 specification [ key ] = value
281 else
282
283 end
284end
285
286local usedstyles = { }
287
288local namespacetemplate = [[
289/* %what% for file %filename% */
290
291%cssnamespaceurl%
292 ]]
293
294do
295
296
297
298
299
300
301
302
303
304local documenttemplate = [[
305document,
306%namespace%div.document {
307 font-size : %size% !important ;
308 max-width : %width% !important ;
309 text-align : %align% !important ;
310 hyphens : %hyphens% !important ;
311} ]]
312
313local styletemplate = [[
314%element%[detail="%detail%"],
315%namespace%div.%element%.%detail% {
316 display : inline ;
317 font-style : %style% ;
318 font-variant : %variant% ;
319 font-weight : %weight% ;
320 font-family : %family% ;
321 color : %color% ;
322} ]]
323
324 local numbertoallign = {
325 [ 0 ] = " justify " , [ " 0 " ] = " justify " , [ variables . normal ] = " justify " ,
326 [ 1 ] = " right " , [ " 1 " ] = " right " , [ variables . flushright ] = " right " ,
327 [ 2 ] = " center " , [ " 2 " ] = " center " , [ variables . middle ] = " center " ,
328 [ 3 ] = " left " , [ " 3 " ] = " left " , [ variables . flushleft ] = " left " ,
329 }
330
331 function wrapups . allusedstyles ( basename )
332 local result = { replacetemplate ( namespacetemplate , {
333 what = " styles " ,
334 filename = basename ,
335 namespace = contextns ,
336
337 cssnamespaceurl = cssnamespaceurl ,
338 } , false , true ) }
339
340 local bodyfont = finetuning . bodyfont
341 local width = finetuning . width
342 local hyphen = finetuning . hyphen
343 local align = finetuning . align
344
345 if type ( bodyfont ) = = " number " then
346 bodyfont = todimen ( bodyfont )
347 else
348 bodyfont = " 12pt "
349 end
350 if type ( width ) = = " number " then
351 width = todimen ( width ) or " 50em "
352 else
353 width = " 50em "
354 end
355 if hyphen = = v_yes then
356 hyphen = " manual "
357 else
358 hyphen = " inherited "
359 end
360 if align then
361 align = numbertoallign [ align ]
362 end
363 if not align then
364 align = hyphen and " justify " or " inherited "
365 end
366
367 result [ # result + 1 ] = replacetemplate ( documenttemplate , {
368 size = bodyfont ,
369 width = width ,
370 align = align ,
371 hyphens = hyphen
372 } )
373
374 local colorspecification = xml . css . colorspecification
375 local fontspecification = xml . css . fontspecification
376 for element , details in sortedhash ( usedstyles ) do
377 for detail , data in sortedhash ( details ) do
378 local s = fontspecification ( data . style )
379 local c = colorspecification ( data . color )
380 detail = gsub ( detail , " [^A-Za-z0-9]+ " , " - " )
381 result [ # result + 1 ] = replacetemplate ( styletemplate , {
382 namespace = usecssnamespace and cssnamespace or " " ,
383 element = element ,
384 detail = detail ,
385 style = s . style or " inherit " ,
386 variant = s . variant or " inherit " ,
387 weight = s . weight or " inherit " ,
388 family = s . family or " inherit " ,
389 color = c or " inherit " ,
390 display = s . display and " block " or nil ,
391 } )
392 end
393 end
394 return concat ( result , " \n\n " )
395 end
396
397end
398
399local usedimages = { }
400
401do
402
403local imagetemplate = [[
404%element%[id="%id%"], %namespace%div.%element%[id="%id%"] {
405 display : block ;
406 background-image : url('%url%') ;
407 background-size : 100%% auto ;
408 background-repeat : no-repeat ;
409 width : %width% ;
410 height : %height% ;
411} ]]
412
413 local f_svgname = formatters [ " %s.svg " ]
414 local f_svgpage = formatters [ " %s-page-%s.svg " ]
415 local collected = { }
416
417 local function usedname ( name , page )
418 if file . suffix ( name ) = = " pdf " then
419
420 if page and page > 1 then
421 name = f_svgpage ( file . nameonly ( name ) , page )
422 else
423 name = f_svgname ( file . nameonly ( name ) )
424 end
425 end
426 local scheme = url . hasscheme ( name )
427 if not scheme or scheme = = " file " then
428
429 return file . join ( " ../images " , file . basename ( url . filename ( name ) ) )
430 else
431 return name
432 end
433 end
434
435 function wrapups . allusedimages ( basename )
436 local result = { replacetemplate ( namespacetemplate , {
437 what = " images " ,
438 filename = basename ,
439 namespace = contextns ,
440
441 cssnamespaceurl = cssnamespaceurl ,
442 } , false , true ) }
443 for element , details in sortedhash ( usedimages ) do
444 for detail , data in sortedhash ( details ) do
445 local name = data . name
446 local page = tonumber ( data . page ) or 1
447 local spec = {
448 element = element ,
449 id = data . id ,
450 name = name ,
451 page = page ,
452 url = usedname ( name , page ) ,
453 width = data . width ,
454 height = data . height ,
455 used = data . used ,
456 namespace = usecssnamespace and cssnamespace or " " ,
457 }
458 result [ # result + 1 ] = replacetemplate ( imagetemplate , spec )
459 collected [ detail ] = spec
460 end
461 end
462 return concat ( result , " \n\n " )
463 end
464
465 function wrapups . uniqueusedimages ( )
466 return collected
467 end
468
469end
470
471
472
473properties . vspace = { export = " break " , nature = " display " }
474
475
476local function makebreaklist ( list )
477 nofbreaks = nofbreaks + 1
478 local t = { }
479 local l = list and list . taglist
480 if l then
481 for i = 1 , # list do
482 t [ i ] = l [ i ]
483 end
484 end
485 t [ # t + 1 ] = " break> " . . nofbreaks
486 return { taglist = t }
487end
488
489local breakattributes = {
490 type = " collapse "
491}
492
493local function makebreaknode ( attributes )
494 nofbreaks = nofbreaks + 1
495 return {
496 tg = " break " ,
497 fulltag = " break> " . . nofbreaks ,
498 n = nofbreaks ,
499 element = " break " ,
500 nature = " display " ,
501 attributes = attributes or nil ,
502
503
504
505 }
506end
507
508do
509
510 local fields = { " title " , " subtitle " , " author " , " keywords " , " url " , " version " }
511
512 local ignoredelements = false
513
514 local function checkdocument ( root )
515 local data = root . data
516 if data then
517 for i = 1 , # data do
518 local di = data [ i ]
519 local tg = di . tg
520 if tg = = " noexport " then
521 local s = specifications [ di . fulltag ]
522 local u = s and s . userdata
523 if u then
524 local comment = u . comment
525 if comment then
526 di . element = " comment "
527 di . data = { { content = comment } }
528 u . comment = nil
529 else
530 data [ i ] = false
531 end
532 else
533 data [ i ] = false
534 end
535 elseif di . content then
536
537 elseif tg = = " ignore " then
538 di . element = " "
539 checkdocument ( di )
540 elseif ignoredelements and ignoredelements [ tg ] then
541 di . element = " "
542 checkdocument ( di )
543 else
544 checkdocument ( di )
545 end
546 end
547 end
548 end
549
550 function extras . document ( di , element , n , fulltag )
551 setattribute ( di , " language " , languagenames [ texgetcount ( " mainlanguagenumber " ) ] )
552 if not less_state then
553 setattribute ( di , " file " , tex . jobname )
554 if included . date then
555 setattribute ( di , " date " , backends . timestamp ( ) )
556 end
557 setattribute ( di , " context " , environment . version )
558 setattribute ( di , " version " , exportversion )
559 setattribute ( di , " xmlns:m " , mathmlns )
560 local identity = interactions . general . getidentity ( )
561 for i = 1 , # fields do
562 local key = fields [ i ]
563 local value = identity [ key ]
564 if value and value ~ = " " then
565 setattribute ( di , key , value )
566 end
567 end
568 end
569 checkdocument ( di )
570 end
571
572 implement {
573 name = " ignoretagsinexport " ,
574 arguments = " string " ,
575 actions = function ( list )
576 for tag in string . gmatch ( list , " [a-z]+ " ) do
577 if ignoredelements then
578 ignoredelements [ tag ] = true
579 else
580 ignoredelements = { [ tag ] = true }
581 end
582 end
583 end ,
584 }
585
586end
587
588do
589
590 local marginanchors = { }
591 local margincontent = { }
592
593 implement {
594 name = " settagmargintext " ,
595 arguments = " integer " ,
596 actions = function ( n )
597 marginanchors [ locatedtag ( " margintext " ) ] = n
598 end
599 }
600
601 implement {
602 name = " settagmarginanchor " ,
603 arguments = " integer " ,
604 actions = function ( n )
605 marginanchors [ locatedtag ( " marginanchor " ) ] = n
606 end
607 }
608
609 function checks . margintext ( di )
610 local i = marginanchors [ di . fulltag ]
611 margincontent [ i ] = di
612 end
613
614 function checks . marginanchor ( di )
615 local i = marginanchors [ di . fulltag ]
616 local d = margincontent [ i ]
617
618 di . attribute = d . attribute
619 di . data = d . data
620 di . detail = d . detail
621 di . element = d . element
622 di . fulltag = d . fulltag
623 di . nature = d . nature
624 di . samepar = true
625 di . tg = d . tg
626
627 d . skip = " ignore "
628 end
629
630end
631
632do
633
634 local symbols = { }
635
636 function structurestags . settagdelimitedsymbol ( symbol )
637 symbols [ locatedtag ( " delimitedsymbol " ) ] = {
638 symbol = symbol ,
639 }
640 end
641
642 function extras . delimitedsymbol ( di , element , n , fulltag )
643 local hash = symbols [ fulltag ]
644 if hash then
645 setattribute ( di , " symbol " , hash . symbol or nil )
646 end
647 end
648
649end
650
651do
652
653 local symbols = { }
654
655 function structurestags . settagsubsentencesymbol ( symbol )
656 symbols [ locatedtag ( " subsentencesymbol " ) ] = {
657 symbol = symbol ,
658 }
659 end
660
661 function extras . subsentencesymbol ( di , element , n , fulltag )
662 local hash = symbols [ fulltag ]
663 if hash then
664 setattribute ( di , " symbol " , hash . symbol or nil )
665 end
666 end
667
668end
669
670do
671
672 local itemgroups = { }
673
674 function structurestags . setitemgroup ( packed , level , symbol )
675 itemgroups [ locatedtag ( " itemgroup " ) ] = {
676 packed = packed ,
677 symbol = symbol ,
678 level = level ,
679 }
680 end
681
682 function structurestags . setitem ( kind )
683 itemgroups [ locatedtag ( " item " ) ] = {
684 kind = kind ,
685 }
686 end
687
688 function extras . itemgroup ( di , element , n , fulltag )
689 local hash = itemgroups [ fulltag ]
690 if hash then
691 setattribute ( di , " packed " , hash . packed and " yes " or nil )
692 setattribute ( di , " symbol " , hash . symbol )
693 setattribute ( di , " level " , hash . level )
694 end
695 end
696
697 function extras . item ( di , element , n , fulltag )
698 local hash = itemgroups [ fulltag ]
699 if hash then
700 local kind = hash . kind
701 if kind and kind ~ = " " then
702 setattribute ( di , " kind " , kind )
703 end
704 end
705 end
706
707end
708
709do
710
711 function fixes . linenumber ( di , data , i )
712 local ni = data [ i + 1 ]
713 if ni then
714 if ni . data then
715 while true do
716 local d = ni . data [ 1 ]
717 if d then
718 local e = d . element
719 if e then
720 if e = = " line " or e = = " verbatimline " then
721 insert ( d . data , 1 , di )
722 data [ i ] = false
723 return
724 else
725 ni = d
726 end
727 else
728 return
729 end
730 else
731 return
732 end
733 end
734 end
735 end
736 end
737
738end
739
740do
741
742 local synonyms = { }
743 local sortings = { }
744
745 function structurestags . setsynonym ( tag )
746 synonyms [ locatedtag ( " synonym " ) ] = tag
747 end
748
749 function extras . synonym ( di , element , n , fulltag )
750 local tag = synonyms [ fulltag ]
751 if tag then
752 setattribute ( di , " tag " , tag )
753 end
754 end
755
756 function structurestags . setsorting ( tag )
757 sortings [ locatedtag ( " sorting " ) ] = tag
758 end
759
760 function extras . sorting ( di , element , n , fulltag )
761 local tag = sortings [ fulltag ]
762 if tag then
763 setattribute ( di , " tag " , tag )
764 end
765 end
766
767end
768
769do
770
771 local strippedtag = structurestags . strip
772
773 local highlight = { }
774 local construct = { }
775
776 usedstyles . highlight = highlight
777 usedstyles . construct = construct
778
779 function structurestags . sethighlight ( name , style , color , mode )
780 if not highlight [ name ] then
781 highlight [ name ] = {
782 style = style ,
783 color = color ,
784 mode = mode = = 1 and " display " or nil ,
785 }
786 end
787 end
788
789 function structurestags . setconstruct ( name , style , color , mode )
790 if not construct [ name ] then
791 construct [ name ] = {
792 style = style ,
793 color = color ,
794 mode = mode = = 1 and " display " or nil ,
795 }
796 end
797 end
798
799end
800
801do
802
803 local descriptions = { }
804 local symbols = { }
805 local linked = { }
806
807
808
809 function structurestags . setnotation ( tag , n )
810
811 local nd = structures . notes . get ( tag , n )
812 if nd then
813 local references = nd . references
814 descriptions [ references and references . internal ] = locatedtag ( " description " )
815 end
816 end
817
818 function structurestags . setnotationsymbol ( tag , n )
819 local nd = structures . notes . get ( tag , n )
820 if nd then
821 local references = nd . references
822 symbols [ references and references . internal ] = locatedtag ( " descriptionsymbol " )
823 end
824 end
825
826 function finalizers . descriptions ( tree )
827 local n = 0
828 for id , tag in sortedhash ( descriptions ) do
829 local sym = symbols [ id ]
830 if sym then
831 n = n + 1
832 linked [ tag ] = n
833 linked [ sym ] = n
834 end
835 end
836 end
837
838 function extras . description ( di , element , n , fulltag )
839 local id = linked [ fulltag ]
840 if id then
841 setattribute ( di , " insert " , id )
842 end
843 end
844
845 function extras . descriptionsymbol ( di , element , n , fulltag )
846 local id = linked [ fulltag ]
847 if id then
848 setattribute ( di , " insert " , id )
849 end
850 end
851
852end
853
854
855
856
857
858
859
860do
861
862 local f_id = formatters [ " %s-%s " ]
863 local image = { }
864 usedimages . image = image
865
866 structurestags . usewithcare . images = image
867
868 function structurestags . setfigure ( name , used , page , width , height , label )
869 local fulltag = locatedtag ( " image " )
870 local spec = specifications [ fulltag ]
871 if spec then
872 local page = tonumber ( page )
873 image [ fulltag ] = {
874 id = f_id ( spec . tagname , spec . tagindex ) ,
875 name = name ,
876 used = used ,
877 page = page and page > 1 and page or nil ,
878 width = todimen ( width , " cm " , " %0.3F%s " ) ,
879 height = todimen ( height , " cm " , " %0.3F%s " ) ,
880 label = label ,
881 }
882 else
883
884 end
885 end
886
887 function extras . image ( di , element , n , fulltag )
888 local data = image [ fulltag ]
889 if data then
890 setattribute ( di , " name " , data . name )
891 setattribute ( di , " page " , data . page )
892 setattribute ( di , " id " , data . id )
893 setattribute ( di , " width " , data . width )
894 setattribute ( di , " height " , data . height )
895 setattribute ( di , " label " , data . height )
896 end
897 end
898
899end
900
901do
902
903 local combinations = { }
904
905 function structurestags . setcombination ( nx , ny )
906 combinations [ locatedtag ( " combination " ) ] = {
907 nx = nx ,
908 ny = ny ,
909 }
910 end
911
912 function extras . combination ( di , element , n , fulltag )
913 local data = combinations [ fulltag ]
914 if data then
915 setattribute ( di , " nx " , data . nx )
916 setattribute ( di , " ny " , data . ny )
917 end
918 end
919
920end
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936local evaluators = { }
937local specials = { }
938local explicits = { }
939
940evaluators . inner = function ( di , var )
941 local inner = var . inner
942 if inner then
943 setattribute ( di , " location " , inner , true )
944 end
945end
946
947evaluators . outer = function ( di , var )
948 local file , url = references . checkedfileorurl ( var . outer , var . outer )
949 if url then
950 setattribute ( di , " url " , url , true )
951 elseif file then
952 setattribute ( di , " file " , file , true )
953 end
954end
955
956evaluators [ " outer with inner " ] = function ( di , var )
957 local file = references . checkedfile ( var . f )
958 if file then
959 setattribute ( di , " file " , file , true )
960 end
961 local inner = var . inner
962 if inner then
963 setattribute ( di , " inner " , inner , true )
964 end
965end
966
967evaluators . special = function ( di , var )
968 local handler = specials [ var . special ]
969 if handler then
970 handler ( di , var )
971 end
972end
973
974local referencehash = { }
975local destinationhash = { }
976
977do
978
979 evaluators [ " special outer with operation " ] = evaluators . special
980 evaluators [ " special operation " ] = evaluators . special
981 evaluators [ " special operation with arguments " ] = evaluators . special
982
983 function specials . url ( di , var )
984 local url = references . checkedurl ( var . operation )
985 if url and url ~ = " " then
986 setattribute ( di , " url " , url , true )
987 end
988 end
989
990 function specials . file ( di , var )
991 local file = references . checkedfile ( var . operation )
992 if file and file ~ = " " then
993 setattribute ( di , " file " , file , true )
994 end
995 end
996
997 function specials . fileorurl ( di , var )
998 local file , url = references . checkedfileorurl ( var . operation , var . operation )
999 if url and url ~ = " " then
1000 setattribute ( di , " url " , url , true )
1001 elseif file and file ~ = " " then
1002 setattribute ( di , " file " , file , true )
1003 end
1004 end
1005
1006 function specials . internal ( di , var )
1007 local internal = references . checkedurl ( var . operation )
1008 if internal then
1009 setattribute ( di , " location " , internal )
1010 end
1011 end
1012
1013 local function adddestination ( di , references )
1014 if references then
1015 local reference = references . reference
1016 if reference and reference ~ = " " then
1017 local prefix = references . prefix
1018 if prefix and prefix ~ = " " then
1019 setattribute ( di , " prefix " , prefix , true )
1020 end
1021 setattribute ( di , " destination " , reference , true )
1022 for i = 1 , # references do
1023 local r = references [ i ]
1024 local e = evaluators [ r . kind ]
1025 if e then
1026 e ( di , r )
1027 end
1028 end
1029 end
1030 end
1031 end
1032
1033 function extras . addimplicit ( di , references )
1034 if references then
1035 local internal = references . internal
1036 if internal then
1037 setattribute ( di , " implicit " , internal )
1038 end
1039 end
1040 end
1041
1042 function extras . addinternal ( di , references )
1043 if references then
1044 local internal = references . internal
1045 if internal then
1046 setattribute ( di , " internal " , internal )
1047 end
1048 end
1049 end
1050
1051 local p_firstpart = lpeg . Cs ( ( 1 - lpeg . P ( " , " ) ) ^ 0 )
1052
1053 local function addreference ( di , references )
1054 if references then
1055 local reference = references . reference
1056 if reference and reference ~ = " " then
1057 local prefix = references . prefix
1058 if prefix and prefix ~ = " " then
1059 setattribute ( di , " prefix " , prefix )
1060 end
1061 setattribute ( di , " reference " , reference , true )
1062 setattribute ( di , " explicit " , lpegmatch ( p_firstpart , reference ) , true )
1063 end
1064 local internal = references . internal
1065 if internal and internal ~ = " " then
1066 setattribute ( di , " implicit " , internal )
1067 end
1068 end
1069 end
1070
1071 local function link ( di , element , n , fulltag )
1072
1073 local reference = referencehash [ fulltag ]
1074 if reference then
1075 adddestination ( di , structures . references . get ( reference ) )
1076 return true
1077 else
1078 local data = di . data
1079 if data then
1080 for i = 1 , # data do
1081 local di = data [ i ]
1082 if di then
1083 local fulltag = di . fulltag
1084 if fulltag and link ( di , element , n , fulltag ) then
1085 return true
1086 end
1087 end
1088 end
1089 end
1090 end
1091 end
1092
1093 local function reference ( di , element , n , fulltag )
1094 local destination = destinationhash [ fulltag ]
1095 if destination then
1096 local d = structures . references . internals [ destination ]
1097 if d then
1098 addreference ( di , d . references )
1099 return true
1100 else
1101 return false
1102 end
1103 else
1104 local data = di . data
1105 if data then
1106 for i = 1 , # data do
1107 local di = data [ i ]
1108 if di then
1109 local fulltag = di . fulltag
1110 if fulltag and reference ( di , element , n , fulltag ) then
1111 return true
1112 end
1113 end
1114 end
1115 end
1116 end
1117 end
1118
1119 extras . adddestination = adddestination
1120 extras . addreference = addreference
1121
1122 extras . link = link
1123 extras . reference = reference
1124
1125end
1126
1127
1128
1129do
1130
1131 local automathrows = true directives . register ( " export.math.autorows " , function ( v ) automathrows = v end )
1132 local automathapply = true directives . register ( " export.math.autoapply " , function ( v ) automathapply = v end )
1133 local automathnumber = true directives . register ( " export.math.autonumber " , function ( v ) automathnumber = v end )
1134 local automathstrip = true directives . register ( " export.math.autostrip " , function ( v ) automathstrip = v end )
1135
1136 local functions = mathematics . categories . functions
1137
1138 local function collapse ( di , i , data , ndata , detail , element )
1139 local collapsing = di . data
1140 if data then
1141 di . element = element
1142 di . detail = nil
1143 i = i + 1
1144 while i < = ndata do
1145 local dn = data [ i ]
1146 if dn . detail = = detail then
1147 collapsing [ # collapsing + 1 ] = dn . data [ 1 ]
1148 dn . skip = " ignore "
1149 i = i + 1
1150 else
1151 break
1152 end
1153 end
1154 end
1155 return i
1156 end
1157
1158 local function collapse_mn ( di , i , data , ndata )
1159
1160
1161 local collapsing = di . data
1162 if data then
1163 i = i + 1
1164 while i < = ndata do
1165 local dn = data [ i ]
1166 local tg = dn . tg
1167 if tg = = " mn " then
1168 collapsing [ # collapsing + 1 ] = dn . data [ 1 ]
1169 dn . skip = " ignore "
1170 i = i + 1
1171 elseif tg = = " mo " then
1172 local d = dn . data [ 1 ]
1173 if d = = " . " then
1174 collapsing [ # collapsing + 1 ] = d
1175 dn . skip = " ignore "
1176 i = i + 1
1177 else
1178 break
1179 end
1180 else
1181 break
1182 end
1183 end
1184 end
1185 return i
1186 end
1187
1188
1189
1190 local apply_function = {
1191 {
1192 element = " mo " ,
1193
1194
1195 data = { " ⁡ " } ,
1196 nature = " mixed " ,
1197 }
1198 }
1199
1200 local functioncontent = { }
1201
1202 setmetatableindex ( functioncontent , function ( t , k )
1203 local v = { { content = k } }
1204 t [ k ] = v
1205 return v
1206 end )
1207
1208 local dummy_nucleus = {
1209 element = " mtext " ,
1210 data = { content = " " } ,
1211 nature = " inline " ,
1212 comment = " dummy nucleus " ,
1213 fulltag = " mtext>0 "
1214 }
1215
1216 local function accentchar ( d )
1217 for i = 1 , 3 do
1218 d = d . data
1219 if not d then
1220 return
1221 end
1222 d = d [ 1 ]
1223 if not d then
1224 return
1225 end
1226 local tg = d . tg
1227 if tg = = " mover " then
1228 local s = specifications [ d . fulltag ]
1229 local t = s . top
1230 if t then
1231 d = d . data [ 1 ]
1232 local d1 = d . data [ 1 ]
1233 d1 . content = utfchar ( t )
1234 d . data = { d1 }
1235 return d
1236 end
1237 elseif tg = = " munder " then
1238 local s = specifications [ d . fulltag ]
1239 local b = s . bottom
1240 if b then
1241 d = d . data [ 1 ]
1242 local d1 = d . data [ 1 ]
1243 d1 . content = utfchar ( b )
1244 d . data = { d1 }
1245 return d
1246 end
1247 end
1248 end
1249 end
1250
1251 local no_mrow = {
1252 mrow = true ,
1253 mfenced = true ,
1254 mfrac = true ,
1255 mroot = true ,
1256 msqrt = true ,
1257 mtable = true ,
1258 mi = true ,
1259 mo = true ,
1260 mn = true ,
1261 }
1262
1263 local function checkmath ( root )
1264 local data = root . data
1265 if data then
1266 local ndata = # data
1267 local roottg = root . tg
1268 if roottg = = " msubsup " then
1269
1270 local nucleus , superscript , subscript
1271 if ndata > 3 then
1272
1273 else
1274 for i = 1 , ndata do
1275 local di = data [ i ]
1276 if not di then
1277
1278 elseif di . content then
1279
1280 else
1281 local s = specifications [ di . fulltag ]
1282 if s . subscript then
1283 subscript = i
1284 elseif s . superscript then
1285 superscript = i
1286 else
1287 nucleus = i
1288 end
1289 end
1290 end
1291 if superscript or subscript then
1292
1293 local nuc = nucleus and data [ nucleus ]
1294 local sub = subscript and data [ subscript ]
1295 local sup = superscript and data [ superscript ]
1296 local n = 0
1297 if nuc then n = n + 1 ; data [ n ] = nuc end
1298 if sub then n = n + 1 ; data [ n ] = sub end
1299 if sup then n = n + 1 ; data [ n ] = sup end
1300 end
1301 end
1302
1303
1304
1305
1306
1307
1308
1309
1310 elseif roottg = = " mfenced " then
1311 local s = specifications [ root . fulltag ]
1312 local l , m , r = s . left , s . middle , s . right
1313 if l then
1314 l = utfchar ( l )
1315 end
1316 if m then
1317 local t = { }
1318 for i = 1 , # m do
1319 t [ i ] = utfchar ( m [ i ] )
1320 end
1321 m = concat ( t )
1322 end
1323 if r then
1324 r = utfchar ( r )
1325 end
1326 root . attributes = {
1327 open = l ,
1328 separators = m ,
1329 close = r ,
1330 }
1331 end
1332 if ndata = = 0 then
1333 root . skip = " comment "
1334 root . nota = " weird "
1335 return
1336 elseif ndata = = 1 then
1337 local d = data [ 1 ]
1338 if not d or d = = " " then
1339 root . skip = " comment "
1340 return
1341 elseif d . content then
1342 return
1343 else
1344 local tg = d . tg
1345 if automathrows and ( roottg = = " mrow " or roottg = = " mtext " ) then
1346
1347
1348 if no_mrow [ tg ] then
1349 root . skip = " comment "
1350 end
1351 elseif roottg = = " mo " then
1352 if tg = = " mo " then
1353 root . skip = " comment "
1354 end
1355 end
1356 end
1357 end
1358 local i = 1
1359 while i < = ndata do
1360 local di = data [ i ]
1361 if di and not di . content then
1362 local tg = di . tg
1363 if tg = = " math " then
1364
1365 di . skip = " comment "
1366 checkmath ( di )
1367 i = i + 1
1368 elseif tg = = " mover " then
1369 local s = specifications [ di . fulltag ]
1370 if s . accent then
1371 local t = s . top
1372 local d = di . data
1373
1374 di . attributes = {
1375 accent = " true " ,
1376 }
1377
1378 if t then
1379
1380 d [ 1 ] . data [ 1 ] . content = utfchar ( t )
1381 di . data = { d [ 2 ] , d [ 1 ] }
1382 end
1383 else
1384
1385 end
1386 checkmath ( di )
1387 i = i + 1
1388 elseif tg = = " munder " then
1389 local s = specifications [ di . fulltag ]
1390 if s . accent then
1391 local b = s . bottom
1392 local d = di . data
1393
1394 di . attributes = {
1395 accent = " true " ,
1396 }
1397
1398 if b then
1399
1400 d [ 2 ] . data [ 1 ] . content = utfchar ( b )
1401 end
1402 else
1403
1404 end
1405 checkmath ( di )
1406 i = i + 1
1407 elseif tg = = " munderover " then
1408 local s = specifications [ di . fulltag ]
1409 if s . accent then
1410 local t = s . top
1411 local b = s . bottom
1412 local d = di . data
1413
1414
1415 di . attributes = {
1416 accent = " true " ,
1417 accentunder = " true " ,
1418 }
1419
1420
1421 if t and b then
1422
1423 d [ 1 ] . data [ 1 ] . content = utfchar ( t )
1424 d [ 3 ] . data [ 1 ] . content = utfchar ( b )
1425 di . data = { d [ 2 ] , d [ 3 ] , d [ 1 ] }
1426 else
1427
1428 end
1429 else
1430
1431 end
1432 checkmath ( di )
1433 i = i + 1
1434 elseif tg = = " mstacker " then
1435 local d = di . data
1436 local d1 = d [ 1 ]
1437 local d2 = d [ 2 ]
1438 local d3 = d [ 3 ]
1439 local t1 = d1 and d1 . tg
1440 local t2 = d2 and d2 . tg
1441 local t3 = d3 and d3 . tg
1442 local m = nil
1443 local t = nil
1444 local b = nil
1445
1446
1447 if t1 = = " mstackermid " then
1448 m = accentchar ( d1 )
1449 if t2 = = " mstackertop " then
1450 if t3 = = " mstackerbot " then
1451 t = accentchar ( d2 )
1452 b = accentchar ( d3 )
1453 di . element = " munderover "
1454 di . data = { m or d1 . data [ 1 ] , b or d3 . data [ 1 ] , t or d2 . data [ 1 ] }
1455 else
1456 t = accentchar ( d2 )
1457 di . element = " mover "
1458 di . data = { m or d1 . data [ 1 ] , t or d2 . data [ 1 ] }
1459 end
1460 elseif t2 = = " mstackerbot " then
1461 if t3 = = " mstackertop " then
1462 b = accentchar ( d2 )
1463 t = accentchar ( d3 )
1464 di . element = " munderover "
1465 di . data = { m or d1 . data [ 1 ] , t or d3 . data [ 1 ] , m , b or d2 . data [ 1 ] }
1466 else
1467 b = accentchar ( d2 )
1468 di . element = " munder "
1469 di . data = { m or d1 . data [ 1 ] , b or d2 . data [ 1 ] }
1470 end
1471 else
1472
1473 end
1474 else
1475
1476 end
1477 if t or b then
1478 di . attributes = {
1479 accent = t and " true " or nil ,
1480 accentunder = b and " true " or nil ,
1481 }
1482 di . detail = nil
1483 end
1484 checkmath ( di )
1485 i = i + 1
1486 elseif tg = = " mroot " then
1487 local data = di . data
1488 local size = # data
1489 if size = = 1 then
1490
1491 di . element = " msqrt "
1492 elseif size = = 2 then
1493 data [ 1 ] , data [ 2 ] = data [ 2 ] , data [ 1 ]
1494 end
1495 checkmath ( di )
1496 i = i + 1
1497 elseif tg = = " break " then
1498 di . skip = " comment "
1499 i = i + 1
1500 elseif tg = = " mtext " then
1501
1502
1503 local data = di . data
1504 if # data > 1 then
1505 for i = 1 , # data do
1506 local di = data [ i ]
1507 local content = di . content
1508 if content then
1509 data [ i ] = {
1510 element = " mtext " ,
1511 nature = " inline " ,
1512 data = { di } ,
1513 n = 0 ,
1514 }
1515 elseif di . tg = = " math " then
1516 local di = di . data [ 1 ]
1517 if di then
1518 data [ i ] = di
1519 checkmath ( di )
1520 end
1521 end
1522 end
1523 di . element = " mrow "
1524
1525
1526 end
1527 checkmath ( di )
1528 i = i + 1
1529 elseif tg = = " mrow " and detail then
1530 di . detail = nil
1531 checkmath ( di )
1532 di = {
1533 element = " maction " ,
1534 nature = " display " ,
1535 attributes = { actiontype = detail } ,
1536 data = { di } ,
1537 n = 0 ,
1538 }
1539 data [ i ] = di
1540 i = i + 1
1541 else
1542 local category = di . mathcategory
1543 if category then
1544
1545 if category = = 1 then
1546 i = collapse ( di , i , data , ndata , detail , " mo " )
1547 elseif category = = 2 then
1548 i = collapse ( di , i , data , ndata , detail , " mi " )
1549 elseif category = = 3 then
1550 i = collapse ( di , i , data , ndata , detail , " mn " )
1551 elseif category = = 4 then
1552 i = collapse ( di , i , data , ndata , detail , " ms " )
1553 elseif category > = 1000 then
1554 local apply = category > = 2000
1555 if apply then
1556 category = category - 1000
1557 end
1558 if tg = = " mi " then
1559 if roottg = = " mrow " then
1560 root . skip = " comment "
1561 root . element = " function "
1562 end
1563 i = collapse ( di , i , data , ndata , detail , " mi " )
1564 local tag = functions [ category ]
1565 if tag then
1566 di . data = functioncontent [ tag ]
1567 end
1568 if apply then
1569 di . after = apply_function
1570 elseif automathapply then
1571 local following
1572 if i < = ndata then
1573
1574 following = data [ i ]
1575 else
1576 local parent = di . __p__
1577 if parent . tg = = " mrow " then
1578 parent = parent . __p__
1579 end
1580 local index = parent . __i__
1581 following = parent . data [ index + 1 ]
1582 end
1583 if following then
1584 local tg = following . tg
1585 if tg = = " mrow " or tg = = " mfenced " then
1586 di . after = apply_function
1587 end
1588 end
1589 end
1590 else
1591 checkmath ( di )
1592 i = i + 1
1593 end
1594 else
1595 checkmath ( di )
1596 i = i + 1
1597 end
1598 elseif automathnumber and tg = = " mn " then
1599 checkmath ( di )
1600 i = collapse_mn ( di , i , data , ndata )
1601 else
1602 checkmath ( di )
1603 i = i + 1
1604 end
1605 end
1606 else
1607 if parenttg ~ = " mtext " and di = = " " then
1608 data [ i ] = false
1609 end
1610 i = i + 1
1611 end
1612 end
1613 end
1614 end
1615
1616 local function stripmath ( di )
1617 if not di then
1618
1619 elseif di . content then
1620 return di
1621 else
1622 local tg = di . tg
1623 if tg = = " mtext " or tg = = " ms " then
1624 return di
1625 else
1626 local data = di . data
1627 local ndata = # data
1628 local n = 0
1629 for i = 1 , ndata do
1630 local d = data [ i ]
1631 if d and not d . content then
1632 d = stripmath ( d )
1633 end
1634 if d then
1635 local content = d . content
1636 if not content then
1637 n = n + 1
1638 d . __i__ = n
1639 data [ n ] = d
1640 elseif content = = " " or content = = " " then
1641 if di . tg = = " mspace " then
1642
1643 local parent = di . __p__
1644 local index = di . __i__
1645 local data = parent . data
1646 if index > 1 then
1647 local d = data [ index -1 ]
1648 if d . tg = = " mtext " then
1649 local dd = d . data
1650 local dn = dd [ # dd ]
1651 local dc = dn . content
1652 if dc then
1653 dn . content = dc . . content
1654 end
1655 end
1656 elseif index < ndata then
1657 local d = data [ index + 1 ]
1658 if d . tg = = " mtext " then
1659 local dd = d . data
1660 local dn = dd [ 1 ]
1661 local dc = dn . content
1662 if dc then
1663 dn . content = content . . dc
1664 end
1665 end
1666 end
1667 end
1668 else
1669 n = n + 1
1670 data [ n ] = d
1671 end
1672 end
1673 end
1674 for i = ndata , n + 1 , -1 do
1675 data [ i ] = nil
1676 end
1677 if # data > 0 then
1678 return di
1679 end
1680 end
1681 end
1682 end
1683
1684 function checks . math ( di )
1685 if di . skip = = " comment " then
1686
1687
1688 else
1689 local specification = specifications [ di . fulltag ]
1690 local mode = specification and specification . mode = = " display " and " block " or " inline "
1691 di . attributes = {
1692 [ " display " ] = mode ,
1693 [ " xmlns:m " ] = mathmlns ,
1694 }
1695
1696 if mode = = " inline " then
1697
1698 di . nature = " inline "
1699 else
1700 di . nature = " display "
1701 end
1702 if automathstrip then
1703 stripmath ( di )
1704 end
1705 checkmath ( di )
1706 end
1707 end
1708
1709
1710
1711
1712
1713 local function checked ( d )
1714 local n = # d
1715 if n = = 1 then
1716 local di = d [ 1 ]
1717 local tg = di . tg
1718 if tg = = " ignore " then
1719
1720 return 1
1721 elseif di . content then
1722 return 1
1723 else
1724 local dd = di . data
1725 if # dd > 0 and checked ( dd ) > 0 then
1726 return 1
1727 else
1728 return 0
1729 end
1730 end
1731 else
1732 local m = 0
1733 for i = 1 , n do
1734 local di = d [ i ]
1735 local tg = di . tg
1736 if tg = = " ignore " then
1737
1738 elseif di . content then
1739 m = m + 1
1740 d [ m ] = di
1741 else
1742 local dd = di . data
1743 if # dd > 0 and checked ( dd ) > 0 then
1744 m = m + 1
1745 d [ m ] = di
1746 end
1747 end
1748 end
1749 if m < n then
1750 for i = n , m + 1 , -1 do
1751 d [ i ] = nil
1752 end
1753 end
1754 return m
1755 end
1756 end
1757
1758 function checks . mrow ( di )
1759
1760
1761
1762
1763 end
1764
1765
1766
1767 local function flatten ( di )
1768 local r = di . __p__
1769 while r do
1770 local d = r . data
1771 local n = # d
1772 if d and n > 1 then
1773 n = checked ( d )
1774 end
1775 local tg = r . tg
1776 if n = = 1 and ( tg = = " mtext " or tg = = " mrow " ) then
1777 r . skip = " comment "
1778 r = r . __p__
1779 else
1780 break
1781 end
1782 end
1783 end
1784
1785 function checks . mtable ( di )
1786 flatten ( di )
1787 local d = di . data
1788 for i = 1 , # d do
1789 local d = d [ i ]
1790 if d . tg = = " mtr " then
1791 local d = d . data
1792 for i = 1 , # d do
1793 local d = d [ i ]
1794 if d . tg = = " mtd " then
1795
1796 elseif d . content then
1797 d . content = " "
1798 else
1799 d . skip = " comment "
1800 end
1801 end
1802 elseif d . content then
1803 d . content = " "
1804 else
1805 d . skip = " comment "
1806 end
1807 end
1808 end
1809
1810 do
1811
1812 local a , z , A , Z = 0x61 , 0x7A , 0x41 , 0x5A
1813
1814 function extras . mi ( di , element , n , fulltag )
1815 local str = di . data [ 1 ] . content
1816 if str and sub ( str , 1 , 1 ) ~ = " & " then
1817 for v in utfvalues ( str ) do
1818 if ( v > = a and v < = z ) or ( v > = A and v < = Z ) then
1819 local a = di . attributes
1820 if a then
1821 a . mathvariant = " normal "
1822 else
1823 di . attributes = { mathvariant = " normal " }
1824 end
1825 end
1826 end
1827 end
1828 end
1829
1830 end
1831
1832 function extras . msub ( di , element , n , fulltag )
1833
1834 local data = di . data
1835 if # data = = 1 then
1836 local d = data [ 1 ]
1837 data [ 2 ] = d
1838 d . __i__ = 2
1839 data [ 1 ] = dummy_nucleus
1840 end
1841 end
1842
1843 extras . msup = extras . msub
1844
1845end
1846
1847do
1848
1849 local registered = { }
1850
1851 function structurestags . setformulacontent ( n )
1852 registered [ locatedtag ( " formulacontent " ) ] = {
1853 n = n ,
1854 }
1855 end
1856
1857 function extras . formulacontent ( di , element , n , fulltag )
1858 local r = registered [ fulltag ]
1859 if r then
1860 setattribute ( di , " n " , r . n )
1861 end
1862 end
1863
1864end
1865
1866do
1867
1868 local registered = structures . sections . registered
1869
1870 local function resolve ( di , element , n , fulltag )
1871 local data = listdata [ fulltag ]
1872 if data then
1873 extras . addreference ( di , data . references )
1874 return true
1875 else
1876 local data = di . data
1877 if data then
1878 for i = 1 , # data do
1879 local di = data [ i ]
1880 if di then
1881 local ft = di . fulltag
1882 if ft and resolve ( di , element , n , ft ) then
1883 return true
1884 end
1885 end
1886 end
1887 end
1888 end
1889 end
1890
1891 function extras . section ( di , element , n , fulltag )
1892 local r = registered [ specifications [ fulltag ] . detail ]
1893 if r then
1894 setattribute ( di , " level " , r . level )
1895 end
1896 resolve ( di , element , n , fulltag )
1897 end
1898
1899 local floats = { }
1900
1901 function structurestags . setfloat ( options , method )
1902 floats [ locatedtag ( " float " ) ] = {
1903 options = options ,
1904 method = method ,
1905 }
1906 end
1907
1908 function extras . float ( di , element , n , fulltag )
1909 local hash = floats [ fulltag ]
1910 if hash then
1911 local method = hash . method
1912 if not method or method = = " " then
1913 method = " here "
1914 end
1915 setattribute ( di , " method " , method )
1916 local options = hash . options
1917 if options and options ~ = " " then
1918 options = settings_to_hash ( options )
1919 options [ method ] = nil
1920 options = concat ( sortedkeys ( options ) , " , " )
1921 if # options > 0 then
1922 setattribute ( di , " options " , options )
1923 end
1924 end
1925 end
1926 resolve ( di , element , n , fulltag )
1927 end
1928
1929
1930
1931 function structurestags . setlist ( n )
1932 local data = structures . lists . getresult ( n )
1933 if data then
1934 referencehash [ locatedtag ( " listitem " ) ] = data
1935 end
1936 end
1937
1938 function extras . listitem ( di , element , n , fulltag )
1939 local data = referencehash [ fulltag ]
1940 if data then
1941 extras . addinternal ( di , data . references )
1942 return true
1943 end
1944 end
1945
1946end
1947
1948do
1949
1950
1951
1952 function structurestags . setregister ( tag , n )
1953 local data = structures . registers . get ( tag , n )
1954 if data then
1955 referencehash [ locatedtag ( " registerlocation " ) ] = data
1956 end
1957 end
1958
1959 function extras . registerlocation ( di , element , n , fulltag )
1960 local data = referencehash [ fulltag ]
1961 if type ( data ) = = " table " then
1962 extras . addinternal ( di , data . references )
1963 return true
1964 else
1965
1966 end
1967 end
1968
1969 function extras . registerpages ( di , element , n , fulltag )
1970 local data = di . data
1971 for i = 1 , # data do
1972 local d = data [ i ]
1973 if d . content = = " " then
1974 d . content = " "
1975 end
1976 end
1977 end
1978
1979 function extras . registerseparator ( di , element , n , fulltag )
1980 local data = di . data
1981 for i = 1 , # data do
1982 local d = data [ i ]
1983 local c = d . content
1984 if type ( c ) = = " string " then
1985 d . content = lpegmatch ( p_stripper , c )
1986 end
1987 end
1988 end
1989
1990end
1991
1992do
1993
1994 local tabledata = { }
1995
1996 local function hascontent ( data )
1997 for i = 1 , # data do
1998 local di = data [ i ]
1999 if not di or di . tg = = " ignore " then
2000
2001 else
2002 local content = di . content
2003 if content = = " " then
2004
2005 elseif content then
2006 return true
2007 else
2008 local d = di . data
2009 if d and # d > 0 and hascontent ( d ) then
2010 return true
2011 end
2012 end
2013 end
2014 end
2015 end
2016
2017 function structurestags . settablecell ( rows , columns , align )
2018 if align > 0 or rows > 1 or columns > 1 then
2019 tabledata [ locatedtag ( " tablecell " ) ] = {
2020 rows = rows ,
2021 columns = columns ,
2022 align = align ,
2023 }
2024 end
2025 end
2026
2027 function structurestags . gettablecell ( fulltag )
2028 return tabledata [ fulltag ]
2029 end
2030
2031 function extras . tablecell ( di , element , n , fulltag )
2032 local hash = tabledata [ fulltag ]
2033 if hash then
2034 local columns = hash . columns
2035 if columns and columns > 1 then
2036 setattribute ( di , " columns " , columns )
2037 end
2038 local rows = hash . rows
2039 if rows and rows > 1 then
2040 setattribute ( di , " rows " , rows )
2041 end
2042 local align = hash . align
2043 if not align or align = = 0 then
2044
2045 elseif align = = 1 then
2046 setattribute ( di , " align " , " flushright " )
2047 elseif align = = 2 then
2048 setattribute ( di , " align " , " middle " )
2049 elseif align = = 3 then
2050 setattribute ( di , " align " , " flushleft " )
2051 end
2052 end
2053 end
2054
2055 local tabulatedata = { }
2056
2057 function structurestags . settabulatecell ( align , kind )
2058 if align > 0 or kind > 0 then
2059 tabulatedata [ locatedtag ( " tabulatecell " ) ] = {
2060 align = align ,
2061 kind = kind ,
2062 }
2063 end
2064 end
2065
2066 function structurestags . gettabulatecell ( fulltag )
2067 return tabulatedata [ fulltag ]
2068 end
2069
2070 function extras . tabulate ( di , element , n , fulltag )
2071 local data = di . data
2072 for i = 1 , # data do
2073 local di = data [ i ]
2074 if di . tg = = " tabulaterow " and not hascontent ( di . data ) then
2075 di . element = " "
2076 end
2077 end
2078 end
2079
2080 function extras . tabulatecell ( di , element , n , fulltag )
2081 local hash = tabulatedata [ fulltag ]
2082 if hash then
2083 local align = hash . align
2084 if not align or align = = 0 then
2085
2086 elseif align = = 1 then
2087 setattribute ( di , " align " , " flushleft " )
2088 elseif align = = 2 then
2089 setattribute ( di , " align " , " flushright " )
2090 elseif align = = 3 then
2091 setattribute ( di , " align " , " middle " )
2092 end
2093 local kind = hash . kind
2094 if kind = = 1 then
2095 setattribute ( di , " kind " , " strong " )
2096 elseif kind = = 2 then
2097 setattribute ( di , " kind " , " equals " )
2098 end
2099 end
2100 end
2101
2102end
2103
2104do
2105
2106 local usedpublications = { }
2107 local tagsindatasets = setmetatableindex ( " table " )
2108 local serialize = false
2109
2110 function structurestags . setpublication ( dataset , tag , rendering )
2111 usedpublications [ locatedtag ( " publication " ) ] = {
2112 dataset = dataset ,
2113 tag = tag ,
2114 rendering = rendering
2115 }
2116 tagsindatasets [ dataset ] [ tag ] = true
2117 if not serialize then
2118 structures . tags . registerextradata ( " btx " , function ( )
2119 local t = { " <btxdata> " }
2120 for dataset , used in sortedhash ( tagsindatasets ) do
2121 t [ # t + 1 ] = publications . converttoxml ( dataset , true , false , true , false , true , true )
2122 end
2123 t [ # t + 1 ] = " </btxdata> "
2124 return concat ( t , " \n " )
2125 end )
2126 end
2127 end
2128
2129 function extras . publication ( di , element , n , fulltag )
2130 local hash = usedpublications [ fulltag ]
2131 if hash then
2132 setattribute ( di , " dataset " , hash . dataset )
2133 setattribute ( di , " tag " , hash . tag )
2134 end
2135 end
2136
2137end
2138
2139do
2140
2141 local usedparagraphs = { }
2142
2143 function structurestags . setparagraph ( align )
2144 if align ~ = " " then
2145 usedparagraphs [ locatedtag ( " paragraph " ) ] = {
2146 dataset = dataset ,
2147 tag = tag ,
2148 align = align ,
2149 }
2150 end
2151 end
2152
2153 function extras . paragraph ( di , element , n , fulltag )
2154 local hash = usedparagraphs [ fulltag ]
2155 if hash then
2156 setattribute ( di , " align " , hash . align )
2157 end
2158 end
2159
2160end
2161
2162
2163
2164do
2165
2166 local f_detail = formatters [ ' detail="%s" ' ]
2167 local f_chain = formatters [ ' chain="%s" ' ]
2168 local f_index = formatters [ ' n="%s" ' ]
2169 local f_spacing = formatters [ ' <c p="%s">%s</c> ' ]
2170
2171 local f_empty_inline = formatters [ " <%s/> " ]
2172 local f_empty_mixed = formatters [ " %w<%s/>\n " ]
2173 local f_empty_display = formatters [ " \n%w<%s/>\n " ]
2174 local f_empty_inline_attr = formatters [ " <%s%s/> " ]
2175 local f_empty_mixed_attr = formatters [ " %w<%s%s/> " ]
2176 local f_empty_display_attr = formatters [ " \n%w<%s%s/>\n " ]
2177
2178 local f_begin_inline = formatters [ " <%s> " ]
2179 local f_begin_mixed = formatters [ " %w<%s> " ]
2180 local f_begin_display = formatters [ " \n%w<%s>\n " ]
2181 local f_begin_inline_attr = formatters [ " <%s%s> " ]
2182 local f_begin_mixed_attr = formatters [ " %w<%s%s> " ]
2183 local f_begin_display_attr = formatters [ " \n%w<%s%s>\n " ]
2184
2185 local f_end_inline = formatters [ " </%s> " ]
2186 local f_end_mixed = formatters [ " </%s>\n " ]
2187 local f_end_display = formatters [ " %w</%s>\n " ]
2188
2189 local f_begin_inline_comment = formatters [ " <!-- %s --><%s> " ]
2190 local f_begin_mixed_comment = formatters [ " %w<!-- %s --><%s> " ]
2191 local f_begin_display_comment = formatters [ " \n%w<!-- %s -->\n%w<%s>\n " ]
2192 local f_begin_inline_attr_comment = formatters [ " <!-- %s --><%s%s> " ]
2193 local f_begin_mixed_attr_comment = formatters [ " %w<!-- %s --><%s%s> " ]
2194 local f_begin_display_attr_comment = formatters [ " \n%w<!-- %s -->\n%w<%s%s>\n " ]
2195
2196 local f_comment_begin_inline = formatters [ " <!-- begin %s --> " ]
2197 local f_comment_begin_mixed = formatters [ " %w<!-- begin %s --> " ]
2198 local f_comment_begin_display = formatters [ " \n%w<!-- begin %s -->\n " ]
2199
2200 local f_comment_end_inline = formatters [ " <!-- end %s --> " ]
2201 local f_comment_end_mixed = formatters [ " <!-- end %s -->\n " ]
2202 local f_comment_end_display = formatters [ " %w<!-- end %s -->\n " ]
2203
2204 local f_metadata_begin = formatters [ " \n%w<metadata>\n " ]
2205 local f_metadata = formatters [ " %w<metavariable name=%q>%s</metavariable>\n " ]
2206 local f_metadata_end = formatters [ " %w</metadata>\n " ]
2207
2208 local function attributes ( a )
2209 local r = { }
2210 local n = 0
2211 for k , v in next , a do
2212 n = n + 1
2213 r [ n ] = f_attribute ( k , tostring ( v ) )
2214 end
2215 sort ( r )
2216 return concat ( r , " " )
2217 end
2218
2219 local function properties ( a )
2220 local r = { }
2221 local n = 0
2222 for k , v in next , a do
2223 n = n + 1
2224 r [ n ] = f_property ( exportproperties , k , tostring ( v ) )
2225 end
2226 sort ( r )
2227 return concat ( r , " " )
2228 end
2229
2230 local depth = 0
2231 local inline = 0
2232
2233 local function emptytag ( result , element , nature , di )
2234 local a = di . attributes
2235 if a then
2236 if nature = = " display " then
2237 result [ # result + 1 ] = f_empty_display_attr ( depth , namespaced [ element ] , attributes ( a ) )
2238 elseif nature = = " mixed " then
2239 result [ # result + 1 ] = f_empty_mixed_attr ( depth , namespaced [ element ] , attributes ( a ) )
2240 else
2241 result [ # result + 1 ] = f_empty_inline_attr ( namespaced [ element ] , attributes ( a ) )
2242 end
2243 else
2244 if nature = = " display " then
2245 result [ # result + 1 ] = f_empty_display ( depth , namespaced [ element ] )
2246 elseif nature = = " mixed " then
2247 result [ # result + 1 ] = f_empty_mixed ( depth , namespaced [ element ] )
2248 else
2249 result [ # result + 1 ] = f_empty_inline ( namespaced [ element ] )
2250 end
2251 end
2252 end
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272 local function stripspaces ( di )
2273 local d = di . data
2274 for i = 1 , # d do
2275 local di = d [ i ]
2276 if not di . tg then
2277 di . content = " "
2278 end
2279 end
2280 end
2281
2282 local function begintag ( result , element , nature , di , skip )
2283 local index = di . n
2284 local fulltag = di . fulltag
2285 local specification = specifications [ fulltag ] or { }
2286 local comment = di . comment
2287 local detail = specification . detail
2288 if skip = = " comment " then
2289 if show_comment then
2290 if nature = = " inline " or inline > 0 then
2291 result [ # result + 1 ] = f_comment_begin_inline ( namespaced [ element ] )
2292 inline = inline + 1
2293 elseif nature = = " mixed " then
2294 result [ # result + 1 ] = f_comment_begin_mixed ( depth , namespaced [ element ] )
2295 depth = depth + 1
2296 inline = 1
2297 else
2298 result [ # result + 1 ] = f_comment_begin_display ( depth , namespaced [ element ] )
2299 depth = depth + 1
2300 end
2301 end
2302 elseif skip then
2303
2304 else
2305
2306 local n = 0
2307 local r = { }
2308 if detail then
2309 detail = gsub ( detail , " [^A-Za-z0-9]+ " , " - " )
2310 specification . detail = detail
2311 n = n + 1
2312 r [ n ] = f_detail ( detail )
2313 end
2314 local parents = specification . parents
2315 if parents then
2316 parents = gsub ( parents , " [^A-Za-z0-9 ]+ " , " - " )
2317 specification . parents = parents
2318 n = n + 1
2319 r [ n ] = f_chain ( parents )
2320 end
2321 if indexing and index then
2322 n = n + 1
2323 r [ n ] = f_index ( index )
2324 end
2325
2326 local extra = extras [ element ]
2327 if extra then
2328 extra ( di , element , index , fulltag )
2329 end
2330
2331 if di . record then
2332 stripspaces ( di )
2333 end
2334
2335 if exportproperties then
2336 local p = specification . userdata
2337 if not p then
2338
2339 elseif exportproperties = = v_yes then
2340 n = n + 1
2341 r [ n ] = attributes ( p )
2342 else
2343 n = n + 1
2344 r [ n ] = properties ( p )
2345 end
2346 end
2347 local a = di . attributes
2348 if a then
2349 if trace_spacing then
2350 a . p = di . parnumber or 0
2351 end
2352 n = n + 1
2353 r [ n ] = attributes ( a )
2354 elseif trace_spacing then
2355 n = n + 1
2356 r [ n ] = attributes { p = di . parnumber or 0 }
2357 end
2358 if n = = 0 then
2359 if nature = = " inline " or inline > 0 then
2360 if show_comment and comment then
2361 result [ # result + 1 ] = f_begin_inline_comment ( comment , namespaced [ element ] )
2362 else
2363 result [ # result + 1 ] = f_begin_inline ( namespaced [ element ] )
2364 end
2365 inline = inline + 1
2366 elseif nature = = " mixed " then
2367 if show_comment and comment then
2368 result [ # result + 1 ] = f_begin_mixed_comment ( depth , comment , namespaced [ element ] )
2369 else
2370 result [ # result + 1 ] = f_begin_mixed ( depth , namespaced [ element ] )
2371 end
2372 depth = depth + 1
2373 inline = 1
2374 else
2375 if show_comment and comment then
2376 result [ # result + 1 ] = f_begin_display_comment ( depth , comment , depth , namespaced [ element ] )
2377 else
2378 result [ # result + 1 ] = f_begin_display ( depth , namespaced [ element ] )
2379 end
2380 depth = depth + 1
2381 end
2382 else
2383 r = concat ( r , " " , 1 , n )
2384 if nature = = " inline " or inline > 0 then
2385 if show_comment and comment then
2386 result [ # result + 1 ] = f_begin_inline_attr_comment ( comment , namespaced [ element ] , r )
2387 else
2388 result [ # result + 1 ] = f_begin_inline_attr ( namespaced [ element ] , r )
2389 end
2390 inline = inline + 1
2391 elseif nature = = " mixed " then
2392 if show_comment and comment then
2393 result [ # result + 1 ] = f_begin_mixed_attr_comment ( depth , comment , namespaced [ element ] , r )
2394 else
2395 result [ # result + 1 ] = f_begin_mixed_attr ( depth , namespaced [ element ] , r )
2396 end
2397 depth = depth + 1
2398 inline = 1
2399 else
2400 if show_comment and comment then
2401 result [ # result + 1 ] = f_begin_display_attr_comment ( depth , comment , depth , namespaced [ element ] , r )
2402 else
2403 result [ # result + 1 ] = f_begin_display_attr ( depth , namespaced [ element ] , r )
2404 end
2405 depth = depth + 1
2406 end
2407 end
2408 end
2409 used [ element ] [ detail or " " ] = { nature , specification . parents }
2410
2411 local metadata = specification . metadata
2412 if metadata then
2413 result [ # result + 1 ] = f_metadata_begin ( depth )
2414 for k , v in table . sortedpairs ( metadata ) do
2415 if v ~ = " " then
2416 result [ # result + 1 ] = f_metadata ( depth + 1 , k , lpegmatch ( p_entity , v ) )
2417 end
2418 end
2419 result [ # result + 1 ] = f_metadata_end ( depth )
2420 end
2421 end
2422
2423 local function endtag ( result , element , nature , di , skip )
2424 if skip = = " comment " then
2425 if show_comment then
2426 if nature = = " display " and ( inline = = 0 or inline = = 1 ) then
2427 depth = depth - 1
2428 result [ # result + 1 ] = f_comment_end_display ( depth , namespaced [ element ] )
2429 inline = 0
2430 elseif nature = = " mixed " and ( inline = = 0 or inline = = 1 ) then
2431 depth = depth - 1
2432 result [ # result + 1 ] = f_comment_end_mixed ( namespaced [ element ] )
2433 inline = 0
2434 else
2435 inline = inline - 1
2436 result [ # result + 1 ] = f_comment_end_inline ( namespaced [ element ] )
2437 end
2438 end
2439 elseif skip then
2440
2441 else
2442 if nature = = " display " and ( inline = = 0 or inline = = 1 ) then
2443 depth = depth - 1
2444 result [ # result + 1 ] = f_end_display ( depth , namespaced [ element ] )
2445 inline = 0
2446 elseif nature = = " mixed " and ( inline = = 0 or inline = = 1 ) then
2447 depth = depth - 1
2448 result [ # result + 1 ] = f_end_mixed ( namespaced [ element ] )
2449 inline = 0
2450 else
2451 inline = inline - 1
2452 result [ # result + 1 ] = f_end_inline ( namespaced [ element ] )
2453 end
2454 end
2455 end
2456
2457 local function flushtree ( result , data , nature )
2458 local nofdata = # data
2459 for i = 1 , nofdata do
2460 local di = data [ i ]
2461 if not di then
2462
2463 else
2464 local content = di . content
2465
2466 if content then
2467
2468 local content = lpegmatch ( p_entity , content )
2469 if i = = nofdata and sub ( content , -1 ) = = " \n " then
2470
2471 if trace_spacing then
2472 result [ # result + 1 ] = f_spacing ( di . parnumber or 0 , sub ( content , 1 , -2 ) )
2473 else
2474 result [ # result + 1 ] = sub ( content , 1 , -2 )
2475 end
2476 result [ # result + 1 ] = " "
2477 else
2478 if trace_spacing then
2479 result [ # result + 1 ] = f_spacing ( di . parnumber or 0 , content )
2480 else
2481 result [ # result + 1 ] = content
2482 end
2483 end
2484 elseif not di . collapsed then
2485 local element = di . element
2486 if not element then
2487
2488 elseif element = = " break " then
2489 emptytag ( result , element , nature , di )
2490 elseif element = = " " or di . skip = = " ignore " then
2491
2492 else
2493 if di . before then
2494 flushtree ( result , di . before , nature )
2495 end
2496 local natu = di . nature
2497 local skip = di . skip
2498 if di . breaknode then
2499 emptytag ( result , " break " , " display " , di )
2500 end
2501 begintag ( result , element , natu , di , skip )
2502 flushtree ( result , di . data , natu )
2503 endtag ( result , element , natu , di , skip )
2504 if di . after then
2505 flushtree ( result , di . after , nature )
2506 end
2507 end
2508 end
2509 end
2510 end
2511 end
2512
2513 local function breaktree ( tree , parent , parentelement )
2514 local data = tree . data
2515 if data then
2516 local nofdata = # data
2517 local prevelement
2518 local prevnature
2519 local prevparnumber
2520 local newdata = { }
2521 local nofnewdata = 0
2522 for i = 1 , nofdata do
2523 local di = data [ i ]
2524 if not di then
2525
2526 elseif di . skip = = " ignore " then
2527
2528elseif di . tg = = " ignore " then
2529
2530 elseif di . content then
2531 if di . samepar then
2532 prevparnumber = false
2533 else
2534 local parnumber = di . parnumber
2535 if prevnature = = " inline " and prevparnumber and prevparnumber ~ = parnumber then
2536 nofnewdata = nofnewdata + 1
2537 if trace_spacing then
2538 newdata [ nofnewdata ] = makebreaknode { type = " a " , p = prevparnumber , n = parnumber }
2539 else
2540 newdata [ nofnewdata ] = makebreaknode ( )
2541 end
2542 end
2543 prevelement = nil
2544 prevparnumber = parnumber
2545 end
2546 prevnature = " inline "
2547 nofnewdata = nofnewdata + 1
2548 newdata [ nofnewdata ] = di
2549 elseif not di . collapsed then
2550 local element = di . element
2551 if element = = " break " then
2552 if prevelement = = " break " then
2553 di . element = " "
2554 end
2555 prevelement = element
2556 prevnature = " display "
2557 nofnewdata = nofnewdata + 1
2558 newdata [ nofnewdata ] = di
2559 elseif element = = " " or di . skip = = " ignore " then
2560
2561 else
2562 if di . samepar then
2563 prevnature = " inline "
2564 prevparnumber = false
2565 else
2566 local nature = di . nature
2567 local parnumber = di . parnumber
2568 if prevnature = = " inline " and nature = = " inline " and prevparnumber and prevparnumber ~ = parnumber then
2569 nofnewdata = nofnewdata + 1
2570 if trace_spacing then
2571 newdata [ nofnewdata ] = makebreaknode { type = " b " , p = prevparnumber , n = parnumber }
2572 else
2573 newdata [ nofnewdata ] = makebreaknode ( )
2574 end
2575 end
2576 prevnature = nature
2577 prevparnumber = parnumber
2578 end
2579 prevelement = element
2580 breaktree ( di , tree , element )
2581 nofnewdata = nofnewdata + 1
2582 newdata [ nofnewdata ] = di
2583 end
2584 else
2585 if di . samepar then
2586 prevnature = " inline "
2587 prevparnumber = false
2588 else
2589 local nature = di . nature
2590 local parnumber = di . parnumber
2591 if prevnature = = " inline " and nature = = " inline " and prevparnumber and prevparnumber ~ = parnumber then
2592 nofnewdata = nofnewdata + 1
2593 if trace_spacing then
2594 newdata [ nofnewdata ] = makebreaknode { type = " c " , p = prevparnumber , n = parnumber }
2595 else
2596 newdata [ nofnewdata ] = makebreaknode ( )
2597 end
2598 end
2599 prevnature = nature
2600 prevparnumber = parnumber
2601 end
2602 nofnewdata = nofnewdata + 1
2603 newdata [ nofnewdata ] = di
2604 end
2605 end
2606 tree . data = newdata
2607 end
2608 end
2609
2610
2611
2612
2613 local function collapsetree ( tree )
2614
2615 for tag , trees in next , treehash do
2616 local d = trees [ 1 ] . data
2617
2618
2619 if d then
2620 local nd = # d
2621 if nd > 0 then
2622 for i = 2 , # trees do
2623 local currenttree = trees [ i ]
2624 local currentdata = currenttree . data
2625 local currentpar = currenttree . parnumber
2626 local previouspar = trees [ i -1 ] . parnumber
2627 currenttree . collapsed = true
2628
2629 if previouspar = = 0 or not ( di and di . content ) then
2630 previouspar = nil
2631 end
2632 for j = 1 , # currentdata do
2633 local cd = currentdata [ j ]
2634 if not cd or cd = = " " then
2635
2636 elseif cd . skip = = " ignore " then
2637
2638 elseif cd . content then
2639 if not currentpar then
2640
2641 elseif not previouspar then
2642
2643 elseif currentpar ~ = previouspar then
2644 nd = nd + 1
2645 if trace_spacing then
2646 d [ nd ] = makebreaknode { type = " d " , p = previouspar , n = currentpar }
2647 else
2648 d [ nd ] = makebreaknode ( )
2649 end
2650 end
2651 previouspar = currentpar
2652 nd = nd + 1
2653 d [ nd ] = cd
2654 else
2655 nd = nd + 1
2656 d [ nd ] = cd
2657 end
2658 currentdata [ j ] = false
2659 end
2660 end
2661 end
2662 end
2663 end
2664 end
2665
2666 local function finalizetree ( tree )
2667 for _ , finalizer in next , finalizers do
2668 finalizer ( tree )
2669 end
2670 end
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683 local function indextree ( tree )
2684 local data = tree . data
2685 if data then
2686 local n , new = 0 , { }
2687
2688 for i = 1 , # data do
2689 local d = data [ i ]
2690 if not d then
2691
2692 elseif d . content then
2693 n = n + 1
2694 new [ n ] = d
2695 elseif not d . collapsed then
2696 n = n + 1
2697 d . __i__ = n
2698 d . __p__ = tree
2699 indextree ( d )
2700 new [ n ] = d
2701 end
2702 end
2703 tree . data = new
2704
2705 end
2706 end
2707
2708 local function checktree ( tree )
2709 local data = tree . data
2710 if data then
2711
2712 for i = 1 , # data do
2713 local d = data [ i ]
2714 if type ( d ) = = " table " then
2715 local check = checks [ d . tg ]
2716 if check then
2717 check ( d , data , i )
2718 end
2719 checktree ( d )
2720 end
2721 end
2722
2723 end
2724 end
2725
2726 local function fixtree ( tree )
2727 local data = tree . data
2728 if data then
2729
2730 for i = 1 , # data do
2731 local d = data [ i ]
2732 if type ( d ) = = " table " then
2733 local fix = fixes [ d . tg ]
2734 if fix then
2735 fix ( d , data , i )
2736 end
2737 fixtree ( d )
2738 end
2739 end
2740
2741 end
2742 end
2743
2744 wrapups . flushtree = flushtree
2745 wrapups . breaktree = breaktree
2746 wrapups . collapsetree = collapsetree
2747 wrapups . finalizetree = finalizetree
2748 wrapups . indextree = indextree
2749 wrapups . checktree = checktree
2750 wrapups . fixtree = fixtree
2751
2752end
2753
2754
2755
2756local function push ( fulltag , depth )
2757 local tg , n , detail , element , nature , record
2758 local specification = specifications [ fulltag ]
2759 if specification then
2760 tg = specification . tagname
2761 n = specification . tagindex
2762 detail = specification . detail
2763 else
2764
2765 tg , n = lpegmatch ( tagsplitter , fulltag )
2766 n = tonumber ( n )
2767 end
2768 local p = properties [ tg ]
2769 if p then
2770 element = p . export or tg
2771 nature = p . nature or " inline "
2772 record = p . record
2773 end
2774 local treedata = tree . data
2775 local t = {
2776 tg = tg ,
2777 fulltag = fulltag ,
2778 detail = detail ,
2779 n = n ,
2780 element = element ,
2781 nature = nature ,
2782 data = { } ,
2783 attribute = currentattribute ,
2784 parnumber = currentparagraph ,
2785 record = record ,
2786 }
2787 treedata [ # treedata + 1 ] = t
2788 currentdepth = currentdepth + 1
2789 nesting [ currentdepth ] = fulltag
2790 treestack [ currentdepth ] = tree
2791 if trace_export then
2792 if detail and detail ~ = " " then
2793 report_export ( " %w<%s trigger=%q n=%q paragraph=%q index=%q detail=%q> " , currentdepth -1 , tg , n , currentattribute or 0 , currentparagraph or 0 , # treedata , detail )
2794 else
2795 report_export ( " %w<%s trigger=%q n=%q paragraph=%q index=%q> " , currentdepth -1 , tg , n , currentattribute or 0 , currentparagraph or 0 , # treedata )
2796 end
2797 end
2798 tree = t
2799 if tg = = " break " then
2800
2801 else
2802 local h = treehash [ fulltag ]
2803 if h then
2804 h [ # h + 1 ] = t
2805 else
2806 treehash [ fulltag ] = { t }
2807 end
2808 end
2809end
2810
2811local function pop ( )
2812 if currentdepth > 0 then
2813 local top = nesting [ currentdepth ]
2814 tree = treestack [ currentdepth ]
2815 currentdepth = currentdepth - 1
2816 if trace_export then
2817 if top then
2818 report_export ( " %w</%s> " , currentdepth , match ( top , " [^>]+ " ) )
2819 else
2820 report_export ( " </BAD> " )
2821 end
2822 end
2823 else
2824 report_export ( " %w<!-- too many pops --> " , currentdepth )
2825 end
2826end
2827
2828local function continueexport ( )
2829 if nofcurrentcontent > 0 then
2830 if trace_export then
2831 report_export ( " %w<!-- injecting pagebreak space --> " , currentdepth )
2832 end
2833 nofcurrentcontent = nofcurrentcontent + 1
2834 currentcontent [ nofcurrentcontent ] = " "
2835 end
2836end
2837
2838local function pushentry ( current )
2839 if not current then
2840
2841 return
2842 end
2843 current = current . taglist
2844 if not current then
2845
2846 return
2847 end
2848 if restart then
2849 continueexport ( )
2850 restart = false
2851 end
2852 local newdepth = # current
2853 local olddepth = currentdepth
2854 if trace_export then
2855 report_export ( " %w<!-- moving from depth %s to %s (%s) --> " , currentdepth , olddepth , newdepth , current [ newdepth ] )
2856 end
2857 if olddepth < = 0 then
2858 for i = 1 , newdepth do
2859 push ( current [ i ] , i )
2860 end
2861 else
2862 local difference
2863 if olddepth < newdepth then
2864 for i = 1 , olddepth do
2865 if current [ i ] ~ = nesting [ i ] then
2866 difference = i
2867 break
2868 end
2869 end
2870 else
2871 for i = 1 , newdepth do
2872 if current [ i ] ~ = nesting [ i ] then
2873 difference = i
2874 break
2875 end
2876 end
2877 end
2878 if difference then
2879 for i = olddepth , difference , -1 do
2880 pop ( )
2881 end
2882 for i = difference , newdepth do
2883 push ( current [ i ] , i )
2884 end
2885 elseif newdepth > olddepth then
2886 for i = olddepth + 1 , newdepth do
2887 push ( current [ i ] , i )
2888 end
2889 elseif newdepth < olddepth then
2890 for i = olddepth , newdepth , -1 do
2891 pop ( )
2892 end
2893 elseif trace_export then
2894 report_export ( " %w<!-- staying at depth %s (%s) --> " , currentdepth , newdepth , nesting [ newdepth ] or " ? " )
2895 end
2896 end
2897 return olddepth , newdepth
2898end
2899
2900local function pushcontent ( oldparagraph , newparagraph )
2901 if nofcurrentcontent > 0 then
2902 if oldparagraph then
2903 if currentcontent [ nofcurrentcontent ] = = " \n " then
2904 if trace_export then
2905 report_export ( " %w<!-- removing newline --> " , currentdepth )
2906 end
2907 nofcurrentcontent = nofcurrentcontent - 1
2908 end
2909 end
2910 local content = concat ( currentcontent , " " , 1 , nofcurrentcontent )
2911 if content = = " " then
2912
2913 elseif somespace [ content ] and oldparagraph then
2914
2915 else
2916 local olddepth , newdepth
2917 local list = taglist [ currentattribute ]
2918 if list then
2919 olddepth , newdepth = pushentry ( list )
2920 end
2921 if tree then
2922 local td = tree . data
2923 local nd = # td
2924 td [ nd + 1 ] = { parnumber = oldparagraph or currentparagraph , content = content }
2925 if trace_export then
2926 report_export ( " %w<!-- start content with length %s --> " , currentdepth , utflen ( content ) )
2927 report_export ( " %w%s " , currentdepth , ( gsub ( content , " \n " , " \\n " ) ) )
2928 report_export ( " %w<!-- stop content --> " , currentdepth )
2929 end
2930 if olddepth then
2931 for i = newdepth -1 , olddepth , -1 do
2932 pop ( )
2933 end
2934 end
2935 end
2936 end
2937 nofcurrentcontent = 0
2938 end
2939 if oldparagraph then
2940 pushentry ( makebreaklist ( currentnesting ) )
2941 if trace_export then
2942 report_export ( " %w<!-- break added between paragraph %a and %a --> " , currentdepth , oldparagraph , newparagraph )
2943 end
2944 end
2945end
2946
2947local function finishexport ( )
2948 if trace_export then
2949 report_export ( " %w<!-- start finalizing --> " , currentdepth )
2950 end
2951 if nofcurrentcontent > 0 then
2952 if somespace [ currentcontent [ nofcurrentcontent ] ] then
2953 if trace_export then
2954 report_export ( " %w<!-- removing space --> " , currentdepth )
2955 end
2956 nofcurrentcontent = nofcurrentcontent - 1
2957 end
2958 pushcontent ( )
2959 end
2960 for i = currentdepth , 1 , -1 do
2961 pop ( )
2962 end
2963 currentcontent = { }
2964 if trace_export then
2965 report_export ( " %w<!-- stop finalizing --> " , currentdepth )
2966 end
2967end
2968
2969
2970
2971local collectresults do
2972
2973 local nodecodes = nodes . nodecodes
2974 local gluecodes = nodes . gluecodes
2975 local listcodes = nodes . listcodes
2976 local whatsitcodes = nodes . whatsitcodes
2977
2978 local subtypes = nodes . subtypes
2979
2980 local hlist_code = nodecodes . hlist
2981 local vlist_code = nodecodes . vlist
2982 local glyph_code = nodecodes . glyph
2983 local glue_code = nodecodes . glue
2984 local kern_code = nodecodes . kern
2985 local disc_code = nodecodes . disc
2986 local whatsit_code = nodecodes . whatsit
2987 local localpar_code = nodecodes . localpar
2988
2989 local userskip_code = gluecodes . userskip
2990 local rightskip_code = gluecodes . rightskip
2991 local parfillskip_code = gluecodes . parfillskip
2992 local spaceskip_code = gluecodes . spaceskip
2993 local xspaceskip_code = gluecodes . xspaceskip
2994
2995 local linelist_code = listcodes . line
2996
2997 local userdefinedwhatsit_code = whatsitcodes . userdefined
2998
2999 local privateattribute = attributes . private
3000 local a_image = privateattribute ( ' image ' )
3001 local a_reference = privateattribute ( ' reference ' )
3002 local a_destination = privateattribute ( ' destination ' )
3003 local a_characters = privateattribute ( ' characters ' )
3004 local a_exportstatus = privateattribute ( ' exportstatus ' )
3005 local a_tagged = privateattribute ( ' tagged ' )
3006 local a_taggedpar = privateattribute ( " taggedpar " )
3007 local a_textblock = privateattribute ( " textblock " )
3008
3009 local inline_mark = nodes . pool . userids [ " margins.inline " ]
3010
3011 local nuts = nodes . nuts
3012
3013 local getnext = nuts . getnext
3014 local getdisc = nuts . getdisc
3015 local getlist = nuts . getlist
3016 local getid = nuts . getid
3017 local getattr = nuts . getattr
3018 local setattr = nuts . setattr
3019 local isglyph = nuts . isglyph
3020 local getkern = nuts . getkern
3021 local getwidth = nuts . getwidth
3022
3023 local start_of_par = nuts . start_of_par
3024
3025 local nexthlist = nuts . traversers . hlist
3026 local nextnode = nuts . traversers . node
3027
3028 local function addtomaybe ( maybewrong , c , case )
3029 if trace_export then
3030 report_export ( " %w<!-- possible paragraph mixup at %C case %i --> " , currentdepth , c , case )
3031 else
3032 local s = formatters [ " %C " ] ( c )
3033 if maybewrong then
3034 maybewrong [ # maybewrong + 1 ] = s
3035 else
3036 maybewrong = { s }
3037 end
3038 return maybewrong
3039 end
3040 end
3041
3042 local function showmaybe ( maybewrong )
3043 if not trace_export then
3044 report_export ( " fuzzy paragraph: % t " , maybewrong )
3045 end
3046 end
3047
3048 local function showdetail ( n , id , subtype )
3049 local a = getattr ( n , a_tagged )
3050 local t = taglist [ a ]
3051 local c = nodecodes [ id ]
3052 local s = subtypes [ id ] [ subtype ]
3053 if a and t then
3054 report_export ( " node %a, subtype %a, tag %a, element %a, tree '% t' " , c , s , a , t . tagname , t . taglist )
3055 else
3056 report_export ( " node %a, subtype %a, untagged " , c , s )
3057 end
3058 end
3059
3060 local function collectresults ( head , list , pat , pap )
3061 local p
3062 local localparagraph
3063 local maybewrong
3064 local pid
3065 for n , id , subtype in nextnode , head do
3066 if trace_details then
3067 showdetail ( n , id , subtype )
3068 end
3069 if id = = glyph_code then
3070 local c , f = isglyph ( n )
3071 local at = getattr ( n , a_tagged ) or pat
3072 if not at then
3073
3074
3075
3076 else
3077 if last ~ = at then
3078 local tl = taglist [ at ]
3079 local ap = getattr ( n , a_taggedpar ) or pap
3080 if localparagraph and ( not ap or ap < localparagraph ) then
3081 maybewrong = addtomaybe ( maybewrong , c , 1 )
3082 end
3083 pushcontent ( )
3084 currentnesting = tl
3085 currentparagraph = ap
3086 currentattribute = at
3087 last = at
3088 pushentry ( currentnesting )
3089 if trace_export then
3090 report_export ( " %w<!-- processing glyph %C tagged %a --> " , currentdepth , c , at )
3091 end
3092
3093
3094 local r = getattr ( n , a_reference )
3095 if r then
3096 local t = tl . taglist
3097 referencehash [ t [ # t ] ] = r
3098 end
3099 local d = getattr ( n , a_destination )
3100 if d then
3101 local t = tl . taglist
3102 destinationhash [ t [ # t ] ] = d
3103 end
3104
3105 elseif last then
3106
3107
3108
3109 local ap = getattr ( n , a_taggedpar ) or pap
3110 if ap ~ = currentparagraph then
3111 pushcontent ( currentparagraph , ap )
3112 pushentry ( currentnesting )
3113 currentattribute = last
3114 currentparagraph = ap
3115 end
3116 if localparagraph and ( not ap or ap < localparagraph ) then
3117 maybewrong = addtomaybe ( maybewrong , c , 2 )
3118 end
3119 if trace_export then
3120 report_export ( " %w<!-- processing glyph %C tagged %a --> " , currentdepth , c , last )
3121 end
3122 else
3123 if trace_export then
3124 report_export ( " %w<!-- processing glyph %C tagged %a --> " , currentdepth , c , at )
3125 end
3126 end
3127 local s = getattr ( n , a_exportstatus )
3128 if s then
3129 c = s
3130 end
3131 if c = = 0 then
3132 if trace_export then
3133 report_export ( " %w<!-- skipping last glyph --> " , currentdepth )
3134 end
3135 elseif c = = 0x20 then
3136 local a = getattr ( n , a_characters )
3137 nofcurrentcontent = nofcurrentcontent + 1
3138 if a then
3139 if trace_export then
3140 report_export ( " %w<!-- turning last space into special space %U --> " , currentdepth , a )
3141 end
3142 currentcontent [ nofcurrentcontent ] = specialspaces [ a ]
3143 else
3144 currentcontent [ nofcurrentcontent ] = " "
3145 end
3146 else
3147 local fc = fontchar [ f ]
3148 if fc then
3149 fc = fc and fc [ c ]
3150 if fc then
3151 local u = fc . unicode
3152 if not u then
3153 nofcurrentcontent = nofcurrentcontent + 1
3154 currentcontent [ nofcurrentcontent ] = utfchar ( c )
3155 elseif type ( u ) = = " table " then
3156 for i = 1 , # u do
3157 nofcurrentcontent = nofcurrentcontent + 1
3158 currentcontent [ nofcurrentcontent ] = utfchar ( u [ i ] )
3159 end
3160 else
3161 nofcurrentcontent = nofcurrentcontent + 1
3162 currentcontent [ nofcurrentcontent ] = utfchar ( u )
3163 end
3164 elseif c > 0 then
3165 nofcurrentcontent = nofcurrentcontent + 1
3166 currentcontent [ nofcurrentcontent ] = utfchar ( c )
3167 else
3168
3169 end
3170 elseif c > 0 then
3171 nofcurrentcontent = nofcurrentcontent + 1
3172 currentcontent [ nofcurrentcontent ] = utfchar ( c )
3173 else
3174
3175 end
3176 end
3177 end
3178 elseif id = = disc_code then
3179 local pre , post , replace = getdisc ( n )
3180 if keephyphens then
3181 if pre and not getnext ( pre ) and isglyph ( pre ) = = 0xAD then
3182 nofcurrentcontent = nofcurrentcontent + 1
3183 currentcontent [ nofcurrentcontent ] = hyphen
3184 end
3185 end
3186 if replace then
3187 collectresults ( replace , nil )
3188 end
3189 elseif id = = glue_code then
3190
3191 local ca = getattr ( n , a_characters )
3192 if ca = = 0 then
3193
3194 elseif ca then
3195 local a = getattr ( n , a_tagged ) or pat
3196 if a then
3197 local c = specialspaces [ ca ]
3198 if last ~ = a then
3199 local tl = taglist [ a ]
3200 if trace_export then
3201 report_export ( " %w<!-- processing space glyph %U tagged %a case 1 --> " , currentdepth , ca , a )
3202 end
3203 pushcontent ( )
3204 currentnesting = tl
3205 currentparagraph = getattr ( n , a_taggedpar ) or pap
3206 currentattribute = a
3207 last = a
3208 pushentry ( currentnesting )
3209
3210 elseif last then
3211 local ap = getattr ( n , a_taggedpar ) or pap
3212 if ap ~ = currentparagraph then
3213 pushcontent ( currentparagraph , ap )
3214 pushentry ( currentnesting )
3215 currentattribute = last
3216 currentparagraph = ap
3217 end
3218 if trace_export then
3219 report_export ( " %w<!-- processing space glyph %U tagged %a case 2 --> " , currentdepth , ca , last )
3220 end
3221 end
3222
3223
3224
3225
3226
3227
3228 nofcurrentcontent = nofcurrentcontent + 1
3229 currentcontent [ nofcurrentcontent ] = c
3230 end
3231 elseif subtype = = userskip_code then
3232 if getwidth ( n ) > threshold then
3233 if last and not somespace [ currentcontent [ nofcurrentcontent ] ] then
3234 local a = getattr ( n , a_tagged ) or pat
3235 if a = = last then
3236 if trace_export then
3237 report_export ( " %w<!-- injecting spacing 5a --> " , currentdepth )
3238 end
3239 nofcurrentcontent = nofcurrentcontent + 1
3240 currentcontent [ nofcurrentcontent ] = " "
3241 elseif a then
3242
3243 if trace_export then
3244 report_export ( " %w<!-- processing glue > threshold tagged %s becomes %s --> " , currentdepth , last , a )
3245 end
3246 pushcontent ( )
3247 if trace_export then
3248 report_export ( " %w<!-- injecting spacing 5b --> " , currentdepth )
3249 end
3250 last = a
3251 nofcurrentcontent = nofcurrentcontent + 1
3252 currentcontent [ nofcurrentcontent ] = " "
3253 currentnesting = taglist [ last ]
3254 pushentry ( currentnesting )
3255 currentattribute = last
3256 end
3257 end
3258 end
3259 elseif subtype = = spaceskip_code or subtype = = xspaceskip_code then
3260 if not somespace [ currentcontent [ nofcurrentcontent ] ] then
3261 local a = getattr ( n , a_tagged ) or pat
3262 if a = = last then
3263 if trace_export then
3264 report_export ( " %w<!-- injecting spacing 7 (stay in element) --> " , currentdepth )
3265 end
3266 nofcurrentcontent = nofcurrentcontent + 1
3267 currentcontent [ nofcurrentcontent ] = " "
3268 else
3269 if trace_export then
3270 report_export ( " %w<!-- injecting spacing 7 (end of element) --> " , currentdepth )
3271 end
3272 last = a
3273 pushcontent ( )
3274 nofcurrentcontent = nofcurrentcontent + 1
3275 currentcontent [ nofcurrentcontent ] = " "
3276 currentnesting = taglist [ last ]
3277 pushentry ( currentnesting )
3278 currentattribute = last
3279 end
3280 end
3281 elseif subtype = = rightskip_code then
3282
3283 if nofcurrentcontent > 0 then
3284 local r = currentcontent [ nofcurrentcontent ]
3285 if r = = hyphen then
3286 if not keephyphens then
3287 nofcurrentcontent = nofcurrentcontent - 1
3288 end
3289 elseif pid = = disc_code then
3290
3291 elseif not somespace [ r ] then
3292 local a = getattr ( n , a_tagged ) or pat
3293 if a = = last then
3294 if trace_export then
3295 report_export ( " %w<!-- injecting spacing 1 (end of line, stay in element) --> " , currentdepth )
3296 end
3297 nofcurrentcontent = nofcurrentcontent + 1
3298 currentcontent [ nofcurrentcontent ] = " "
3299 else
3300 if trace_export then
3301 report_export ( " %w<!-- injecting spacing 1 (end of line, end of element) --> " , currentdepth )
3302 end
3303 last = a
3304 pushcontent ( )
3305 nofcurrentcontent = nofcurrentcontent + 1
3306 currentcontent [ nofcurrentcontent ] = " "
3307 currentnesting = taglist [ last ]
3308 pushentry ( currentnesting )
3309 currentattribute = last
3310 end
3311 end
3312 end
3313 elseif subtype = = parfillskip_code then
3314
3315
3316 if maybewrong then
3317 showmaybe ( maybewrong )
3318 end
3319 return
3320 end
3321 elseif id = = hlist_code or id = = vlist_code then
3322 local ai = getattr ( n , a_image )
3323 if ai then
3324 local at = getattr ( n , a_tagged ) or pat
3325 if nofcurrentcontent > 0 then
3326 pushcontent ( )
3327 pushentry ( currentnesting )
3328 end
3329 pushentry ( taglist [ at ] )
3330 if trace_export then
3331 report_export ( " %w<!-- processing image tagged %a " , currentdepth , last )
3332 end
3333 last = nil
3334 currentparagraph = nil
3335 else
3336
3337 local list = getlist ( n )
3338 if list then
3339
3340 local at = getattr ( n , a_tagged ) or pat
3341 collectresults ( list , n , at )
3342 end
3343 end
3344 elseif id = = kern_code then
3345 local kern = getkern ( n )
3346 if kern > 0 then
3347local a = getattr ( n , a_tagged ) or pat
3348local t = taglist [ a ]
3349if not t or t . tagname ~ = " ignore " then
3350 local limit = threshold
3351 if p then
3352 local c , f = isglyph ( p )
3353 if c then
3354 limit = fontquads [ f ] / 4
3355 end
3356 end
3357 if kern > limit then
3358 if last and not somespace [ currentcontent [ nofcurrentcontent ] ] then
3359
3360 if a = = last then
3361 if not somespace [ currentcontent [ nofcurrentcontent ] ] then
3362 if trace_export then
3363 report_export ( " %w<!-- injecting spacing 8 (kern %p) --> " , currentdepth , kern )
3364 end
3365 nofcurrentcontent = nofcurrentcontent + 1
3366 currentcontent [ nofcurrentcontent ] = " "
3367 end
3368 elseif a then
3369
3370 if trace_export then
3371 report_export ( " %w<!-- processing kern, threshold %p, tag %s => %s --> " , currentdepth , limit , last , a )
3372 end
3373 last = a
3374 pushcontent ( )
3375 if trace_export then
3376 report_export ( " %w<!-- injecting spacing 9 (kern %p) --> " , currentdepth , kern )
3377 end
3378 nofcurrentcontent = nofcurrentcontent + 1
3379 currentcontent [ nofcurrentcontent ] = " "
3380
3381currentnesting = t
3382 pushentry ( currentnesting )
3383 currentattribute = last
3384 end
3385 end
3386 end
3387end
3388 end
3389 elseif id = = whatsit_code then
3390 if subtype = = userdefinedwhatsit_code then
3391
3392 local at = getattr ( n , a_tagged )
3393 if nofcurrentcontent > 0 then
3394 pushcontent ( )
3395 pushentry ( currentnesting )
3396 end
3397 pushentry ( taglist [ at ] )
3398 if trace_export then
3399 report_export ( " %w<!-- processing anchor tagged %a " , currentdepth , last )
3400 end
3401 last = nil
3402 currentparagraph = nil
3403 end
3404 elseif not localparagraph and id = = localpar_code and start_of_par ( n ) then
3405 localparagraph = getattr ( n , a_taggedpar )
3406 end
3407 p = n
3408 pid = id
3409 end
3410 if maybewrong then
3411 showmaybe ( maybewrong )
3412 end
3413 end
3414
3415 function nodes . handlers . export ( head )
3416 starttiming ( treehash )
3417 if trace_export then
3418 report_export ( " %w<!-- start flushing page --> " , currentdepth )
3419 end
3420
3421 restart = true
3422 collectresults ( head )
3423 if trace_export then
3424 report_export ( " %w<!-- stop flushing page --> " , currentdepth )
3425 end
3426 stoptiming ( treehash )
3427 return head
3428 end
3429
3430 function nodes . handlers . checkparcounter ( p )
3431 setattr ( p , a_taggedpar , texgetcount ( " tagparcounter " ) + 1 )
3432 return p
3433 end
3434
3435 function builders . paragraphs . tag ( head )
3436 noftextblocks = noftextblocks + 1
3437 for n , subtype in nexthlist , head do
3438 if subtype = = linelist_code then
3439 setattr ( n , a_textblock , noftextblocks )
3440 elseif subtype = = glue_code or subtype = = kern_code then
3441 setattr ( n , a_textblock , 0 )
3442 end
3443 end
3444 return false
3445 end
3446
3447end
3448
3449do
3450
3451 local xmlcollected = xml . collected
3452 local xmlsetcomment = xml . setcomment
3453
3454local xmlpreamble = [[
3455<?xml version="1.0" encoding="UTF-8" standalone="%standalone%" ?>
3456
3457<!--
3458
3459 input filename : %filename%
3460 processing date : %date%
3461 context version : %contextversion%
3462 exporter version : %exportversion%
3463
3464-->
3465
3466 ]]
3467
3468 local flushtree = wrapups . flushtree
3469
3470 local function wholepreamble ( standalone )
3471 return replacetemplate ( xmlpreamble , {
3472 standalone = standalone and " yes " or " no " ,
3473 filename = tex . jobname ,
3474 date = included . date and backends . timestamp ( ) ,
3475 contextversion = environment . version ,
3476 exportversion = exportversion ,
3477 } )
3478 end
3479
3480
3481local csspreamble = [[
3482<?xml-stylesheet type="text/css" href="%filename%" ?>
3483 ]]
3484
3485local cssheadlink = [[
3486<link type="text/css" rel="stylesheet" href="%filename%" />
3487 ]]
3488
3489 local function allusedstylesheets ( cssfiles , files , path )
3490 local done = { }
3491 local result = { }
3492 local extras = { }
3493 for i = 1 , # cssfiles do
3494 local cssfile = cssfiles [ i ]
3495 if type ( cssfile ) ~ = " string " then
3496
3497 elseif cssfile = = " export-example.css " then
3498
3499 elseif not done [ cssfile ] then
3500 cssfile = file . join ( path , cssfile )
3501 report_export ( " adding css reference '%s' " , cssfile )
3502 files [ # files + 1 ] = cssfile
3503 result [ # result + 1 ] = replacetemplate ( csspreamble , { filename = cssfile } )
3504 extras [ # extras + 1 ] = replacetemplate ( cssheadlink , { filename = cssfile } )
3505 done [ cssfile ] = true
3506 end
3507 end
3508 return concat ( result ) , concat ( extras )
3509 end
3510
3511local elementtemplate = [[
3512/* element="%element%" detail="%detail%" chain="%chain%" */
3513
3514%element%,
3515%namespace%div.%element% {
3516 display: %display% ;
3517} ]]
3518
3519local detailtemplate = [[
3520/* element="%element%" detail="%detail%" chain="%chain%" */
3521
3522%element%[detail=%detail%],
3523%namespace%div.%element%.%detail% {
3524 display: %display% ;
3525} ]]
3526
3527
3528
3529local htmltemplate = [[
3530%preamble%
3531
3532<html xmlns="http://www.w3.org/1999/xhtml" xmlns:math="http://www.w3.org/1998/Math/MathML">
3533
3534 <head>
3535
3536 <meta charset="utf-8"/>
3537
3538 <title>%title%</title>
3539
3540%style%
3541
3542 </head>
3543 <body>
3544 <div class="document" xmlns="http://www.pragma-ade.com/context/export">
3545
3546<div class="warning">Rendering can be suboptimal because there is no default/fallback css loaded.</div>
3547
3548%body%
3549
3550 </div>
3551 </body>
3552</html>
3553 ]]
3554
3555 local displaymapping = {
3556 inline = " inline " ,
3557 display = " block " ,
3558 mixed = " inline " ,
3559 }
3560
3561 local function allusedelements ( basename )
3562 local result = { replacetemplate ( namespacetemplate , {
3563 what = " template " ,
3564 filename = basename ,
3565 namespace = contextns ,
3566
3567 cssnamespaceurl = cssnamespaceurl ,
3568 } , false , true ) }
3569 for element , details in sortedhash ( used ) do
3570 if namespaces [ element ] then
3571
3572 else
3573 for detail , what in sortedhash ( details ) do
3574 local nature = what [ 1 ] or " display "
3575 local chain = what [ 2 ]
3576 local display = displaymapping [ nature ] or " block "
3577 if detail = = " " then
3578 result [ # result + 1 ] = replacetemplate ( elementtemplate , {
3579 element = element ,
3580 display = display ,
3581 chain = chain ,
3582 namespace = usecssnamespace and namespace or " " ,
3583 } )
3584 else
3585 result [ # result + 1 ] = replacetemplate ( detailtemplate , {
3586 element = element ,
3587 display = display ,
3588 detail = detail ,
3589 chain = chain ,
3590 namespace = usecssnamespace and cssnamespace or " " ,
3591 } )
3592 end
3593 end
3594 end
3595 end
3596 return concat ( result , " \n\n " )
3597 end
3598
3599 local function allcontent ( tree , embed )
3600 local result = { }
3601 flushtree ( result , tree . data , " display " )
3602 result = concat ( result )
3603
3604 result = gsub ( result , " \n *\n " , " \n " )
3605 result = gsub ( result , " \n +([^< ]) " , " \n%1 " )
3606 return result
3607 end
3608
3609
3610
3611
3612
3613
3614
3615
3616 local function cleanxhtmltree ( xmltree )
3617 if xmltree then
3618 local implicits = { }
3619 local explicits = { }
3620 local overloads = { }
3621 for e in xmlcollected ( xmltree , " * " ) do
3622 local at = e . at
3623 if at then
3624 local explicit = at . explicit
3625 local implicit = at . implicit
3626 if explicit then
3627 if not explicits [ explicit ] then
3628 explicits [ explicit ] = true
3629 at . id = explicit
3630 if implicit then
3631 overloads [ implicit ] = explicit
3632 end
3633 end
3634 else
3635 if implicit and not implicits [ implicit ] then
3636 implicits [ implicit ] = true
3637 at . id = " aut: " . . implicit
3638 end
3639 end
3640 end
3641 end
3642 for e in xmlcollected ( xmltree , " * " ) do
3643 local at = e . at
3644 if at then
3645 local internal = at . internal
3646 local location = at . location
3647 if internal then
3648 if location then
3649 local explicit = overloads [ location ]
3650 if explicit then
3651 at . href = " # " . . explicit
3652 else
3653 at . href = " #aut: " . . internal
3654 end
3655 else
3656 at . href = " #aut: " . . internal
3657 end
3658 else
3659 if location then
3660 at . href = " # " . . location
3661 else
3662 local url = at . url
3663 if url then
3664 at . href = url
3665 else
3666 local file = at . file
3667 if file then
3668 at . href = file
3669 end
3670 end
3671 end
3672 end
3673 end
3674 end
3675 return xmltree
3676 else
3677 return xml . convert ( ' <?xml version="1.0"?>\n<error>invalid xhtml tree</error> ' )
3678 end
3679 end
3680
3681
3682
3683 local private = {
3684 destination = true ,
3685 prefix = true ,
3686 reference = true ,
3687
3688 id = true ,
3689 href = true ,
3690
3691 implicit = true ,
3692 explicit = true ,
3693
3694 url = true ,
3695 file = true ,
3696 internal = true ,
3697 location = true ,
3698
3699 name = true ,
3700 used = true ,
3701 page = true ,
3702 width = true ,
3703 height = true ,
3704
3705 }
3706
3707 local addclicks = true
3708 local f_onclick = formatters [ [[ location.href='%s' ]] ]
3709 local f_onclick = formatters [ [[ location.href='%s' ]] ]
3710
3711 local p_cleanid = lpeg . replacer { [ " : " ] = " - " }
3712 local p_cleanhref = lpeg . Cs ( lpeg . P ( " # " ) * p_cleanid )
3713
3714 local p_splitter = lpeg . Ct ( (
3715 lpeg . Carg ( 1 ) * lpeg . C ( ( 1 - lpeg . P ( " " ) ) ^ 1 ) / function ( d , s ) if not d [ s ] then d [ s ] = true return s end end
3716 * lpeg . P ( " " ) ^ 0 ) ^ 1 )
3717
3718
3719 local classes = table . setmetatableindex ( function ( t , k )
3720 local v = concat ( lpegmatch ( p_splitter , k , 1 , { } ) , " " )
3721 t [ k ] = v
3722 return v
3723 end )
3724
3725 local function makeclass ( tg , at )
3726 local detail = at . detail
3727 local chain = at . chain
3728 local extra = nil
3729 local classes = { }
3730 local nofclasses = 0
3731 at . detail = nil
3732 at . chain = nil
3733 for k , v in next , at do
3734 if not private [ k ] then
3735 nofclasses = nofclasses + 1
3736 classes [ nofclasses ] = k . . " - " . . v
3737 end
3738 end
3739 if detail and detail ~ = " " then
3740 if chain and chain ~ = " " then
3741 if chain ~ = detail then
3742 extra = classes [ tg . . " " . . chain . . " " . . detail ]
3743 elseif tg ~ = detail then
3744 extra = detail
3745 end
3746 elseif tg ~ = detail then
3747 extra = detail
3748 end
3749 elseif chain and chain ~ = " " then
3750 if tg ~ = chain then
3751 extra = chain
3752 end
3753 end
3754
3755 if nofclasses > 0 then
3756 sort ( classes )
3757 classes = concat ( classes , " " )
3758 if extra then
3759 return tg . . " " . . extra . . " " . . classes
3760 else
3761 return tg . . " " . . classes
3762 end
3763 else
3764 if extra then
3765 return tg . . " " . . extra
3766 else
3767 return tg
3768 end
3769 end
3770 end
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782 local crappycss = {
3783 table = " table " , tabulate = " table " ,
3784 tablehead = " thead " , tabulatehead = " thead " ,
3785 tablebody = " tbody " , tabulatebody = " tbody " ,
3786 tablefoot = " tfoot " , tabulatefoot = " tfoot " ,
3787 tablerow = " tr " , tabulaterow = " tr " ,
3788 tablecell = " td " , tabulatecell = " td " ,
3789 }
3790
3791 local cssmapping = false
3792
3793 directives . register ( " export.nativetags " , function ( v )
3794 cssmapping = v and crappycss or false
3795 end )
3796
3797 local function remap ( specification , source , target )
3798 local comment = nil
3799 for c in xmlcollected ( source , " * " ) do
3800 if not c . special then
3801 local tg = c . tg
3802 local ns = c . ns
3803 if ns = = " m " then
3804 if false then
3805 c . ns = " "
3806 c . at [ " xmlns:m " ] = nil
3807 end
3808
3809
3810 else
3811 local dt = c . dt
3812 local nt = # dt
3813 if nt = = 0 or ( nt = = 1 and dt [ 1 ] = = " " ) then
3814 if comment then
3815 c . dt = comment
3816 else
3817 xmlsetcomment ( c , " empty " )
3818 comment = c . dt
3819 end
3820 end
3821 local at = c . at
3822 local class = nil
3823 local label = nil
3824 if tg = = " document " then
3825 at . href = nil
3826 at . detail = nil
3827 at . chain = nil
3828 elseif tg = = " metavariable " then
3829 label = at . name
3830 at . detail = " metaname- " . . label
3831 class = makeclass ( tg , at )
3832 else
3833 class = makeclass ( tg , at )
3834 end
3835 local id = at . id
3836 local href = at . href
3837 local attr = nil
3838 if id then
3839 id = lpegmatch ( p_cleanid , id ) or id
3840 if href then
3841 href = lpegmatch ( p_cleanhref , href ) or href
3842 attr = {
3843 class = class ,
3844 id = id ,
3845 href = href ,
3846 onclick = addclicks and f_onclick ( href ) or nil ,
3847 }
3848 else
3849 attr = {
3850 class = class ,
3851 id = id ,
3852 }
3853 end
3854 else
3855 if href then
3856 href = lpegmatch ( p_cleanhref , href ) or href
3857 attr = {
3858 class = class ,
3859 href = href ,
3860 onclick = addclicks and f_onclick ( href ) or nil ,
3861 }
3862 else
3863 attr = {
3864 class = class ,
3865 }
3866 end
3867 end
3868 c . at = attr
3869 if label then
3870 attr . label = label
3871 end
3872 c . tg = cssmapping and cssmapping [ tg ] or " div "
3873 end
3874 end
3875 end
3876 end
3877
3878
3879
3880 local addsuffix = file . addsuffix
3881 local joinfile = file . join
3882 local nameonly = file . nameonly
3883 local basename = file . basename
3884
3885 local embedfile = false directives . register ( " export.embed " , function ( v ) embedfile = v end )
3886
3887 function structurestags . finishexport ( )
3888
3889 if exporting then
3890 exporting = false
3891 else
3892 return
3893 end
3894
3895 local onlyxml = finetuning . export = = v_xml
3896
3897 starttiming ( treehash )
3898
3899 finishexport ( )
3900
3901 report_export ( " " )
3902 if onlyxml then
3903 report_export ( " exporting xml, no other files " )
3904 else
3905 report_export ( " exporting xml, xhtml, html and css files " )
3906 end
3907 report_export ( " " )
3908
3909 wrapups . fixtree ( tree )
3910 wrapups . collapsetree ( tree )
3911 wrapups . indextree ( tree )
3912 wrapups . checktree ( tree )
3913 wrapups . breaktree ( tree )
3914 wrapups . finalizetree ( tree )
3915
3916 wrapups . hashlistdata ( )
3917
3918 local askedname = finetuning . file
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935 if type ( askedname ) ~ = " string " or askedname = = " " then
3936 askedname = tex . jobname
3937 end
3938
3939 local usedname = nameonly ( askedname )
3940 local basepath = usedname . . " -export "
3941 local imagepath = joinfile ( basepath , " images " )
3942 local stylepath = joinfile ( basepath , " styles " )
3943
3944 local function validpath ( what , pathname )
3945 if lfs . isdir ( pathname ) then
3946 report_export ( " using existing %s path %a " , what , pathname )
3947 return pathname
3948 end
3949 lfs . mkdir ( pathname )
3950 if lfs . isdir ( pathname ) then
3951 report_export ( " using cretated %s path %a " , what , basepath )
3952 return pathname
3953 else
3954 report_export ( " unable to create %s path %a " , what , basepath )
3955 return false
3956 end
3957 end
3958
3959 if not ( validpath ( " export " , basepath ) and validpath ( " images " , imagepath ) and validpath ( " styles " , stylepath ) ) then
3960 return
3961 end
3962
3963
3964
3965
3966
3967 local xmlfilebase = addsuffix ( usedname . . " -raw " , " xml " )
3968 local xhtmlfilebase = addsuffix ( usedname . . " -tag " , " xhtml " )
3969 local htmlfilebase = addsuffix ( usedname . . " -div " , " html " )
3970 local specificationfilebase = addsuffix ( usedname . . " -pub " , " lua " )
3971
3972 local xmlfilename = joinfile ( basepath , xmlfilebase )
3973 local xhtmlfilename = joinfile ( basepath , xhtmlfilebase )
3974 local htmlfilename = joinfile ( basepath , htmlfilebase )
3975 local specificationfilename = joinfile ( basepath , specificationfilebase )
3976
3977 local defaultfilebase = addsuffix ( usedname . . " -defaults " , " css " )
3978 local imagefilebase = addsuffix ( usedname . . " -images " , " css " )
3979 local stylefilebase = addsuffix ( usedname . . " -styles " , " css " )
3980 local templatefilebase = addsuffix ( usedname . . " -templates " , " css " )
3981
3982 local defaultfilename = joinfile ( stylepath , defaultfilebase )
3983 local imagefilename = joinfile ( stylepath , imagefilebase )
3984 local stylefilename = joinfile ( stylepath , stylefilebase )
3985 local templatefilename = joinfile ( stylepath , templatefilebase )
3986
3987 local cssfile = finetuning . cssfile
3988
3989
3990
3991 local files = {
3992 }
3993
3994
3995
3996
3997 local cssfiles = {
3998 defaultfilebase ,
3999 imagefilebase ,
4000 stylefilebase ,
4001 }
4002
4003 local cssextra = cssfile and table . unique ( settings_to_array ( cssfile ) ) or { }
4004
4005
4006
4007
4008
4009
4010 local data = tree . data
4011 for i = 1 , # data do
4012 if data [ i ] . tg ~ = " document " then
4013 data [ i ] = { }
4014 end
4015 end
4016
4017 local result = allcontent ( tree , embedmath )
4018
4019
4020
4021 local extradata = structures . tags . getextradata ( )
4022 if extradata then
4023 local t = { " " }
4024 t [ # t + 1 ] = " <extradata> "
4025 for name , action in sortedhash ( extradata ) do
4026 t [ # t + 1 ] = action ( )
4027 end
4028 t [ # t + 1 ] = " </extradata> "
4029 t [ # t + 1 ] = " </document> "
4030
4031 result = gsub ( result , " </document> " , function ( )
4032 return concat ( t , " \n " )
4033 end )
4034 end
4035
4036
4037
4038 if onlyxml then
4039
4040 os . remove ( defaultfilename )
4041 os . remove ( imagefilename )
4042 os . remove ( stylefilename )
4043 os . remove ( templatefilename )
4044
4045 for i = 1 , # cssextra do
4046 os . remove ( joinfile ( stylepath , basename ( source ) ) )
4047 end
4048
4049
4050
4051 os . remove ( imagefilename )
4052 os . remove ( stylefilename )
4053 os . remove ( templatefilename )
4054 os . remove ( xhtmlfilename )
4055 os . remove ( specificationfilename )
4056 os . remove ( htmlfilename )
4057
4058 result = concat {
4059 wholepreamble ( true ) ,
4060 " <!-- This export file is used for filtering runtime only! -->\n " ,
4061 result ,
4062 }
4063
4064 report_export ( " saving xml data in %a " , xmlfilename )
4065 io . savedata ( xmlfilename , result )
4066
4067 return
4068
4069 end
4070
4071 local examplefilename = resolvers . findfile ( " export-example.css " )
4072 if examplefilename then
4073 local data = io . loaddata ( examplefilename )
4074 if not data or data = = " " then
4075 data = " /* missing css file */ "
4076 elseif not usecssnamespace then
4077 data = gsub ( data , cssnamespace , " " )
4078 end
4079 io . savedata ( defaultfilename , data )
4080 end
4081
4082 if cssfile then
4083 for i = 1 , # cssextra do
4084 local source = addsuffix ( cssextra [ i ] , " css " )
4085 local target = joinfile ( stylepath , basename ( source ) )
4086 cssfiles [ # cssfiles + 1 ] = source
4087 if not lfs . isfile ( source ) then
4088 source = joinfile ( " ../ " , source )
4089 end
4090 if lfs . isfile ( source ) then
4091 report_export ( " copying %s " , source )
4092 file . copy ( source , target )
4093 end
4094 end
4095 end
4096
4097 local x_styles , h_styles = allusedstylesheets ( cssfiles , files , " styles " )
4098
4099 local attach = backends . nodeinjections . attachfile
4100
4101 if embedfile and attach then
4102
4103 attach {
4104 data = concat { wholepreamble ( true ) , result } ,
4105 name = basename ( xmlfilename ) ,
4106 registered = " export " ,
4107 title = " raw xml export " ,
4108 method = v_hidden ,
4109 mimetype = " application/mathml+xml " ,
4110 }
4111 end
4112
4113 result = concat {
4114 wholepreamble ( true ) ,
4115 x_styles ,
4116 result ,
4117 }
4118
4119 cssfiles = table . unique ( cssfiles )
4120
4121
4122
4123 report_export ( " saving xml data in %a " , xmlfilename )
4124 io . savedata ( xmlfilename , result )
4125
4126 report_export ( " saving css image definitions in %a " , imagefilename )
4127 io . savedata ( imagefilename , wrapups . allusedimages ( usedname ) )
4128
4129 report_export ( " saving css style definitions in %a " , stylefilename )
4130 io . savedata ( stylefilename , wrapups . allusedstyles ( usedname ) )
4131
4132 report_export ( " saving css template in %a " , templatefilename )
4133 io . savedata ( templatefilename , allusedelements ( usedname ) )
4134
4135
4136
4137 report_export ( " saving xhtml variant in %a " , xhtmlfilename )
4138
4139 local xmltree = cleanxhtmltree ( xml . convert ( result ) )
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150 xml . save ( xmltree , xhtmlfilename )
4151
4152
4153
4154
4155
4156
4157 local identity = interactions . general . getidentity ( )
4158 local metadata = structures . tags . getmetadata ( )
4159
4160 local specification = {
4161 name = usedname ,
4162 identifier = os . uuid ( ) ,
4163 images = wrapups . uniqueusedimages ( ) ,
4164 imagefile = joinfile ( " styles " , imagefilebase ) ,
4165 imagepath = " images " ,
4166 stylepath = " styles " ,
4167 xmlfiles = { xmlfilebase } ,
4168 xhtmlfiles = { xhtmlfilebase } ,
4169 htmlfiles = { htmlfilebase } ,
4170 styles = cssfiles ,
4171 htmlroot = htmlfilebase ,
4172 language = languagenames [ texgetcount ( " mainlanguagenumber " ) ] ,
4173 title = validstring ( finetuning . title ) or validstring ( identity . title ) ,
4174 subtitle = validstring ( finetuning . subtitle ) or validstring ( identity . subtitle ) ,
4175 author = validstring ( finetuning . author ) or validstring ( identity . author ) ,
4176 firstpage = validstring ( finetuning . firstpage ) ,
4177 lastpage = validstring ( finetuning . lastpage ) ,
4178 metadata = metadata ,
4179 }
4180
4181 report_export ( " saving specification in %a " , specificationfilename , specificationfilename )
4182
4183 xml . wipe ( xmltree , " metadata " )
4184
4185 io . savedata ( specificationfilename , table . serialize ( specification , true ) )
4186
4187
4188
4189
4190 report_export ( " saving div based alternative in %a " , htmlfilename )
4191
4192 remap ( specification , xmltree )
4193
4194
4195
4196 local title = specification . title
4197
4198 if not title or title = = " " then
4199 title = metadata . title
4200 if not title or title = = " " then
4201 title = usedname
4202 end
4203 end
4204
4205 local variables = {
4206 style = h_styles ,
4207 body = xml . tostring ( xml . first ( xmltree , " /div " ) ) ,
4208 preamble = wholepreamble ( false ) ,
4209 title = title ,
4210 }
4211
4212 io . savedata ( htmlfilename , replacetemplate ( htmltemplate , variables , " xml " ) )
4213
4214
4215
4216 report_export ( " " )
4217 report_export ( ' create epub with: mtxrun --script epub --make "%s" [--purge --rename --svgmath] ' , usedname )
4218 report_export ( " " )
4219
4220 stoptiming ( treehash )
4221 end
4222
4223 local enableaction = nodes . tasks . enableaction
4224
4225 function structurestags . initializeexport ( )
4226 if not exporting then
4227 report_export ( " enabling export to xml " )
4228 enableaction ( " shipouts " , " nodes.handlers.export " )
4229 enableaction ( " shipouts " , " nodes.handlers.accessibility " )
4230 enableaction ( " math " , " noads.handlers.tags " )
4231 enableaction ( " everypar " , " nodes.handlers.checkparcounter " )
4232 luatex . registerstopactions ( structurestags . finishexport )
4233 exporting = true
4234 end
4235 end
4236
4237 function structurestags . setupexport ( t )
4238 merge ( finetuning , t )
4239 keephyphens = finetuning . hyphen = = v_yes
4240 exportproperties = finetuning . properties
4241 if exportproperties = = v_no then
4242 exportproperties = false
4243 end
4244 end
4245
4246 statistics . register ( " xml exporting time " , function ( )
4247 if exporting then
4248 return string . format ( " %s seconds, version %s " , statistics . elapsedtime ( treehash ) , exportversion )
4249 end
4250 end )
4251
4252end
4253
4254
4255
4256implement {
4257 name = " setupexport " ,
4258 actions = structurestags . setupexport ,
4259 arguments = {
4260 {
4261 { " align " } ,
4262 { " bodyfont " , " dimen " } ,
4263 { " width " , " dimen " } ,
4264 { " properties " } ,
4265 { " hyphen " } ,
4266 { " title " } ,
4267 { " subtitle " } ,
4268 { " author " } ,
4269 { " firstpage " } ,
4270 { " lastpage " } ,
4271 { " svgstyle " } ,
4272 { " cssfile " } ,
4273 { " file " } ,
4274 { " export " } ,
4275 }
4276 }
4277}
4278
4279implement {
4280 name = " finishexport " ,
4281 actions = structurestags . finishexport ,
4282}
4283
4284implement {
4285 name = " initializeexport " ,
4286 actions = structurestags . initializeexport ,
4287}
4288
4289implement {
4290 name = " settagitemgroup " ,
4291 actions = structurestags . setitemgroup ,
4292 arguments = { " boolean " , " integer " , " string " }
4293}
4294
4295implement {
4296 name = " settagitem " ,
4297 actions = structurestags . setitem ,
4298 arguments = " string "
4299}
4300
4301implement {
4302 name = " settagfloat " ,
4303 actions = structurestags . setfloat ,
4304 arguments = " 2 strings " ,
4305}
4306
4307implement {
4308 name = " settagformulacontent " ,
4309 actions = structurestags . setformulacontent ,
4310 arguments = " integer " ,
4311}
4312
4313implement {
4314 name = " settagdelimitedsymbol " ,
4315 actions = structurestags . settagdelimitedsymbol ,
4316 arguments = " string "
4317}
4318
4319implement {
4320 name = " settagsubsentencesymbol " ,
4321 actions = structurestags . settagsubsentencesymbol ,
4322 arguments = " string "
4323}
4324
4325implement {
4326 name = " settagsynonym " ,
4327 actions = structurestags . setsynonym ,
4328 arguments = " string "
4329}
4330
4331implement {
4332 name = " settagsorting " ,
4333 actions = structurestags . setsorting ,
4334 arguments = " string "
4335}
4336
4337implement {
4338 name = " settagnotation " ,
4339 actions = structurestags . setnotation ,
4340 arguments = { " string " , " integer " }
4341}
4342
4343implement {
4344 name = " settagnotationsymbol " ,
4345 actions = structurestags . setnotationsymbol ,
4346 arguments = { " string " , " integer " }
4347}
4348
4349implement {
4350 name = " settaghighlight " ,
4351 actions = structurestags . sethighlight ,
4352 arguments = { " string " , " string " , " integer " , " integer " }
4353}
4354
4355implement {
4356 name = " settagconstruct " ,
4357 actions = structurestags . setconstruct ,
4358 arguments = { " string " , " string " , " integer " , " integer " }
4359}
4360
4361implement {
4362 name = " settagfigure " ,
4363 actions = structurestags . setfigure ,
4364 arguments = { " string " , " string " , " string " , " dimen " , " dimen " , " string " }
4365}
4366
4367implement {
4368 name = " settagcombination " ,
4369 actions = structurestags . setcombination ,
4370 arguments = { " integer " , " integer " }
4371}
4372
4373implement {
4374 name = " settagtablecell " ,
4375 actions = structurestags . settablecell ,
4376 arguments = { " integer " , " integer " , " integer " }
4377}
4378
4379implement {
4380 name = " settagtabulatecell " ,
4381 actions = structurestags . settabulatecell ,
4382 arguments = { " integer " , " integer " } ,
4383}
4384
4385implement {
4386 name = " settagregister " ,
4387 actions = structurestags . setregister ,
4388 arguments = { " string " , " integer " }
4389}
4390
4391implement {
4392 name = " settaglist " ,
4393 actions = structurestags . setlist ,
4394 arguments = " integer "
4395}
4396
4397implement {
4398 name = " settagpublication " ,
4399 actions = structurestags . setpublication ,
4400 arguments = " 2 strings "
4401}
4402
4403implement {
4404 name = " settagparagraph " ,
4405 actions = structurestags . setparagraph ,
4406 arguments = " string "
4407}
4408 |