1if not modules then modules = { } end modules [ ' util-sci ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to m-scite.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 gsub , sub , find = string . gsub , string . sub , string . find
10local concat = table . concat
11local formatters = string . formatters
12local lpegmatch = lpeg . match
13local setmetatableindex = table . setmetatableindex
14
15local scite = scite or { }
16utilities . scite = scite
17
18local report = logs . reporter ( " scite " )
19
20do
21
22
23 lexerroot = file . dirname ( resolvers . findfile ( " scite-context-lexer.lua " ) )
24
25 if lfs . isdir ( lexerroot ) then
26 package . extraluapath ( lexerroot )
27 package . extraluapath ( lexerroot . . " /themes " )
28 package . extraluapath ( lexerroot . . " /data " )
29 report ( " using lexer root %a " , lexerroot )
30 else
31 report ( " no valid lexer root " )
32 end
33end
34
35local knownlexers = {
36 tex = " tex " ,
37 mkiv = " tex " , mkvi = " tex " ,
38 mkxl = " tex " , mklx = " tex " ,
39 mkxi = " tex " , mkix = " tex " ,
40 mkii = " tex " ,
41 bib = " bibtex " ,
42 cld = " tex " ,
43 lua = " lua " , lmt = " lua " ,
44 lfg = " lua " , lus = " lua " , luv = " lua " ,
45 mp = " mps " ,
46 mpiv = " mps " ,
47 mpxl = " mps " ,
48 mpii = " mps " ,
49 w = " web " , ww = " web " ,
50 c = " cpp " , h = " cpp " ,
51 cpp = " cpp " , hpp = " cpp " ,
52 cxx = " cpp " , hxx = " cpp " ,
53 xml = " xml " , xsl = " xml " , xsd = " xml " , dtd = " xml " ,
54 lmx = " xml " , ctx = " xml " , rlx = " xml " ,
55 css = " xml " ,
56 rme = " txt " ,
57 txt = " txt " ,
58
59}
60
61lexer = nil
62
63local function loadscitelexer ( )
64 if not lexer then
65 lexer = require ( " scite-context-lexer " )
66 require ( " scite-context-theme " )
67 if lexer then
68 lexer . context . disablewordcheck ( )
69 end
70 end
71 return lexer
72end
73
74local loadedlexers = setmetatableindex ( function ( t , k )
75 local l = knownlexers [ k ] or k
76 loadscitelexer ( )
77 local v = lexer . load ( formatters [ " scite-context-lexer-%s " ] ( l ) )
78 t [ l ] = v
79 t [ k ] = v
80 return v
81end )
82
83scite . loadedlexers = loadedlexers
84scite . knownlexers = knownlexers
85scite . loadscitelexer = loadscitelexer
86
87local f_fore_bold = formatters [ ' .%s { display:inline; font-weight:bold; color:#%02X%02X%02X; } ' ]
88local f_fore_none = formatters [ ' .%s { display:inline; font-weight:normal; color:#%02X%02X%02X; } ' ]
89local f_none_bold = formatters [ ' .%s { display:inline; font-weight:bold; } ' ]
90local f_none_none = formatters [ ' .%s { display:inline; font-weight:normal; } ' ]
91local f_div_class = formatters [ ' <div class="%s">%s</div> ' ]
92local f_linenumber = formatters [ ' <div class="linenumber">%s</div>\n ' ]
93local f_lineerror = formatters [ ' <div class="linenumber lineerror">%s</div>\n ' ]
94local f_div_number = formatters [ ' .linenumber { display:inline-block; font-weight:normal; width:%sem; margin-right:2em; padding-right:.25em; text-align:right; color:#000000; } ' ]
95local s_div_error = ' .lineerror { font-weight:bold; color:#FFFFFF; background-color:#000000; } '
96
97local replacer_regular = lpeg . replacer {
98 [ " < " ] = " < " ,
99 [ " > " ] = " > " ,
100 [ " & " ] = " & " ,
101}
102
103local linenumber = 0
104local lineerror = 0
105local linenumbers = { }
106
107local replacer_numbered = lpeg . replacer {
108 [ " < " ] = " < " ,
109 [ " > " ] = " > " ,
110 [ " & " ] = " & " ,
111 [ lpeg . patterns . newline ] = function ( )
112 linenumber = linenumber + 1
113 linenumbers [ linenumber ] = ( linenumber = = lineerror and f_lineerror or f_linenumber ) ( linenumber )
114 return " \n "
115 end ,
116}
117
118local css = nil
119
120local function exportcsslexing ( )
121 if not css then
122 loadscitelexer ( )
123 local function black ( f )
124 return ( # f = = 0 and f [ 1 ] = = 0 ) or ( ( f [ 1 ] = = f [ 2 ] ) and ( f [ 2 ] = = f [ 3 ] ) and ( f [ 3 ] = = 0 ) )
125 end
126 local result , r = { } , 0
127 for k , v in table . sortedhash ( lexer . context . styles ) do
128 local bold = v . bold
129 local fore = v . fore
130 r = r + 1
131 if fore and not black ( fore ) then
132 local cr , cg , cb = fore [ 1 ] , fore [ 2 ] , fore [ 3 ]
133 result [ r ] = ( bold and f_fore_bold or f_fore_none ) ( k , cr , cg or cr , cb or cr )
134 else
135 result [ r ] = ( bold and f_none_bold or f_none_none ) ( k )
136 end
137 end
138 css = concat ( result , " \n " )
139 end
140 return css
141end
142
143local function exportwhites ( )
144 return setmetatableindex ( function ( t , k )
145 local v = find ( k , " white " , 1 , true ) and true or false
146 t [ k ] = v
147 return v
148 end )
149end
150
151local function exportstyled ( lexer , text , numbered )
152 local result = lexer . lex ( lexer , text , 0 )
153 local start = 1
154 local whites = exportwhites ( )
155 local buffer = { }
156 local b = 0
157 linenumber = 0
158 linenumbers = { }
159 lineerror = tonumber ( numbered ) or 0
160 local replacer = numbered and replacer_numbered or replacer_regular
161 local n = # result
162 for i = 1 , n , 2 do
163 local ii = i + 1
164 local style = result [ i ]
165 local position = result [ ii ]
166 local txt = sub ( text , start , position -1 )
167 txt = lpegmatch ( replacer , txt )
168 b = b + 1
169 if whites [ style ] then
170 buffer [ b ] = txt
171 else
172 buffer [ b ] = f_div_class ( style , txt )
173 end
174 start = position
175 end
176 return concat ( buffer ) , concat ( linenumbers )
177end
178
179local function exportcsslinenumber ( )
180 return f_div_number ( # tostring ( linenumber ) / 2 + 1 ) . . " \n " . . s_div_error
181end
182
183local htmlfile = utilities . templates . replacer ( [[
184<?xml version="1.0"?>
185<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
186 <html xmlns="http://www.w3.org/1999/xhtml">
187 <title>%title%</title>
188 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
189 <style type="text/css"><!--
190%lexingstyles%
191%numberstyles%
192 --></style>
193 <body>
194 <table style="padding:0; margin:0; background-color:#FFFFFF;">
195 <tr>
196 <td><pre>%linenumbers%</pre></td>
197 <td><pre>%lexedcontent%</pre></td>
198 </tr>
199 </table>
200 </body>
201</html>
202 ]] )
203
204local htmlblob = utilities . templates . replacer ( [[
205<style type="text/css"><!--
206%lexingstyles%
207%numberstyles%
208--></style>
209<table style="padding:0; margin:0; background-color:#FFFFFF;">
210 <tr>
211 <td><pre>%linenumbers%</pre></td>
212 <td><pre>%lexedcontent%</pre></td>
213 </tr>
214</table>
215 ]] )
216
217function scite . tohtml ( data , lexname , numbered , title )
218 local source , lines = exportstyled ( loadedlexers [ lexname ] , data or " " , numbered )
219 if source then
220 return ( title = = false and htmlblob or htmlfile ) {
221 lexedcontent = source ,
222 lexingstyles = exportcsslexing ( ) ,
223 numberstyles = exportcsslinenumber ( ) ,
224 title = title or " context source file " ,
225 linenumbers = lines ,
226 }
227 end
228end
229
230local function maketargetname ( name )
231 if name then
232 return file . removesuffix ( name ) . . " - " . . file . suffix ( name ) . . " .html "
233 else
234 return " util-sci.html "
235 end
236end
237
238function scite . filetohtml ( filename , lexname , targetname , numbered , title )
239 io . savedata ( targetname or " util-sci.html " , scite . tohtml ( io . loaddata ( filename ) , lexname or file . suffix ( filename ) , numbered , title or filename ) )
240end
241
242function scite . css ( )
243 return exportcsslexing ( ) . . " \n " . . exportcsslinenumber ( )
244end
245
246function scite . html ( data , lexname , numbered )
247 return exportstyled ( loadedlexers [ lexname ] , data or " " , numbered )
248end
249
250local f_tree_entry = formatters [ ' <a href="%s" class="dir-entry">%s</a> ' ]
251
252local htmlfile = utilities . templates . replacer ( [[
253<?xml version="1.0"?>
254<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
255 <html xmlns="http://www.w3.org/1999/xhtml">
256 <title>%title%</title>
257 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
258 <style type="text/css"><!--
259%styles%
260 --></style>
261 <body>
262 <pre>
263%dirlist%
264 </pre>
265 </body>
266</html>
267 ]] )
268
269function scite . converttree ( sourceroot , targetroot , numbered )
270 if lfs . isdir ( sourceroot ) then
271 statistics . starttiming ( )
272 local skipped = { }
273 local noffiles = 0
274 dir . makedirs ( targetroot )
275 local function scan ( sourceroot , targetroot , subpath )
276 local tree = { }
277 for name in lfs . dir ( sourceroot ) do
278 if name ~ = " . " and name ~ = " .. " then
279 local sourcename = file . join ( sourceroot , name )
280 local targetname = file . join ( targetroot , name )
281 local mode = lfs . attributes ( sourcename , ' mode ' )
282 local path = subpath and file . join ( subpath , name ) or name
283 if mode = = ' file ' then
284 local filetype = file . suffix ( sourcename )
285 local basename = file . basename ( name )
286 local targetname = maketargetname ( targetname )
287 local fullname = file . join ( path , name )
288 if knownlexers [ filetype ] then
289 report ( " converting file %a to %a " , sourcename , targetname )
290 scite . filetohtml ( sourcename , nil , targetname , numbered , fullname )
291 noffiles = noffiles + 1
292 tree [ # tree + 1 ] = f_tree_entry ( file . basename ( targetname ) , basename )
293 else
294 skipped [ filetype ] = true
295 report ( " no lexer for %a " , sourcename )
296 end
297 else
298 dir . makedirs ( targetname )
299 scan ( sourcename , targetname , path )
300 tree [ # tree + 1 ] = f_tree_entry ( file . join ( name , " files.html " ) , name )
301 end
302 end
303 end
304 report ( " saving tree in %a " , targetroot )
305 local htmldata = htmlfile {
306 dirlist = concat ( tree , " \n " ) ,
307 styles = " " ,
308 title = path or " context dir listing " ,
309 }
310 io . savedata ( file . join ( targetroot , " files.html " ) , htmldata )
311 end
312 scan ( sourceroot , targetroot )
313 if next ( skipped ) then
314 report ( " skipped filetypes: %a " , table . concat ( table . sortedkeys ( skipped ) , " " ) )
315 end
316 statistics . stoptiming ( )
317 report ( " conversion time for %s files: %s " , noffiles , statistics . elapsedtime ( ) )
318 end
319end
320
321
322
323
324
325
326return scite
327 |