1if not modules then modules = { } end modules ['x-math-svg'] = {
2 version = 1.001,
3 comment = "companion to x-math-svg.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local tostring, type, next = tostring, type, next
10local lpegmatch, P, Cs = lpeg.match, lpeg.P, lpeg.Cs
11
12local xmlfirst = xml.first
13local xmlconvert = xml.convert
14local xmlload = xml.load
15local xmlsave = xml.save
16local xmlcollected = xml.collected
17local xmldelete = xml.delete
18
19local loadtable = table.load
20local savetable = table.save
21
22local replacesuffix = file.replacesuffix
23local addsuffix = file.addsuffix
24local removefile = os.remove
25local isfile = lfs.isfile
26
27local formatters = string.formatters
28
29moduledata = moduledata or table.setmetatableindex("table")
30local svgmath = moduledata.svgmath
31
32local namedata = { }
33local pagedata = { }
34
35local statusname = "x-math-svg-status.lua"
36local pdfname = "x-math-svg.pdf"
37
38local pdftosvg = os.which("mutool")
39
40local f_make_tex = formatters[ [[context --global kpse:x-math-svg.mkvi --inputfile="%s" --svgstyle="%s" --batch --noconsole --once --purgeall]] ]
41local f_make_svg = formatters[ [[mutool draw -o "math-%%d.svg" "%s" 1-9999]] ]
42
43
44local f_inline = formatters[ [[<div class='math-inline'></div>]] ]
45local f_display = formatters[ [[<div class='math-display'></div>]] ]
46local f_style = formatters[ [[vertical-align:%p]] ]
47
48local f_math_tmp = formatters[ [[math-%i]] ]
49
50function svgmath.process(filename)
51 if not filename then
52
53 return
54 elseif not isfile(filename) then
55
56 return
57 end
58 local index = 0
59 local page = 0
60 local blobs = { }
61 local root = xmlload(filename)
62 for mth in xmlcollected(root,"math") do
63 index = index + 1
64 local blob = tostring(mth)
65 if blobs[blob] then
66 context.ReuseSVGMath(index,blobs[blob])
67 else
68 page = page + 1
69 buffers.assign(f_math_tmp(page),blob)
70 context.MakeSVGMath(index,page,mth.at.display)
71 blobs[blob] = page
72 end
73 end
74 context(function()
75
76 for mathdata, pagenumber in next, blobs do
77 local p = pagedata[pagenumber]
78 p.mathml = mathdata
79 p.number = pagenumber
80 end
81
82 savetable(statusname, {
83 pagedata = pagedata,
84 namedata = namedata,
85 })
86 end)
87end
88
89function svgmath.register(index,page,specification)
90 if specification then
91 pagedata[page] = specification
92 end
93 namedata[index] = page
94end
95
96function svgmath.convert(filename,svgstyle)
97 if not filename then
98
99 return false, "no filename"
100 elseif not isfile(filename) then
101
102 return false, "invalid filename"
103 elseif not pdftosvg then
104 return false, "mutool is not installed"
105 end
106
107 os.execute(f_make_tex(filename,svgstyle))
108
109 local data = loadtable(statusname)
110 if not data then
111
112 return false, "invalid tex run"
113 elseif not next(data) then
114 return false, "no converson needed"
115 end
116
117 local pagedata = data.pagedata
118 local namedata = data.namedata
119
120 os.execute(f_make_svg(pdfname))
121
122 local root = xmlload(filename)
123 local index = 0
124 local done = { }
125 local unique = 0
126
127 local between = (1-P("<"))^1/""
128 local strip = Cs((
129 (P("<text") * ((1-P("</text>"))^1) * P("</text>")) * between^0 / "" +
130 P(">") * between +
131 P(1)
132 )^1)
133
134 for mth in xmlcollected(root,"m:math") do
135 index = index + 1
136 local page = namedata[index]
137 if done[page] then
138 mth.__p__.dt[mth.ni] = done[page]
139 else
140 local info = pagedata[page]
141 local depth = info.depth
142 local mode = info.mode
143 local svgname = addsuffix(f_math_tmp(page),"svg")
144 local action = mode == "inline" and f_inline or f_display
145
146 local x_div = xmlfirst(xmlconvert(action()),"/div")
147 local svgdata = io.loaddata(svgname)
148 if not svgdata or svgdata == "" then
149 print("error in:",svgname,tostring(mth))
150 else
151
152 svgdata = lpegmatch(strip,svgdata)
153 local x_svg = xmlfirst(xmlconvert(svgdata),"/svg")
154
155if mode == "inline" then
156 x_svg.at.style = f_style(-depth)
157end
158
159 x_div.dt = { x_svg }
160 mth.__p__.dt[mth.ni] = x_div
161 end
162 done[page] = x_div
163 unique = unique + 1
164 end
165 end
166
167
168
169
170
171
172
173 xmlsave(root,filename)
174
175 return true, index, unique
176end
177 |