x-ct.lua /size: 4300 b    last modification: 2020-07-01 14:35
1if not modules then modules = { } end modules ['x-ct'] = {
2    version   = 1.001,
3    comment   = "companion to x-ct.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-- needs testing
10
11local xmlsprint, xmlcprint, xmlfilter, xmlcollected = xml.sprint, xml.cprint, xml.filter, xml.collected
12local format, concat, rep, find = string.format, table.concat, string.rep, string.find
13
14moduledata.ct = moduledata.ct or { }
15
16local halignments = {
17    left       = 'l',
18    flushleft  = 'l',
19    right      = 'r',
20    flushright = 'r',
21    center     = 'c',
22    middle     = 'c',
23    centre     = 'c',
24    justify    = '',
25}
26
27local templates = { }
28
29function moduledata.ct.registertabulatetemplate(name,str)
30    templates[name] = str
31end
32
33local function roottemplate(root)
34    local rt = root.at.template
35    if rt then
36        local template = templates[rt]
37        if template then
38            return template
39        else
40            if not find(rt,"|",1,true) then
41                rt = gsub(rt,",","|")
42            end
43            if not find(rt,"^|") then rt = "|" .. rt end
44            if not find(rt,"|$") then rt = rt .. "|" end
45            return rt
46        end
47    end
48end
49
50local function specifiedtemplate(root,templatespec)
51    local template = { }
52    for e in xmlcollected(root,templatespec) do
53        local at = e.at
54        local tm = halignments[at.align] or ""
55        if toboolean(at.paragraph) then
56            tm = tm .. "p"
57        end
58        template[#template+1] = tm
59    end
60    if #template > 0 then
61        return "|" .. concat(template,"|") .. "|"
62    else
63        return nil
64    end
65end
66
67local function autotemplate(root,rowspec,cellspec)
68    local max = 0
69    for e in xmlcollected(root,rowspec) do
70        local n = xml.count(e,cellspec)
71        if n > max then max = n end
72    end
73    if max == 2 then
74        return "|l|p|"
75    elseif max > 0 then
76        return "|" .. rep("p|",max)
77    else
78        return nil
79    end
80end
81
82local defaulttemplate = "|l|p|"
83
84function moduledata.ct.tabulate(root,namespace)
85    if not root then
86        return
87    else
88        root = lxml.id(root)
89    end
90
91    local prefix = (namespace or "context") .. ":"
92
93    local templatespec = "/" .. prefix .. "template" .. "/" .. prefix .. "column"
94    local bodyrowspec  = "/" .. prefix .. "body"     .. "/" .. prefix .. "row"
95    local cellspec     = "/" .. prefix .. "cell"
96
97    local template =
98        roottemplate      (root) or
99        specifiedtemplate (root,templatespec) or
100        autotemplate      (root,bodyrowspec,cellspec) or
101        defaulttemplate
102
103    -- todo: head and foot
104
105    local NC, NR = context.NC, context.NR
106
107    lxml.directives.before(root,'cdx')
108    context.bgroup()
109    lxml.directives.setup(root,'cdx')
110    context.starttabulate { template }
111    for e in xmlcollected(root,bodyrowspec) do
112        NC()
113        for e in xmlcollected(e,cellspec) do
114            xmlcprint(e)
115            NC()
116        end
117        NR()
118    end
119    context.stoptabulate()
120    context.egroup()
121    lxml.directives.after(root,'cdx')
122
123end
124
125-- todo: use content and caption
126
127function moduledata.ct.combination(root,namespace)
128
129    if not root then
130        return
131    else
132        root = lxml.id(root)
133    end
134
135    local prefix = (namespace or "context") .. ":"
136
137    local pairspec    = "/" .. prefix .. "pair"
138    local contentspec = "/" .. prefix .. "content" .. "/text()"
139    local captionspec = "/" .. prefix .. "caption" .. "/text()"
140
141    local nx, ny = root.at.nx, root.at.ny
142
143    if not (nx or ny) then
144        nx = xml.count(root,pairspec) or 2
145    end
146    local template = format("%s*%s", nx or 1, ny or 1)
147
148    lxml.directives.before(root,'cdx')
149    context.bgroup()
150    lxml.directives.setup(root,'cdx')
151    context.startcombination { template }
152    for e in xmlcollected(root,pairspec) do
153     -- context.combination(
154     --     function() xmlfilter(e,contentspec) end,
155     --     function() xmlfilter(e,captionspec) end
156     -- )
157        context("{")
158        xmlfilter(e,contentspec)
159        context("}{")
160        xmlfilter(e,captionspec)
161        context("}")
162    end
163    context.stopcombination()
164    context.egroup()
165    lxml.directives.after(root,'cdx')
166
167end
168