36
37:- module(cpa_wiki,
38 [ serve_page/2
39 ]). 40:- use_module(library(http/http_dispatch)). 41:- use_module(library(http/http_parameters)). 42:- use_module(library(http/http_dirindex)). 43:- use_module(library(http/html_write)). 44:- use_module(library(pldoc/doc_wiki)). 45:- use_module(library(readutil)). 46:- use_module(library(option)). 47:- use_module(library(settings)). 48:- use_module(library(pldoc/doc_index)). 49:- use_module(library(pldoc/doc_html),
50 except([ file//2,
51 include//3
52 ])). 53
62
63:- setting(http:index_files,
64 list(atom),
65 [ 'index.txt', 'index.html' ],
66 'List of files that provide a directory index'). 67
84
85serve_page(Alias, Request) :-
86 memberchk(path_info(Relative), Request),
87 Spec =.. [ Alias, Relative ],
88 http_safe_file(Spec, []),
89 find_file(Spec, File), !,
90 setup_call_cleanup(b_setval(doc_alias, Alias),
91 serve_file(File, Request),
92 nb_delete(Alias)).
93serve_page(Alias, Request) :-
94 \+ memberchk(path_info(_), Request), !,
95 serve_page(Alias, [path_info('index.html')|Request]).
96serve_page(_, Request) :-
97 http_404([], Request).
98
104
105find_file(Spec, File) :-
106 spec_replace_extension(Spec, html, txt, TxtSpec),
107 absolute_file_name(TxtSpec,
108 File,
109 [ access(read),
110 file_errors(fail)
111 ]), !.
112find_file(Spec, File) :-
113 absolute_file_name(Spec,
114 File,
115 [ access(read),
116 file_errors(fail)
117 ]).
118find_file(Spec, File) :-
119 absolute_file_name(Spec,
120 File,
121 [ access(read),
122 file_errors(fail),
123 file_type(directory)
124 ]).
125
126spec_replace_extension(File0, Ext0, Ext, File) :-
127 atomic(File0), !,
128 file_name_extension(Base, Ext0, File0),
129 file_name_extension(Base, Ext, File).
130spec_replace_extension(Comp0, Ext0, Ext, Comp) :-
131 Comp0 =.. [Alias,Inside0],
132 spec_replace_extension(Inside0, Ext0, Ext, Inside),
133 Comp =.. [Alias,Inside].
134
139
140serve_file(File, Request) :-
141 file_name_extension(_, Ext, File),
142 debug(plweb, 'Serving ~q; ext=~q', [File, Ext]),
143 serve_file(Ext, File, Request).
144
145serve_file('', Dir, Request) :-
146 exists_directory(Dir), !,
147 ( sub_atom(Dir, _, _, 0, /),
148 serve_index_file(Dir, Request)
149 -> true
150 ; http_reply_dirindex(Dir, [unsafe(true)], Request)
151 ).
152serve_file(txt, File, Request) :-
153 http_parameters(Request,
154 [ format(Format, [ oneof([raw,html]),
155 default(html)
156 ])
157 ]),
158 Format == html, !,
159 read_file_to_codes(File, String, []),
160 setup_call_cleanup(b_setval(pldoc_file, File),
161 serve_wiki(String, File, Request),
162 nb_delete(pldoc_file)).
163serve_file(_Ext, File, Request) :- 164 http_reply_file(File, [unsafe(true)], Request).
165
169
170serve_index_file(Dir, Request) :-
171 setting(http:index_files, Indices),
172 member(Index, Indices),
173 ensure_slash(Dir, DirSlash),
174 atom_concat(DirSlash, Index, File),
175 access_file(File, read), !,
176 serve_file(File, Request).
177
178ensure_slash(Dir, Dir) :-
179 sub_atom(Dir, _, _, 0, /), !.
180ensure_slash(Dir0, Dir) :-
181 atom_concat(Dir0, /, Dir).
182
183
187
188serve_wiki(String, File, Request) :-
189 wiki_codes_to_dom(String, [], DOM0),
190 ( sub_term(h1(_, Title), DOM0)
191 -> true
192 ; Title = 'SWI-Prolog'
193 ),
194 insert_edit_button(DOM0, File, Request, DOM),
195 setup_call_cleanup(b_setval(pldoc_options,
196 [ prefer(manual)
197 ]),
198 serve_wiki_page(Title, DOM),
199 nb_delete(pldoc_options)).
200
201serve_wiki_page(Title, DOM) :-
202 reply_html_page(pldoc(wiki),
203 [ title(Title)
204 ],
205 DOM).
206
207insert_edit_button(DOM, _, Request, DOM) :-
208 \+ catch(http:authenticate(pldoc(edit), Request, _), _, fail), !.
209insert_edit_button([h1(Attrs,Title)|DOM], File, _,
210 [h1(Attrs,[ span(style('float:right'),
211 \edit_button(File, [edit(true)]))
212 | Title
213 ])|DOM]) :- !.
214insert_edit_button(DOM, File, _,
215 [ h1(class(wiki),
216 [ span(style('float:right'),
217 \edit_button(File, [edit(true)]))
218 ])
219 | DOM
220 ]).
221
222
223:- public 224 include//3,
225 file//2. 226
227 230
232
233include(Object, Type, Options) -->
234 pldoc_html:include(Object, Type,
235 [ map_extension([txt-html])
236 | Options
237 ]).
238
244
245file(Path, Options) -->
246 { \+ option(label(_), Options),
247 file_name_extension(Base, txt, Path),
248 option(absolute_path(AbsPath), Options),
249 current_alias_root(DocRoot),
250 sub_atom(AbsPath, 0, _, _, DocRoot), !,
251 file_base_name(Base, Label),
252 file_href(Options, Options1)
253 },
254 pldoc_html:file(Path,
255 [ label(Label),
256 map_extension([txt-html])
257 | Options1
258 ]).
259file(File, Options) -->
260 { file_href(Options, Options1)
261 },
262 pldoc_html:file(File,
263 [ map_extension([txt-html])
264 | Options1
265 ]).
266
267
268file_href(Options0, Options) :-
269 \+ ( nb_current(pldoc_file, CFile),
270 CFile \== []
271 ),
272 option(absolute_path(Path), Options0),
273 current_alias_root(DocRoot),
274 atom_concat(DocRoot, DocLocal, Path), !,
275 ensure_leading_slash(DocLocal, HREF),
276 Options = [ href(HREF) | Options0 ].
277file_href(Options0, Options) :-
278 nb_current(pldoc_file, CFile),
279 CFile \== [],
280 option(absolute_path(Path), Options0),
281 plfile_href(Path, HREF),
282 Options = [ href(HREF)|Options0 ].
283file_href(Options, Options).
284
289
290plfile_href(Path, HREF) :-
291 file_name_extension(_, Ext, Path),
292 prolog_file_type(Ext, prolog),
293 current_alias_root(DocRoot),
294 sub_atom(Path, 0, _, _, DocRoot), !,
295 doc_file_href(Path, HREF0),
296 atom_concat(HREF0, '?show=src', HREF).
297plfile_href(Path, HREF) :-
298 doc_file_href(Path, HREF).
299
303
304current_alias_root(DocRoot) :-
305 ( nb_current(doc_alias, Val), Val \== []
306 -> Alias = Val
307 ; Alias = document_root
308 ),
309 Term =.. [Alias,'.'],
310 absolute_file_name(Term,
311 DocRoot,
312 [ file_type(directory),
313 access(read)
314 ]).
315
316
317ensure_leading_slash(Path, SlashPath) :-
318 ( sub_atom(Path, 0, _, _, /)
319 -> SlashPath = Path
320 ; atom_concat(/, Path, SlashPath)
321 )