diff options
Diffstat (limited to 'tex/context/base/back-exp.lua')
-rw-r--r-- | tex/context/base/back-exp.lua | 781 |
1 files changed, 555 insertions, 226 deletions
diff --git a/tex/context/base/back-exp.lua b/tex/context/base/back-exp.lua index 74640ad08..e64b7b77c 100644 --- a/tex/context/base/back-exp.lua +++ b/tex/context/base/back-exp.lua @@ -28,6 +28,10 @@ if not modules then modules = { } end modules ['back-exp'] = { -- todo: move critital formatters out of functions -- todo: delay loading (apart from basic tag stuff) +-- problem : too many local variables + +-- check setting __i__ + local next, type, tonumber = next, type, tonumber local format, concat, sub, gsub = string.format, table.concat, string.sub, string.gsub local validstring = string.valid @@ -42,6 +46,7 @@ local replacetemplate = utilities.templates.replace local trace_export = false trackers.register ("export.trace", function(v) trace_export = v end) local trace_spacing = false trackers.register ("export.trace.spacing", function(v) trace_spacing = v end) + local less_state = false directives.register("export.lessstate", function(v) less_state = v end) local show_comment = true directives.register("export.comment", function(v) show_comment = v end) @@ -233,30 +238,35 @@ local namespaced = { } local namespaces = { - msubsup = "m", - msub = "m", - msup = "m", - mn = "m", - mi = "m", - ms = "m", - mo = "m", - mtext = "m", - mrow = "m", - mfrac = "m", - mroot = "m", - msqrt = "m", - munderover = "m", - munder = "m", - mover = "m", - merror = "m", - math = "m", - mrow = "m", - mtable = "m", - mtr = "m", - mtd = "m", - mfenced = "m", - maction = "m", - mspace = "m", + msubsup = "m", + msub = "m", + msup = "m", + mn = "m", + mi = "m", + ms = "m", + mo = "m", + mtext = "m", + mrow = "m", + mfrac = "m", + mroot = "m", + msqrt = "m", + munderover = "m", + munder = "m", + mover = "m", + merror = "m", + math = "m", + mrow = "m", + mtable = "m", + mtr = "m", + mtd = "m", + mfenced = "m", + maction = "m", + mspace = "m", + -- only when testing + mstacker = "m", + mstackertop = "m", + mstackermid = "m", + mstackernbot = "m", } setmetatableindex(namespaced, function(t,k) @@ -356,8 +366,8 @@ local styletemplate = [[ color : %color% ; }]] - function wrapups.allusedstyles(xmlfile) - local result = { formatters["/* %s for file %s */"]("styles",xmlfile) } + function wrapups.allusedstyles(basename) + local result = { formatters["/* %s for file %s */"]("styles",basename) } -- local bodyfont = finetuning.bodyfont local width = finetuning.width @@ -439,11 +449,10 @@ local imagetemplate = [[ end end - local f_images = formatters["/* %s for file %s */"] local collected = { } - function wrapups.allusedimages(xmlfile) - local result = { f_images("images",xmlfile) } + function wrapups.allusedimages(basename) + local result = { formatters["/* %s for file %s */"]("images",basename) } for element, details in sortedhash(usedimages) do for detail, data in sortedhash(details) do local name = data.name @@ -1053,8 +1062,44 @@ do element = "mtext", data = { content = "" }, nature = "inline", + comment = "dummy nucleus" } + local function accentchar(d) + for i=1,3 do + d = d.data + if not d then + return + end + d = d[1] + if not d then + return + end + local tg = d.tg + if tg == "mover" then + local p = properties[d.fulltag] + local t = p.top + if t then + d = d.data[1] + local d1 = d.data[1] + d1.content = utfchar(t) + d.data = { d1 } + return d + end + elseif tg == "munder" then + local p = properties[d.fulltag] + local b = p.bottom + if b then + d = d.data[1] + local d1 = d.data[1] + d1.content = utfchar(b) + d.data = { d1 } + return d + end + end + end + end + local function checkmath(root) -- we can provide utf.toentities as an option local data = root.data if data then @@ -1093,33 +1138,13 @@ do -- data[1] = dummy_nucleus -- end elseif roottg == "mfenced" then - local new, n = { }, 0 - local attributes = { } - root.attributes = attributes - for i=1,ndata do - local di = data[i] - if not di then - -- weird - elseif di.content then - n = n + 1 - new[n] = di - else - local tg = di.tg - if tg == "mleft" then - attributes.left = tostring(di.data[1].data[1].content) - elseif tg == "mmiddle" then - attributes.middle = tostring(di.data[1].data[1].content) - elseif tg == "mright" then - attributes.right = tostring(di.data[1].data[1].content) - else - n = n + 1 - di.__i__ = n - new[n] = di - end - end - end - root.data = new - ndata = n + local p = properties[root.fulltag] + local l, m, r = p.left, p.middle, p.right + root.attributes = { + left = l and utfchar(l), + middle = m and utfchar(m), + right = r and utfchar(r), + } end if ndata == 0 then return @@ -1156,9 +1181,122 @@ do di.skip = "comment" checkmath(di) i = i + 1 - elseif tg == "mover" or tg == "munder" or tg == "munderover" then + elseif tg == "mover" then + if detail == "accent" then + local p = properties[di.fulltag] + local t = p.top + local d = di.data + -- todo: accent = "false" (for scripts like limits) + di.attributes = { + accent = "true", + } + -- todo: p.topfixed + di.detail = nil + if t then + -- mover + d[1].data[1].content = utfchar(t) + di.data = { d[2], d[1] } + end + else + -- can't happen + end + checkmath(di) + i = i + 1 + elseif tg == "munder" then if detail == "accent" then - di.attributes = { accent = "true" } + local p = properties[di.fulltag] + local b = p.bottom + local d = di.data + -- todo: accent = "false" (for scripts like limits) + di.attributes = { + accent = "true", + } + -- todo: p.bottomfixed + di.detail = nil + if b then + -- munder + d[2].data[1].content = utfchar(b) + end + else + -- can't happen + end + checkmath(di) + i = i + 1 + elseif tg == "munderover" then + if detail == "accent" then + local p = properties[di.fulltag] + local t = p.top + local b = p.bottom + local d = di.data + -- todo: accent = "false" (for scripts like limits) + -- todo: accentunder = "false" (for scripts like limits) + di.attributes = { + accent = "true", + accentunder = "true", + } + -- todo: p.topfixed + -- todo: p.bottomfixed + di.detail = nil + if t and b then + -- munderover + d[1].data[1].content = utfchar(t) + d[3].data[1].content = utfchar(b) + di.data = { d[2], d[3], d[1] } + else + -- can't happen + end + else + -- can't happen + end + checkmath(di) + i = i + 1 + elseif tg == "mstacker" then + local d = di.data + local d1 = d[1] + local d2 = d[2] + local d3 = d[3] + local t1 = d1 and d1.tg + local t2 = d2 and d2.tg + local t3 = d3 and d3.tg + local m = nil -- d1.data[1] + local t = nil + local b = nil + -- only accent when top / bot have stretch + if t1 == "mstackermid" then + m = accentchar(d1) -- or m + if t2 == "mstackertop" then + if t3 == "mstackerbot" then + t = accentchar(d2) + b = accentchar(d3) + di.element = "munderover" + di.data = { m or d1.data[1], b or d3.data[1], t or d2.data[1] } + else + t = accentchar(d2) + di.element = "mover" + di.data = { m or d1.data[1], t or d2.data[1] } + end + elseif t2 == "mstackerbot" then + if t3 == "mstackertop" then + b = accentchar(d2) + t = accentchar(d3) + di.element = "munderover" + di.data = { m or d1.data[1], t or d3.data[1], m, b or d2.data[1] } + else + b = accentchar(d2) + di.element = "munder" + di.data = { m or d1.data[1], b or d2.data[1] } + end + else + -- can't happen + end + else + -- can't happen + end + if t or b then + di.attributes = { + accent = t and "true" or nil, + accentunder = b and "true" or nil, + } di.detail = nil end checkmath(di) @@ -1173,7 +1311,34 @@ do elseif tg == "break" then di.skip = "comment" i = i + 1 - elseif tg == "mrow" and detail then + elseif tg == "mtext" then + -- this is only needed for unboxed mtexts ... all kind of special + -- tex border cases and optimizations ... trial and error + local data = di.data + if #data > 1 then + for i=1,#data do + local di = data[i] + local content = di.content + if content then + data[i] = { + element = "mtext", + nature = "inline", + data = { di }, + n = 0, + } + elseif di.tg == "math" then + local di = di.data[1] + data[i] = di + checkmath(di) + end + end + di.element = "mrow" + -- di.tg = "mrow" + -- di.nature = "inline" + end + checkmath(di) + i = i + 1 + elseif tg == "mrow" and detail then -- hm, falls through di.detail = nil checkmath(di) di = { @@ -1272,21 +1437,47 @@ do local ndata = #data local n = 0 for i=1,ndata do - local di = data[i] - if di and not di.content then - di = stripmath(di) + local d = data[i] + if d and not d.content then + d = stripmath(d) end - if di then - local content = di.content + if d then + local content = d.content if not content then n = n + 1 - di.__i__ = n - data[n] = di + d.__i__ = n + data[n] = d elseif content == " " or content == "" then - -- skip + if di.tg == "mspace" then + -- we append or prepend a space to a preceding or following mtext + local parent = di.__p__ + local index = di.__i__ -- == i + local data = parent.data + if index > 1 then + local d = data[index-1] + if d.tg == "mtext" then + local dd = d.data + local dn = dd[#dd] + local dc = dn.content + if dc then + dn.content = dc .. content + end + end + elseif index < ndata then + local d = data[index+1] + if d.tg == "mtext" then + local dd = d.data + local dn = dd[1] + local dc = dn.content + if dc then + dn.content = content .. dc + end + end + end + end else n = n + 1 - data[n] = di + data[n] = d end end end @@ -1296,7 +1487,16 @@ do if #data > 0 then return di end +-- end end + -- could be integrated but is messy then +-- while roottg == "mrow" and #data == 1 do +-- data = data[1] +-- for k, v in next, data do +-- root[k] = v +-- end +-- roottg = data.tg +-- end end end @@ -1795,46 +1995,50 @@ do local di = data[i] if not di then -- hm, di can be string -- whatever - elseif di.content then - -- already has breaks - local content = lpegmatch(p_entity,di.content) - if i == nofdata and sub(content,-1) == "\n" then -- move check - -- can be an end of line in par but can also be the last line - if trace_spacing then - result[#result+1] = f_spacing(di.parnumber or 0,sub(content,1,-2)) + else + local content = di.content +-- also optimize for content == "" : trace that first + if content then + -- already has breaks + local content = lpegmatch(p_entity,content) + if i == nofdata and sub(content,-1) == "\n" then -- move check + -- can be an end of line in par but can also be the last line + if trace_spacing then + result[#result+1] = f_spacing(di.parnumber or 0,sub(content,1,-2)) + else + result[#result+1] = sub(content,1,-2) + end + result[#result+1] = " " else - result[#result+1] = sub(content,1,-2) + if trace_spacing then + result[#result+1] = f_spacing(di.parnumber or 0,content) + else + result[#result+1] = content + end end - result[#result+1] = " " - else - if trace_spacing then - result[#result+1] = f_spacing(di.parnumber or 0,content) + elseif not di.collapsed then -- ignore collapsed data (is appended, reconstructed par) + local element = di.element + if not element then + -- skip + elseif element == "break" then -- or element == "pagebreak" + emptytag(result,element,nature,di) + elseif element == "" or di.skip == "ignore" then + -- skip else - result[#result+1] = content - end - end - elseif not di.collapsed then -- ignore collapsed data (is appended, reconstructed par) - local element = di.element - if not element then - -- skip - elseif element == "break" then -- or element == "pagebreak" - emptytag(result,element,nature,di) - elseif element == "" or di.skip == "ignore" then - -- skip - else - if di.before then - flushtree(result,di.before,nature) - end - local natu = di.nature - local skip = di.skip - if di.breaknode then - emptytag(result,"break","display",di) - end - begintag(result,element,natu,di,skip) - flushtree(result,di.data,natu) - endtag(result,element,natu,di,skip) - if di.after then - flushtree(result,di.after,nature) + if di.before then + flushtree(result,di.before,nature) + end + local natu = di.nature + local skip = di.skip + if di.breaknode then + emptytag(result,"break","display",di) + end + begintag(result,element,natu,di,skip) + flushtree(result,di.data,natu) + endtag(result,element,natu,di,skip) + if di.after then + flushtree(result,di.after,nature) + end end end end @@ -2222,12 +2426,13 @@ end -- whatsit_code localpar_code -local function collectresults(head,list) -- is last used (we also have currentattribute) +local function collectresults(head,list,pat,pap) -- is last used (we also have currentattribute) local p for n in traverse_nodes(head) do local id = getid(n) -- 14: image, 8: literal (mp) if id == glyph_code then local at = getattr(n,a_tagged) +or pat if not at then -- we need to tag the pagebody stuff as being valid skippable -- @@ -2236,7 +2441,7 @@ local function collectresults(head,list) -- is last used (we also have currentat -- we could add tonunicodes for ligatures (todo) local components = getfield(n,"components") if components then -- we loose data - collectresults(components,nil) + collectresults(components,nil,at) -- this assumes that components have the same attribute as the glyph ... we should be more tolerant (see math) else local c = getchar(n) if last ~= at then @@ -2244,6 +2449,7 @@ local function collectresults(head,list) -- is last used (we also have currentat pushcontent() currentnesting = tl currentparagraph = getattr(n,a_taggedpar) +or pap currentattribute = at last = at pushentry(currentnesting) @@ -2262,6 +2468,7 @@ local function collectresults(head,list) -- is last used (we also have currentat -- information unless we inject a special node (but even then we can run into nesting -- issues) local ap = getattr(n,a_taggedpar) +or pap if ap ~= currentparagraph then pushcontent(currentparagraph,ap) pushentry(currentnesting) @@ -2338,6 +2545,7 @@ local function collectresults(head,list) -- is last used (we also have currentat -- skip this one ... already converted special character (node-acc) elseif ca then local a = getattr(n,a_tagged) +or pat if a then local c = specialspaces[ca] if last ~= a then @@ -2348,12 +2556,14 @@ local function collectresults(head,list) -- is last used (we also have currentat pushcontent() currentnesting = tl currentparagraph = getattr(n,a_taggedpar) +or pap currentattribute = a last = a pushentry(currentnesting) -- no reference check (see above) elseif last then local ap = getattr(n,a_taggedpar) +or pap if ap ~= currentparagraph then pushcontent(currentparagraph,ap) pushentry(currentnesting) @@ -2376,9 +2586,11 @@ local function collectresults(head,list) -- is last used (we also have currentat else local subtype = getsubtype(n) if subtype == userskip_code then - if getfield(getfield(n,"spec"),"width") > threshold then + local spec = getfield(n,"spec") + if getfield(spec,"width") > threshold then if last and not somespace[currentcontent[nofcurrentcontent]] then local a = getattr(n,a_tagged) +or pat if a == last then if trace_export then report_export("%w<!-- injecting spacing 5a -->",currentdepth) @@ -2406,6 +2618,7 @@ local function collectresults(head,list) -- is last used (we also have currentat elseif subtype == spaceskip_code or subtype == xspaceskip_code then if not somespace[currentcontent[nofcurrentcontent]] then local a = getattr(n,a_tagged) +or pat if a == last then if trace_export then report_export("%w<!-- injecting spacing 7 (stay in element) -->",currentdepth) @@ -2435,6 +2648,7 @@ local function collectresults(head,list) -- is last used (we also have currentat end elseif not somespace[r] then local a = getattr(n,a_tagged) +or pat if a == last then if trace_export then report_export("%w<!-- injecting spacing 1 (end of line, stay in element) -->",currentdepth) @@ -2465,6 +2679,7 @@ local function collectresults(head,list) -- is last used (we also have currentat local ai = getattr(n,a_image) if ai then local at = getattr(n,a_tagged) +or pat if nofcurrentcontent > 0 then pushcontent() pushentry(currentnesting) -- ?? @@ -2479,7 +2694,9 @@ local function collectresults(head,list) -- is last used (we also have currentat -- we need to determine an end-of-line local list = getlist(n) if list then - collectresults(list,n) +local at = getattr(n,a_tagged) +or pat + collectresults(list,n,at) end end elseif id == kern_code then @@ -2492,6 +2709,7 @@ local function collectresults(head,list) -- is last used (we also have currentat if kern > limit then if last and not somespace[currentcontent[nofcurrentcontent]] then local a = getattr(n,a_tagged) +or pat if a == last then if not somespace[currentcontent[nofcurrentcontent]] then if trace_export then @@ -2531,6 +2749,19 @@ function nodes.handlers.export(head) -- hooks into the page builder end -- continueexport() restart = true + +-- local function f(head,depth,pat) +-- for n in node.traverse(head) do +-- local a = n[a_tagged] or pat +-- local t = taglist[a] +-- print(depth,n,a,t and table.concat(t," ")) +-- if n.id == hlist_code or n.id == vlist_code and n.list then +-- f(n.list,depth+1,a) +-- end +-- end +-- end +-- f(head,1) + collectresults(tonut(head)) if trace_export then report_export("%w<!-- stop flushing page -->",currentdepth) @@ -2578,31 +2809,35 @@ local f_cssheadlink = formatters [ [[ <link type="text/css" rel="stylesheet" href="%s"/> ]] ] - local function allusedstylesheets(xmlfile,cssfiles,files) + local function allusedstylesheets(cssfiles,files,path) + local done = { } local result = { } local extras = { } for i=1,#cssfiles do local cssfile = cssfiles[i] - if type(cssfile) ~= "string" or cssfile == v_yes or cssfile == "" or cssfile == xmlfile then - cssfile = file.replacesuffix(xmlfile,"css") - else - cssfile = file.addsuffix(cssfile,"css") + if type(cssfile) ~= "string" then + -- error + elseif cssfile == "export-example.css" then + -- ignore + elseif not done[cssfile] then + cssfile = file.join(path,cssfile) + report_export("adding css reference '%s'",cssfile) + files[#files+1] = cssfile + result[#result+1] = f_csspreamble(cssfile) + extras[#extras+1] = f_cssheadlink(cssfile) + done[cssfile] = true end - files[#files+1] = cssfile - report_export("adding css reference '%s'",cssfile) - result[#result+1] = f_csspreamble(cssfile) - extras[#extras+1] = f_cssheadlink(cssfile) end return concat(result), concat(extras) end local f_e_template = [[ -%element% { +%element%, div.%element% { display: %display% ; }]] local f_d_template = [[ -%element%[detail=%detail%], div.detail-%detail% { +%element%[detail=%detail%], div.%element%.detail-%detail% { display: %display% ; }]] @@ -2640,23 +2875,27 @@ local htmltemplate = [[ mixed = "inline", } - local function allusedelements(xmlfile) - local result = { formatters["/* %s for file %s */"]("template",xmlfile) } + local function allusedelements(basename) + local result = { formatters["/* %s for file %s */"]("template",basename) } for element, details in sortedhash(used) do - result[#result+1] = f_category(element) - for detail, nature in sortedhash(details) do - local display = displaymapping[nature or "display"] or "block" - if detail == "" then - result[#result+1] = replacetemplate(f_e_template, { - element = element, - display = display, - }) - else - result[#result+1] = replacetemplate(f_d_template, { - element = element, - detail = detail, - display = display, - }) + if namespaces[element] then + -- skip math + else + result[#result+1] = f_category(element) + for detail, nature in sortedhash(details) do + local display = displaymapping[nature or "display"] or "block" + if detail == "" then + result[#result+1] = replacetemplate(f_e_template, { + element = element, + display = display, + }) + else + result[#result+1] = replacetemplate(f_d_template, { + element = element, + detail = detail, + display = display, + }) + end end end end @@ -2771,8 +3010,11 @@ local htmltemplate = [[ -- } - local addclicks = true - local f_onclick = formatters[ [[location.href='%s']] ] + local addclicks = true + local f_onclick = formatters[ [[location.href='%s']] ] + + local p_cleanid = lpeg.replacer { [":"] = "-" } + local p_cleanhref = lpeg.Cs(lpeg.P("#") * p_cleanid) local function remap(specification,source,target) local comment = nil -- share comments @@ -2781,8 +3023,10 @@ local htmltemplate = [[ local tg = c.tg local ns = c.ns if ns == "m" then +if false then c.ns = "" c.at["xmlns:m"] = nil +end -- elseif tg == "a" then -- c.ns = "" else @@ -2813,7 +3057,9 @@ local htmltemplate = [[ local href = at.href local class = concat(class," ") if id then + id = lpegmatch(p_cleanid, id) or id if href then + href = lpegmatch(p_cleanhref,href) or href c.at = { class = class, id = id, @@ -2828,6 +3074,7 @@ local htmltemplate = [[ end else if href then + href = lpegmatch(p_cleanhref,href) or href c.at = { class = class, href = href, @@ -2845,10 +3092,7 @@ local htmltemplate = [[ end end - local cssfile, xhtmlfile = nil, nil - - directives.register("backend.export.css", function(v) cssfile = v end) - directives.register("backend.export.xhtml", function(v) xhtmlfile = v end) + local cssfile = nil directives.register("backend.export.css", function(v) cssfile = v end) local function stopexport(v) starttiming(treehash) @@ -2856,11 +3100,7 @@ local htmltemplate = [[ finishexport() -- report_export("") - if xhtmlfile then - report_export("exporting xml, xhtml and html files") - else - report_export("exporting xml file") - end + report_export("exporting xml, xhtml and html files") report_export("") -- wrapups.collapsetree(tree) @@ -2874,101 +3114,190 @@ local htmltemplate = [[ if type(v) ~= "string" or v == v_yes or v == "" then v = tex.jobname end - local basename = file.basename(v) - local xmlfile = file.addsuffix(basename,"export") - -- - local imagefilename = file.addsuffix(file.removesuffix(xmlfile) .. "-images","css") - local stylefilename = file.addsuffix(file.removesuffix(xmlfile) .. "-styles","css") - local templatefilename = file.replacesuffix(xmlfile,"template") - local specificationfilename = file.replacesuffix(xmlfile,"specification") + + -- we use a dedicated subpath: -- - if xhtml and not cssfile then - cssfile = true - end - local cssfiles = { } - if cssfile then - if cssfile == true then - cssfiles = { "export-example.css" } + -- ./jobname-export + -- ./jobname-export/images + -- ./jobname-export/styles + -- ./jobname-export/styles + -- ./jobname-export/jobname-export.xml + -- ./jobname-export/jobname-export.xhtml + -- ./jobname-export/jobname-export.html + -- ./jobname-export/jobname-specification.lua + -- ./jobname-export/styles/jobname-defaults.css + -- ./jobname-export/styles/jobname-styles.css + -- ./jobname-export/styles/jobname-images.css + -- ./jobname-export/styles/jobname-templates.css + + local basename = file.basename(v) + local corename = file.removesuffix(basename) + local basepath = basename .. "-export" + local imagepath = file.join(basepath,"images") + local stylepath = file.join(basepath,"styles") + + local function validpath(what,pathname) + if lfs.isdir(pathname) then + report_export("using exiting %s path %a",what,pathname) + return pathname + end + lfs.mkdir(pathname) + if lfs.isdir(pathname) then + report_export("using cretated %s path %a",what,basepath) + return pathname else - cssfiles = settings_to_array(cssfile or "") + report_export("unable to create %s path %a",what,basepath) + return false end - insert(cssfiles,1,imagefilename) - insert(cssfiles,1,stylefilename) end - cssfiles = table.unique(cssfiles) + + if not (validpath("export",basepath) and validpath("images",imagepath) and validpath("styles",stylepath)) then + return + end + + -- we're now on the dedicated export subpath so we can't clash names + + local xmlfilebase = file.addsuffix(basename .. "-raw","xml" ) + local xhtmlfilebase = file.addsuffix(basename .. "-tag","xhtml") + local htmlfilebase = file.addsuffix(basename .. "-div","xhtml") + local specificationfilebase = file.addsuffix(basename .. "-pub","lua" ) + + local xmlfilename = file.join(basepath, xmlfilebase ) + local xhtmlfilename = file.join(basepath, xhtmlfilebase ) + local htmlfilename = file.join(basepath, htmlfilebase ) + local specificationfilename = file.join(basepath, specificationfilebase) -- - local result = allcontent(tree) -- also does some housekeeping and data collecting + local defaultfilebase = file.addsuffix(basename .. "-defaults", "css") + local imagefilebase = file.addsuffix(basename .. "-images", "css") + local stylefilebase = file.addsuffix(basename .. "-styles", "css") + local templatefilebase = file.addsuffix(basename .. "-templates","css") -- + local defaultfilename = file.join(stylepath,defaultfilebase ) + local imagefilename = file.join(stylepath,imagefilebase ) + local stylefilename = file.join(stylepath,stylefilebase ) + local templatefilename = file.join(stylepath,templatefilebase) + + -- we keep track of all used files + local files = { } - local x_styles, h_styles = allusedstylesheets(xmlfile,cssfiles,files) + + -- we always load the defaults and optionally extra css files; we also copy the example + -- css file so that we always have the latest version + + local cssfiles = { + defaultfilebase, + imagefilebase, + stylefilebase, + } + + local examplefilename = resolvers.find_file("export-example.css") + if examplefilename then + file.copy(examplefilename,defaultfilename) + end + + if type(cssfile) == "string" then + local list = table.unique(settings_to_array(cssfile)) + for i=1,#list do + local source = file.addsuffix(list[i],"css") + local target = source + cssfiles[#cssfiles+1] = target + -- todo: warning if no file yet + end + end + + local x_styles, h_styles = allusedstylesheets(cssfiles,files,"styles") + + -- at this point we're ready for the content; the collector also does some + -- housekeeping and data collecting; at this point we still have an xml + -- representation that uses verbose element names and carries information in + -- attributes + + local result = allcontent(tree) + local results = concat { wholepreamble(true), x_styles, -- adds to files result, } - -- - files = table.unique(files) - -- - report_export("saving xml data in %a",xmlfile) - io.savedata(xmlfile,results) - -- + + cssfiles = table.unique(cssfiles) + + -- we're now ready for saving the result in the xml file + + report_export("saving xml data in %a",xmlfilename) + io.savedata(xmlfilename,results) + report_export("saving css image definitions in %a",imagefilename) - io.savedata(imagefilename,wrapups.allusedimages(xmlfile)) - -- + io.savedata(imagefilename,wrapups.allusedimages(basename)) + report_export("saving css style definitions in %a",stylefilename) - io.savedata(stylefilename,wrapups.allusedstyles(xmlfile)) - -- + io.savedata(stylefilename,wrapups.allusedstyles(basename)) + report_export("saving css template in %a",templatefilename) - io.savedata(templatefilename,allusedelements(xmlfile)) - -- - local xmltree = nil - if xhtmlfile then - -- basic - if type(v) ~= "string" or xhtmlfile == true or xhtmlfile == v_yes or xhtmlfile == "" or xhtmlfile == xmlfile then - xhtmlfile = file.replacesuffix(xmlfile,"xhtml") - else - xhtmlfile = file.addsuffix(xhtmlfile,"xhtml") - end - files[#files+1] = xhtmlfile - report_export("saving xhtml variant in %a",xhtmlfile) - xmltree = cleanxhtmltree(xml.convert(results)) - xml.save(xmltree,xhtmlfile) - -- looking at identity is somewhat redundant as we also inherit from interaction - -- at the tex end - local identity = interactions.general.getidentity() - local specification = { - name = file.removesuffix(v), - identifier = os.uuid(), - images = wrapups.uniqueusedimages(), - imagefile = imagefilename, - stylefile = stylefilename, - root = xhtmlfile, - files = files, - language = languagenames[texgetcount("mainlanguagenumber")], - title = validstring(finetuning.title) or validstring(identity.title), - subtitle = validstring(finetuning.subtitle) or validstring(identity.subtitle), - author = validstring(finetuning.author) or validstring(identity.author), - firstpage = validstring(finetuning.firstpage), - lastpage = validstring(finetuning.lastpage), - } - report_export("saving specification in %a",specificationfilename,specificationfilename) - io.savedata(specificationfilename,table.serialize(specification,true)) - -- bonus - local resultfile = file.replacesuffix(xmlfile,"html") - report_export("saving div based alternative in %a",resultfile) - remap(specification,xmltree) - local variables = { - style = h_styles, - body = xml.tostring(xml.first(xmltree,"/div")), - preamble = wholepreamble(false), - title = specification.title, - } - io.savedata(resultfile,replacetemplate(htmltemplate,variables,"xml")) - report_export("") - report_export([[create epub with: mtxrun --script epub --make "%s"]],file.nameonly(resultfile)) - report_export("") - end + io.savedata(templatefilename,allusedelements(basename)) + + -- additionally we save an xhtml file; for that we load the file as xml tree + + report_export("saving xhtml variant in %a",xhtmlfilename) + + local xmltree = cleanxhtmltree(xml.convert(results)) + + xml.save(xmltree,xhtmlfilename) + + -- now we save a specification file that can b eused for generating an epub file + + -- looking at identity is somewhat redundant as we also inherit from interaction + -- at the tex end + + local identity = interactions.general.getidentity() + + local specification = { + name = file.removesuffix(v), + identifier = os.uuid(), + images = wrapups.uniqueusedimages(), + imagefile = file.join("styles",imagefilebase), + imagepath = "images", + stylepath = "styles", + xmlfiles = { xmlfilebase }, + xhtmlfiles = { xhtmlfilebase }, + htmlfiles = { htmlfilebase }, + styles = cssfiles, + htmlroot = htmlfilebase, + language = languagenames[texgetcount("mainlanguagenumber")], + title = validstring(finetuning.title) or validstring(identity.title), + subtitle = validstring(finetuning.subtitle) or validstring(identity.subtitle), + author = validstring(finetuning.author) or validstring(identity.author), + firstpage = validstring(finetuning.firstpage), + lastpage = validstring(finetuning.lastpage), + } + + report_export("saving specification in %a",specificationfilename,specificationfilename) + + io.savedata(specificationfilename,table.serialize(specification,true)) + + -- the html export for epub is different in the sense that it uses div's instead of + -- specific tags + + report_export("saving div based alternative in %a",htmlfilename) + + remap(specification,xmltree) + + local variables = { + style = h_styles, + body = xml.tostring(xml.first(xmltree,"/div")), + preamble = wholepreamble(false), + title = specification.title, + } + + io.savedata(htmlfilename,replacetemplate(htmltemplate,variables,"xml")) + + -- finally we report how an epub file can be made (using the specification) + + report_export("") + report_export('create epub with: mtxrun --script epub --make "%s" [--purge --rename --svgmath]',file.nameonly(basename)) + report_export("") + stoptiming(treehash) end |