Fossil SCM

Simplify the internal interfaces used for injecting built-in Javascript files onto a web page.

drh 2020-07-31 22:04 trunk merge
Commit 036a9d5c586b58d76286f858efc7e9363a078a60c1769ae5f8c9e20dae0e960f
+1 -1
--- src/browse.c
+++ src/browse.c
@@ -911,11 +911,11 @@
911911
}
912912
}
913913
}
914914
@ </ul>
915915
@ </ul></div>
916
- style_load_one_js_file("tree.js");
916
+ builtin_request_js("tree.js");
917917
style_footer();
918918
919919
/* We could free memory used by sTree here if we needed to. But
920920
** the process is about to exit, so doing so would not really accomplish
921921
** anything useful. */
922922
--- src/browse.c
+++ src/browse.c
@@ -911,11 +911,11 @@
911 }
912 }
913 }
914 @ </ul>
915 @ </ul></div>
916 style_load_one_js_file("tree.js");
917 style_footer();
918
919 /* We could free memory used by sTree here if we needed to. But
920 ** the process is about to exit, so doing so would not really accomplish
921 ** anything useful. */
922
--- src/browse.c
+++ src/browse.c
@@ -911,11 +911,11 @@
911 }
912 }
913 }
914 @ </ul>
915 @ </ul></div>
916 builtin_request_js("tree.js");
917 style_footer();
918
919 /* We could free memory used by sTree here if we needed to. But
920 ** the process is about to exit, so doing so would not really accomplish
921 ** anything useful. */
922
+125
--- src/builtin.c
+++ src/builtin.c
@@ -211,5 +211,130 @@
211211
etag_check(0,0);
212212
}
213213
blob_init(&out, zTxt, -1);
214214
cgi_set_content(&out);
215215
}
216
+
217
+/* Variables controlling the JS cache.
218
+*/
219
+static struct {
220
+ int aReq[30]; /* Indexes of all requested built-in JS files */
221
+ int nReq; /* Number of slots in aReq[] currently used */
222
+ int nSent; /* Number of slots in aReq[] fulfilled */
223
+ int eDelivery; /* Delivery mechanism */
224
+} builtin;
225
+
226
+#if INTERFACE
227
+/* Various delivery mechanisms. The 0 option is the default.
228
+*/
229
+#define JS_INLINE 0 /* inline, batched together at end of file */
230
+#define JS_SEPARATE 1 /* Separate HTTP request for each JS file */
231
+#define JS_BUNDLED 2 /* One HTTP request to load all JS files */
232
+ /* concatenated together into a bundle */
233
+#endif /* INTERFACE */
234
+
235
+/*
236
+** The argument is a request to change the javascript delivery mode.
237
+** The argument is a string which is a command-line option or CGI
238
+** parameter. Try to match it against one of the delivery options
239
+** and set things up accordingly. Throw an error if no match unless
240
+** bSilent is true.
241
+*/
242
+void builtin_set_js_delivery_mode(const char *zMode, int bSilent){
243
+ if( zMode==0 ) return;
244
+ if( strcmp(zMode, "inline")==0 ){
245
+ builtin.eDelivery = JS_INLINE;
246
+ }else
247
+ if( strcmp(zMode, "separate")==0 ){
248
+ builtin.eDelivery = JS_SEPARATE;
249
+ }else
250
+ if( strcmp(zMode, "bundled")==0 ){
251
+ builtin.eDelivery = JS_BUNDLED;
252
+ }else if( !bSilent ){
253
+ fossil_fatal("unknown javascript delivery mode \"%s\" - should be"
254
+ " one of: inline separate bundled", zMode);
255
+ }
256
+}
257
+
258
+/*
259
+** The caller wants the Javascript file named by zFilename to be
260
+** included in the generated page. Add the file to the queue of
261
+** requested javascript resources, if it is not there already.
262
+**
263
+** The current implementation queues the file to be included in the
264
+** output later. However, the caller should not depend on that
265
+** behavior. In the future, this routine might decide to insert
266
+** the requested javascript inline, immedaitely, or to insert
267
+** a <script src=..> element to reference the javascript as a
268
+** separate resource. The exact behavior might change in the future
269
+** so pages that use this interface must not rely on any particular
270
+** behavior.
271
+**
272
+** All this routine guarantees is that the named javascript file
273
+** will be requested by the browser at some point. This routine
274
+** does not guarantee when the javascript will be included, and it
275
+** does not guarantee whether the javascript will be added inline or
276
+** delivered as a separate resource.
277
+*/
278
+void builtin_request_js(const char *zFilename){
279
+ int i = builtin_file_index(zFilename);
280
+ int j;
281
+ if( i<0 ){
282
+ fossil_panic("unknown javascript file: \"%s\"", zFilename);
283
+ }
284
+ for(j=0; j<builtin.nReq; j++){
285
+ if( builtin.aReq[j]==i ) return; /* Already queued or sent */
286
+ }
287
+ if( builtin.nReq>=count(builtin.aReq) ){
288
+ fossil_panic("too many javascript files requested");
289
+ }
290
+ builtin.aReq[builtin.nReq++] = i;
291
+}
292
+
293
+/*
294
+** Fulfill all pending requests for javascript files.
295
+**
296
+** The current implementation delivers all javascript in-line. However,
297
+** the caller should not depend on this. Future changes to this routine
298
+** might choose to deliver javascript as separate resources.
299
+*/
300
+void builtin_fulfill_js_requests(void){
301
+ if( builtin.nSent>=builtin.nReq ) return; /* nothing to do */
302
+ switch( builtin.eDelivery ){
303
+ case JS_INLINE: {
304
+ CX("<script nonce='%h'>\n",style_nonce());
305
+ do{
306
+ int i = builtin.aReq[builtin.nSent++];
307
+ CX("/* %s */\n", aBuiltinFiles[i].zName);
308
+ cgi_append_content((const char*)aBuiltinFiles[i].pData,
309
+ aBuiltinFiles[i].nByte);
310
+ }while( builtin.nSent<builtin.nReq );
311
+ CX("</script>\n");
312
+ break;
313
+ }
314
+ case JS_BUNDLED: {
315
+ if( builtin.nSent+1<builtin.nReq ){
316
+ Blob aList;
317
+ blob_init(&aList,0,0);
318
+ while( builtin.nSent<builtin.nReq ){
319
+ blob_appendf(&aList, ",%d", builtin.aReq[builtin.nSent++]+1);
320
+ }
321
+ CX("<script src='%R/builtin?m=%s&id=%.8s'></script>\n",
322
+ blob_str(&aList)+1, fossil_exe_id());
323
+ blob_reset(&aList);
324
+ break;
325
+ }
326
+ /* If there is only one JS file, fall through into the
327
+ ** JS_SEPARATE case below. */
328
+ /*FALLTHROUGH*/
329
+ }
330
+ case JS_SEPARATE: {
331
+ /* Each JS file as a separate resource */
332
+ while( builtin.nSent<builtin.nReq ){
333
+ int i = builtin.aReq[builtin.nSent++];
334
+ CX("<script src='%R/builtin?name=%t&id=%.8s'></script>\n",
335
+ aBuiltinFiles[i].zName, fossil_exe_id());
336
+ }
337
+ break;
338
+ }
339
+ }
340
+}
216341
--- src/builtin.c
+++ src/builtin.c
@@ -211,5 +211,130 @@
211 etag_check(0,0);
212 }
213 blob_init(&out, zTxt, -1);
214 cgi_set_content(&out);
215 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
--- src/builtin.c
+++ src/builtin.c
@@ -211,5 +211,130 @@
211 etag_check(0,0);
212 }
213 blob_init(&out, zTxt, -1);
214 cgi_set_content(&out);
215 }
216
217 /* Variables controlling the JS cache.
218 */
219 static struct {
220 int aReq[30]; /* Indexes of all requested built-in JS files */
221 int nReq; /* Number of slots in aReq[] currently used */
222 int nSent; /* Number of slots in aReq[] fulfilled */
223 int eDelivery; /* Delivery mechanism */
224 } builtin;
225
226 #if INTERFACE
227 /* Various delivery mechanisms. The 0 option is the default.
228 */
229 #define JS_INLINE 0 /* inline, batched together at end of file */
230 #define JS_SEPARATE 1 /* Separate HTTP request for each JS file */
231 #define JS_BUNDLED 2 /* One HTTP request to load all JS files */
232 /* concatenated together into a bundle */
233 #endif /* INTERFACE */
234
235 /*
236 ** The argument is a request to change the javascript delivery mode.
237 ** The argument is a string which is a command-line option or CGI
238 ** parameter. Try to match it against one of the delivery options
239 ** and set things up accordingly. Throw an error if no match unless
240 ** bSilent is true.
241 */
242 void builtin_set_js_delivery_mode(const char *zMode, int bSilent){
243 if( zMode==0 ) return;
244 if( strcmp(zMode, "inline")==0 ){
245 builtin.eDelivery = JS_INLINE;
246 }else
247 if( strcmp(zMode, "separate")==0 ){
248 builtin.eDelivery = JS_SEPARATE;
249 }else
250 if( strcmp(zMode, "bundled")==0 ){
251 builtin.eDelivery = JS_BUNDLED;
252 }else if( !bSilent ){
253 fossil_fatal("unknown javascript delivery mode \"%s\" - should be"
254 " one of: inline separate bundled", zMode);
255 }
256 }
257
258 /*
259 ** The caller wants the Javascript file named by zFilename to be
260 ** included in the generated page. Add the file to the queue of
261 ** requested javascript resources, if it is not there already.
262 **
263 ** The current implementation queues the file to be included in the
264 ** output later. However, the caller should not depend on that
265 ** behavior. In the future, this routine might decide to insert
266 ** the requested javascript inline, immedaitely, or to insert
267 ** a <script src=..> element to reference the javascript as a
268 ** separate resource. The exact behavior might change in the future
269 ** so pages that use this interface must not rely on any particular
270 ** behavior.
271 **
272 ** All this routine guarantees is that the named javascript file
273 ** will be requested by the browser at some point. This routine
274 ** does not guarantee when the javascript will be included, and it
275 ** does not guarantee whether the javascript will be added inline or
276 ** delivered as a separate resource.
277 */
278 void builtin_request_js(const char *zFilename){
279 int i = builtin_file_index(zFilename);
280 int j;
281 if( i<0 ){
282 fossil_panic("unknown javascript file: \"%s\"", zFilename);
283 }
284 for(j=0; j<builtin.nReq; j++){
285 if( builtin.aReq[j]==i ) return; /* Already queued or sent */
286 }
287 if( builtin.nReq>=count(builtin.aReq) ){
288 fossil_panic("too many javascript files requested");
289 }
290 builtin.aReq[builtin.nReq++] = i;
291 }
292
293 /*
294 ** Fulfill all pending requests for javascript files.
295 **
296 ** The current implementation delivers all javascript in-line. However,
297 ** the caller should not depend on this. Future changes to this routine
298 ** might choose to deliver javascript as separate resources.
299 */
300 void builtin_fulfill_js_requests(void){
301 if( builtin.nSent>=builtin.nReq ) return; /* nothing to do */
302 switch( builtin.eDelivery ){
303 case JS_INLINE: {
304 CX("<script nonce='%h'>\n",style_nonce());
305 do{
306 int i = builtin.aReq[builtin.nSent++];
307 CX("/* %s */\n", aBuiltinFiles[i].zName);
308 cgi_append_content((const char*)aBuiltinFiles[i].pData,
309 aBuiltinFiles[i].nByte);
310 }while( builtin.nSent<builtin.nReq );
311 CX("</script>\n");
312 break;
313 }
314 case JS_BUNDLED: {
315 if( builtin.nSent+1<builtin.nReq ){
316 Blob aList;
317 blob_init(&aList,0,0);
318 while( builtin.nSent<builtin.nReq ){
319 blob_appendf(&aList, ",%d", builtin.aReq[builtin.nSent++]+1);
320 }
321 CX("<script src='%R/builtin?m=%s&id=%.8s'></script>\n",
322 blob_str(&aList)+1, fossil_exe_id());
323 blob_reset(&aList);
324 break;
325 }
326 /* If there is only one JS file, fall through into the
327 ** JS_SEPARATE case below. */
328 /*FALLTHROUGH*/
329 }
330 case JS_SEPARATE: {
331 /* Each JS file as a separate resource */
332 while( builtin.nSent<builtin.nReq ){
333 int i = builtin.aReq[builtin.nSent++];
334 CX("<script src='%R/builtin?name=%t&id=%.8s'></script>\n",
335 aBuiltinFiles[i].zName, fossil_exe_id());
336 }
337 break;
338 }
339 }
340 }
341
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -407,11 +407,10 @@
407407
{ "smtp_send_line", 2, FMT_SAFE },
408408
{ "smtp_server_send", 2, FMT_SAFE },
409409
{ "socket_set_errmsg", 1, FMT_SAFE },
410410
{ "ssl_set_errmsg", 1, FMT_SAFE },
411411
{ "style_header", 1, FMT_HTML },
412
- { "style_js_onload", 1, FMT_HTML },
413412
{ "style_set_current_page", 1, FMT_URL },
414413
{ "style_submenu_element", 2, FMT_URL },
415414
{ "style_submenu_sql", 3, FMT_SQL },
416415
{ "webpage_error", 1, FMT_SAFE },
417416
{ "xhref", 2, FMT_URL },
418417
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -407,11 +407,10 @@
407 { "smtp_send_line", 2, FMT_SAFE },
408 { "smtp_server_send", 2, FMT_SAFE },
409 { "socket_set_errmsg", 1, FMT_SAFE },
410 { "ssl_set_errmsg", 1, FMT_SAFE },
411 { "style_header", 1, FMT_HTML },
412 { "style_js_onload", 1, FMT_HTML },
413 { "style_set_current_page", 1, FMT_URL },
414 { "style_submenu_element", 2, FMT_URL },
415 { "style_submenu_sql", 3, FMT_SQL },
416 { "webpage_error", 1, FMT_SAFE },
417 { "xhref", 2, FMT_URL },
418
--- src/codecheck1.c
+++ src/codecheck1.c
@@ -407,11 +407,10 @@
407 { "smtp_send_line", 2, FMT_SAFE },
408 { "smtp_server_send", 2, FMT_SAFE },
409 { "socket_set_errmsg", 1, FMT_SAFE },
410 { "ssl_set_errmsg", 1, FMT_SAFE },
411 { "style_header", 1, FMT_HTML },
 
412 { "style_set_current_page", 1, FMT_URL },
413 { "style_submenu_element", 2, FMT_URL },
414 { "style_submenu_sql", 3, FMT_SQL },
415 { "webpage_error", 1, FMT_SAFE },
416 { "xhref", 2, FMT_URL },
417
+9 -6
--- src/fileedit.c
+++ src/fileedit.c
@@ -1951,23 +1951,26 @@
19511951
19521952
blob_reset(&err);
19531953
CheckinMiniInfo_cleanup(&cimi);
19541954
style_emit_script_fossil_bootstrap(0);
19551955
append_diff_javascript(1);
1956
- style_emit_script_fetch(0);
1957
- style_emit_script_tabs(0)/*also emits fossil.dom*/;
1958
- style_emit_script_confirmer(0);
1959
- style_emit_script_builtin(0, "fossil.storage.js");
1956
+ builtin_request_js("fossil.fetch.js");
1957
+ builtin_request_js("fossil.dom.js");
1958
+ builtin_request_js("fossil.tabs.js");
1959
+ builtin_request_js("fossil.confirmer.js");
1960
+ builtin_request_js("fossil.storage.js");
19601961
19611962
/*
19621963
** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
19631964
** used for dynamically toggling certain UI components on and off.
1964
- ** Must come before fossil.page.fileedit.js.
1965
+ ** Must come before fossil.page.fileedit.js and after the fetches
1966
+ ** above.
19651967
*/
1968
+ builtin_fulfill_js_requests();
19661969
ajax_emit_js_preview_modes(1);
19671970
1968
- style_emit_script_builtin(0, "fossil.page.fileedit.js");
1971
+ builtin_request_js("fossil.page.fileedit.js");
19691972
if(blob_size(&endScript)>0){
19701973
style_emit_script_tag(0,0);
19711974
CX("\n(function(){\n");
19721975
CX("try{\n%b}\n"
19731976
"catch(e){"
19741977
--- src/fileedit.c
+++ src/fileedit.c
@@ -1951,23 +1951,26 @@
1951
1952 blob_reset(&err);
1953 CheckinMiniInfo_cleanup(&cimi);
1954 style_emit_script_fossil_bootstrap(0);
1955 append_diff_javascript(1);
1956 style_emit_script_fetch(0);
1957 style_emit_script_tabs(0)/*also emits fossil.dom*/;
1958 style_emit_script_confirmer(0);
1959 style_emit_script_builtin(0, "fossil.storage.js");
 
1960
1961 /*
1962 ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1963 ** used for dynamically toggling certain UI components on and off.
1964 ** Must come before fossil.page.fileedit.js.
 
1965 */
 
1966 ajax_emit_js_preview_modes(1);
1967
1968 style_emit_script_builtin(0, "fossil.page.fileedit.js");
1969 if(blob_size(&endScript)>0){
1970 style_emit_script_tag(0,0);
1971 CX("\n(function(){\n");
1972 CX("try{\n%b}\n"
1973 "catch(e){"
1974
--- src/fileedit.c
+++ src/fileedit.c
@@ -1951,23 +1951,26 @@
1951
1952 blob_reset(&err);
1953 CheckinMiniInfo_cleanup(&cimi);
1954 style_emit_script_fossil_bootstrap(0);
1955 append_diff_javascript(1);
1956 builtin_request_js("fossil.fetch.js");
1957 builtin_request_js("fossil.dom.js");
1958 builtin_request_js("fossil.tabs.js");
1959 builtin_request_js("fossil.confirmer.js");
1960 builtin_request_js("fossil.storage.js");
1961
1962 /*
1963 ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is
1964 ** used for dynamically toggling certain UI components on and off.
1965 ** Must come before fossil.page.fileedit.js and after the fetches
1966 ** above.
1967 */
1968 builtin_fulfill_js_requests();
1969 ajax_emit_js_preview_modes(1);
1970
1971 builtin_request_js("fossil.page.fileedit.js");
1972 if(blob_size(&endScript)>0){
1973 style_emit_script_tag(0,0);
1974 CX("\n(function(){\n");
1975 CX("try{\n%b}\n"
1976 "catch(e){"
1977
+3 -3
--- src/forum.c
+++ src/forum.c
@@ -759,14 +759,14 @@
759759
*/
760760
static void forum_emit_page_js(){
761761
static int once = 0;
762762
if(0==once){
763763
once = 1;
764
- style_load_js("forum.js");
764
+ builtin_request_js("forum.js");
765765
style_emit_script_fossil_bootstrap(0);
766
- style_emit_script_dom(0);
767
- style_emit_script_builtin(0, "fossil.page.forumpost.js");
766
+ builtin_request_js("fossil.dom.js");
767
+ builtin_request_js("fossil.page.forumpost.js");
768768
}
769769
}
770770
771771
/*
772772
** WEBPAGE: forumpost
773773
--- src/forum.c
+++ src/forum.c
@@ -759,14 +759,14 @@
759 */
760 static void forum_emit_page_js(){
761 static int once = 0;
762 if(0==once){
763 once = 1;
764 style_load_js("forum.js");
765 style_emit_script_fossil_bootstrap(0);
766 style_emit_script_dom(0);
767 style_emit_script_builtin(0, "fossil.page.forumpost.js");
768 }
769 }
770
771 /*
772 ** WEBPAGE: forumpost
773
--- src/forum.c
+++ src/forum.c
@@ -759,14 +759,14 @@
759 */
760 static void forum_emit_page_js(){
761 static int once = 0;
762 if(0==once){
763 once = 1;
764 builtin_request_js("forum.js");
765 style_emit_script_fossil_bootstrap(0);
766 builtin_request_js("fossil.dom.js");
767 builtin_request_js("fossil.page.forumpost.js");
768 }
769 }
770
771 /*
772 ** WEBPAGE: forumpost
773
+3 -3
--- src/info.c
+++ src/info.c
@@ -441,11 +441,11 @@
441441
/*
442442
** Generate javascript to enhance HTML diffs.
443443
*/
444444
void append_diff_javascript(int sideBySide){
445445
if( !sideBySide ) return;
446
- style_load_one_js_file("sbsdiff.js");
446
+ builtin_request_js("sbsdiff.js");
447447
}
448448
449449
/*
450450
** Construct an appropriate diffFlag for text_diff() based on query
451451
** parameters and the to boolean arguments.
@@ -2089,11 +2089,11 @@
20892089
if( z[0]=='\n' ) z++;
20902090
}
20912091
if( n<iEnd ) cgi_printf("</div>");
20922092
@ </pre>
20932093
if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2094
- style_load_one_js_file("scroll.js");
2094
+ builtin_request_js("scroll.js");
20952095
}
20962096
}
20972097
20982098
20992099
/*
@@ -3113,11 +3113,11 @@
31133113
@ <input type="submit" name="apply" value="Apply Changes" />
31143114
}
31153115
@ </td></tr>
31163116
@ </table>
31173117
@ </div></form>
3118
- style_load_one_js_file("ci_edit.js");
3118
+ builtin_request_js("ci_edit.js");
31193119
style_footer();
31203120
}
31213121
31223122
/*
31233123
** Prepare an ammended commit comment. Let the user modify it using the
31243124
--- src/info.c
+++ src/info.c
@@ -441,11 +441,11 @@
441 /*
442 ** Generate javascript to enhance HTML diffs.
443 */
444 void append_diff_javascript(int sideBySide){
445 if( !sideBySide ) return;
446 style_load_one_js_file("sbsdiff.js");
447 }
448
449 /*
450 ** Construct an appropriate diffFlag for text_diff() based on query
451 ** parameters and the to boolean arguments.
@@ -2089,11 +2089,11 @@
2089 if( z[0]=='\n' ) z++;
2090 }
2091 if( n<iEnd ) cgi_printf("</div>");
2092 @ </pre>
2093 if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2094 style_load_one_js_file("scroll.js");
2095 }
2096 }
2097
2098
2099 /*
@@ -3113,11 +3113,11 @@
3113 @ <input type="submit" name="apply" value="Apply Changes" />
3114 }
3115 @ </td></tr>
3116 @ </table>
3117 @ </div></form>
3118 style_load_one_js_file("ci_edit.js");
3119 style_footer();
3120 }
3121
3122 /*
3123 ** Prepare an ammended commit comment. Let the user modify it using the
3124
--- src/info.c
+++ src/info.c
@@ -441,11 +441,11 @@
441 /*
442 ** Generate javascript to enhance HTML diffs.
443 */
444 void append_diff_javascript(int sideBySide){
445 if( !sideBySide ) return;
446 builtin_request_js("sbsdiff.js");
447 }
448
449 /*
450 ** Construct an appropriate diffFlag for text_diff() based on query
451 ** parameters and the to boolean arguments.
@@ -2089,11 +2089,11 @@
2089 if( z[0]=='\n' ) z++;
2090 }
2091 if( n<iEnd ) cgi_printf("</div>");
2092 @ </pre>
2093 if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){
2094 builtin_request_js("scroll.js");
2095 }
2096 }
2097
2098
2099 /*
@@ -3113,11 +3113,11 @@
3113 @ <input type="submit" name="apply" value="Apply Changes" />
3114 }
3115 @ </td></tr>
3116 @ </table>
3117 @ </div></form>
3118 builtin_request_js("ci_edit.js");
3119 style_footer();
3120 }
3121
3122 /*
3123 ** Prepare an ammended commit comment. Let the user modify it using the
3124
+1 -1
--- src/login.c
+++ src/login.c
@@ -752,11 +752,11 @@
752752
@ %h(zCaptcha)
753753
@ </pre></td></tr></table>
754754
if( bAutoCaptcha ) {
755755
@ <input type="button" value="Fill out captcha" id='autofillButton' \
756756
@ data-af='%s(zDecoded)' />
757
- style_load_one_js_file("login.js");
757
+ builtin_request_js("login.js");
758758
}
759759
@ </div>
760760
free(zCaptcha);
761761
}
762762
@ </form>
763763
--- src/login.c
+++ src/login.c
@@ -752,11 +752,11 @@
752 @ %h(zCaptcha)
753 @ </pre></td></tr></table>
754 if( bAutoCaptcha ) {
755 @ <input type="button" value="Fill out captcha" id='autofillButton' \
756 @ data-af='%s(zDecoded)' />
757 style_load_one_js_file("login.js");
758 }
759 @ </div>
760 free(zCaptcha);
761 }
762 @ </form>
763
--- src/login.c
+++ src/login.c
@@ -752,11 +752,11 @@
752 @ %h(zCaptcha)
753 @ </pre></td></tr></table>
754 if( bAutoCaptcha ) {
755 @ <input type="button" value="Fill out captcha" id='autofillButton' \
756 @ data-af='%s(zDecoded)' />
757 builtin_request_js("login.js");
758 }
759 @ </div>
760 free(zCaptcha);
761 }
762 @ </form>
763
+31
--- src/main.c
+++ src/main.c
@@ -2270,10 +2270,23 @@
22702270
** this directive is a silent no-op.
22712271
*/
22722272
skin_use_alternative(blob_str(&value));
22732273
blob_reset(&value);
22742274
continue;
2275
+ }
2276
+ if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
2277
+ /* jsmode: MODE
2278
+ **
2279
+ ** Change how javascript resources are delivered with each HTML
2280
+ ** page. MODE is "inline" to put all JS inline, or "separate" to
2281
+ ** cause each JS file to be requested using a separate HTTP request,
2282
+ ** or "bundled" to have all JS files to be fetched with a single
2283
+ ** auxiliary HTTP request.
2284
+ */
2285
+ builtin_set_js_delivery_mode(blob_str(&value),0);
2286
+ blob_reset(&value);
2287
+ continue;
22752288
}
22762289
if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
22772290
/* cgi-debug: FILENAME
22782291
**
22792292
** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
@@ -2455,10 +2468,18 @@
24552468
** --files GLOB comma-separate glob patterns for static file to serve
24562469
** --host NAME specify hostname of the server
24572470
** --https signal a request coming in via https
24582471
** --in FILE Take input from FILE instead of standard input
24592472
** --ipaddr ADDR Assume the request comes from the given IP address
2473
+** --jsmode MODE Determine how javascript is delivered with pages.
2474
+** Mode can be one of:
2475
+** inline All javascript is inserted inline at
2476
+** the end of the HTML file.
2477
+** separate Separate HTTP requests are made for
2478
+** each javascript file.
2479
+** bundled One single separate HTTP fetches all
2480
+** javascript concatenated together.
24602481
** --localauth enable automatic login for local connections
24612482
** --nocompress do not compress HTTP replies
24622483
** --nodelay omit backoffice processing if it would delay process exit
24632484
** --nojail drop root privilege but do not enter the chroot jail
24642485
** --nossl signal that no SSL connections are available
@@ -2484,10 +2505,11 @@
24842505
int useSCGI;
24852506
int noJail;
24862507
int allowRepoList;
24872508
24882509
Th_InitTraceLog();
2510
+ builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
24892511
24902512
/* The winhttp module passes the --files option as --files-urlenc with
24912513
** the argument being URL encoded, to avoid wildcard expansion in the
24922514
** shell. This option is for internal use and is undocumented.
24932515
*/
@@ -2714,10 +2736,18 @@
27142736
** --files GLOBLIST Comma-separated list of glob patterns for static files
27152737
** --localauth enable automatic login for requests from localhost
27162738
** --localhost listen on 127.0.0.1 only (always true for "ui")
27172739
** --https Indicates that the input is coming through a reverse
27182740
** proxy that has already translated HTTPS into HTTP.
2741
+** --jsmode MODE Determine how javascript is delivered with pages.
2742
+** Mode can be one of:
2743
+** inline All javascript is inserted inline at
2744
+** the end of the HTML file.
2745
+** separate Separate HTTP requests are made for
2746
+** each javascript file.
2747
+** bundled One single separate HTTP fetches all
2748
+** javascript concatenated together.
27192749
** --max-latency N Do not let any single HTTP request run for more than N
27202750
** seconds (only works on unix)
27212751
** --nocompress Do not compress HTTP replies
27222752
** --nojail Drop root privileges but do not enter the chroot jail
27232753
** --nossl signal that no SSL connections are available (Always
@@ -2760,10 +2790,11 @@
27602790
27612791
if( g.zErrlog==0 ){
27622792
g.zErrlog = "-";
27632793
}
27642794
g.zExtRoot = find_option("extroot",0,1);
2795
+ builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
27652796
zFileGlob = find_option("files-urlenc",0,1);
27662797
if( zFileGlob ){
27672798
char *z = mprintf("%s", zFileGlob);
27682799
dehttpize(z);
27692800
zFileGlob = z;
27702801
--- src/main.c
+++ src/main.c
@@ -2270,10 +2270,23 @@
2270 ** this directive is a silent no-op.
2271 */
2272 skin_use_alternative(blob_str(&value));
2273 blob_reset(&value);
2274 continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
2275 }
2276 if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
2277 /* cgi-debug: FILENAME
2278 **
2279 ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
@@ -2455,10 +2468,18 @@
2455 ** --files GLOB comma-separate glob patterns for static file to serve
2456 ** --host NAME specify hostname of the server
2457 ** --https signal a request coming in via https
2458 ** --in FILE Take input from FILE instead of standard input
2459 ** --ipaddr ADDR Assume the request comes from the given IP address
 
 
 
 
 
 
 
 
2460 ** --localauth enable automatic login for local connections
2461 ** --nocompress do not compress HTTP replies
2462 ** --nodelay omit backoffice processing if it would delay process exit
2463 ** --nojail drop root privilege but do not enter the chroot jail
2464 ** --nossl signal that no SSL connections are available
@@ -2484,10 +2505,11 @@
2484 int useSCGI;
2485 int noJail;
2486 int allowRepoList;
2487
2488 Th_InitTraceLog();
 
2489
2490 /* The winhttp module passes the --files option as --files-urlenc with
2491 ** the argument being URL encoded, to avoid wildcard expansion in the
2492 ** shell. This option is for internal use and is undocumented.
2493 */
@@ -2714,10 +2736,18 @@
2714 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2715 ** --localauth enable automatic login for requests from localhost
2716 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2717 ** --https Indicates that the input is coming through a reverse
2718 ** proxy that has already translated HTTPS into HTTP.
 
 
 
 
 
 
 
 
2719 ** --max-latency N Do not let any single HTTP request run for more than N
2720 ** seconds (only works on unix)
2721 ** --nocompress Do not compress HTTP replies
2722 ** --nojail Drop root privileges but do not enter the chroot jail
2723 ** --nossl signal that no SSL connections are available (Always
@@ -2760,10 +2790,11 @@
2760
2761 if( g.zErrlog==0 ){
2762 g.zErrlog = "-";
2763 }
2764 g.zExtRoot = find_option("extroot",0,1);
 
2765 zFileGlob = find_option("files-urlenc",0,1);
2766 if( zFileGlob ){
2767 char *z = mprintf("%s", zFileGlob);
2768 dehttpize(z);
2769 zFileGlob = z;
2770
--- src/main.c
+++ src/main.c
@@ -2270,10 +2270,23 @@
2270 ** this directive is a silent no-op.
2271 */
2272 skin_use_alternative(blob_str(&value));
2273 blob_reset(&value);
2274 continue;
2275 }
2276 if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
2277 /* jsmode: MODE
2278 **
2279 ** Change how javascript resources are delivered with each HTML
2280 ** page. MODE is "inline" to put all JS inline, or "separate" to
2281 ** cause each JS file to be requested using a separate HTTP request,
2282 ** or "bundled" to have all JS files to be fetched with a single
2283 ** auxiliary HTTP request.
2284 */
2285 builtin_set_js_delivery_mode(blob_str(&value),0);
2286 blob_reset(&value);
2287 continue;
2288 }
2289 if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
2290 /* cgi-debug: FILENAME
2291 **
2292 ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
@@ -2455,10 +2468,18 @@
2468 ** --files GLOB comma-separate glob patterns for static file to serve
2469 ** --host NAME specify hostname of the server
2470 ** --https signal a request coming in via https
2471 ** --in FILE Take input from FILE instead of standard input
2472 ** --ipaddr ADDR Assume the request comes from the given IP address
2473 ** --jsmode MODE Determine how javascript is delivered with pages.
2474 ** Mode can be one of:
2475 ** inline All javascript is inserted inline at
2476 ** the end of the HTML file.
2477 ** separate Separate HTTP requests are made for
2478 ** each javascript file.
2479 ** bundled One single separate HTTP fetches all
2480 ** javascript concatenated together.
2481 ** --localauth enable automatic login for local connections
2482 ** --nocompress do not compress HTTP replies
2483 ** --nodelay omit backoffice processing if it would delay process exit
2484 ** --nojail drop root privilege but do not enter the chroot jail
2485 ** --nossl signal that no SSL connections are available
@@ -2484,10 +2505,11 @@
2505 int useSCGI;
2506 int noJail;
2507 int allowRepoList;
2508
2509 Th_InitTraceLog();
2510 builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
2511
2512 /* The winhttp module passes the --files option as --files-urlenc with
2513 ** the argument being URL encoded, to avoid wildcard expansion in the
2514 ** shell. This option is for internal use and is undocumented.
2515 */
@@ -2714,10 +2736,18 @@
2736 ** --files GLOBLIST Comma-separated list of glob patterns for static files
2737 ** --localauth enable automatic login for requests from localhost
2738 ** --localhost listen on 127.0.0.1 only (always true for "ui")
2739 ** --https Indicates that the input is coming through a reverse
2740 ** proxy that has already translated HTTPS into HTTP.
2741 ** --jsmode MODE Determine how javascript is delivered with pages.
2742 ** Mode can be one of:
2743 ** inline All javascript is inserted inline at
2744 ** the end of the HTML file.
2745 ** separate Separate HTTP requests are made for
2746 ** each javascript file.
2747 ** bundled One single separate HTTP fetches all
2748 ** javascript concatenated together.
2749 ** --max-latency N Do not let any single HTTP request run for more than N
2750 ** seconds (only works on unix)
2751 ** --nocompress Do not compress HTTP replies
2752 ** --nojail Drop root privileges but do not enter the chroot jail
2753 ** --nossl signal that no SSL connections are available (Always
@@ -2760,10 +2790,11 @@
2790
2791 if( g.zErrlog==0 ){
2792 g.zErrlog = "-";
2793 }
2794 g.zExtRoot = find_option("extroot",0,1);
2795 builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);
2796 zFileGlob = find_option("files-urlenc",0,1);
2797 if( zFileGlob ){
2798 char *z = mprintf("%s", zFileGlob);
2799 dehttpize(z);
2800 zFileGlob = z;
2801
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -88,10 +88,11 @@
8888
i = k-1;
8989
continue;
9090
}
9191
}
9292
if( c=='\n' ){
93
+ if( j==0 ) continue;
9394
while( j>0 && isspace(z[j-1]) ) j--;
9495
z[j++] = '\n';
9596
while( i+1<n && isspace(z[i+1]) ) i++;
9697
continue;
9798
}
9899
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -88,10 +88,11 @@
88 i = k-1;
89 continue;
90 }
91 }
92 if( c=='\n' ){
 
93 while( j>0 && isspace(z[j-1]) ) j--;
94 z[j++] = '\n';
95 while( i+1<n && isspace(z[i+1]) ) i++;
96 continue;
97 }
98
--- src/mkbuiltin.c
+++ src/mkbuiltin.c
@@ -88,10 +88,11 @@
88 i = k-1;
89 continue;
90 }
91 }
92 if( c=='\n' ){
93 if( j==0 ) continue;
94 while( j>0 && isspace(z[j-1]) ) j--;
95 z[j++] = '\n';
96 while( i+1<n && isspace(z[i+1]) ) i++;
97 continue;
98 }
99
+1 -1
--- src/setupuser.c
+++ src/setupuser.c
@@ -702,11 +702,11 @@
702702
@ </tr>
703703
}
704704
@ </table>
705705
@ </div></form>
706706
@ </div>
707
- style_load_one_js_file("useredit.js");
707
+ builtin_request_js("useredit.js");
708708
@ <hr>
709709
@ <h1>Notes On Privileges And Capabilities:</h1>
710710
@ <ul>
711711
if( higherUser ){
712712
@ <li><p class="missingPriv">
713713
--- src/setupuser.c
+++ src/setupuser.c
@@ -702,11 +702,11 @@
702 @ </tr>
703 }
704 @ </table>
705 @ </div></form>
706 @ </div>
707 style_load_one_js_file("useredit.js");
708 @ <hr>
709 @ <h1>Notes On Privileges And Capabilities:</h1>
710 @ <ul>
711 if( higherUser ){
712 @ <li><p class="missingPriv">
713
--- src/setupuser.c
+++ src/setupuser.c
@@ -702,11 +702,11 @@
702 @ </tr>
703 }
704 @ </table>
705 @ </div></form>
706 @ </div>
707 builtin_request_js("useredit.js");
708 @ <hr>
709 @ <h1>Notes On Privileges And Capabilities:</h1>
710 @ <ul>
711 if( higherUser ){
712 @ <li><p class="missingPriv">
713
+1 -1
--- src/skins.c
+++ src/skins.c
@@ -1101,8 +1101,8 @@
11011101
@ undo a prior publish.
11021102
}else{
11031103
@ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page
11041104
@ for cleanup and recovery actions.
11051105
}
1106
- style_load_one_js_file("skin.js");
1106
+ builtin_request_js("skin.js");
11071107
style_footer();
11081108
}
11091109
--- src/skins.c
+++ src/skins.c
@@ -1101,8 +1101,8 @@
1101 @ undo a prior publish.
1102 }else{
1103 @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page
1104 @ for cleanup and recovery actions.
1105 }
1106 style_load_one_js_file("skin.js");
1107 style_footer();
1108 }
1109
--- src/skins.c
+++ src/skins.c
@@ -1101,8 +1101,8 @@
1101 @ undo a prior publish.
1102 }else{
1103 @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page
1104 @ for cleanup and recovery actions.
1105 }
1106 builtin_request_js("skin.js");
1107 style_footer();
1108 }
1109
+6 -181
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
8888
8989
/*
9090
** Flags for various javascript files needed prior to </body>
9191
*/
9292
static int needHrefJs = 0; /* href.js */
93
-static int needSortJs = 0; /* sorttable.js */
94
-static int needGraphJs = 0; /* graph.js */
95
-static int needCopyBtnJs = 0; /* copybtn.js */
96
-static int needAccordionJs = 0; /* accordion.js */
9793
9894
/*
9995
** Extra JS added to the end of the file.
10096
*/
10197
static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
484480
zBtnFmt/*works-like:"%h%s%h%h%d"*/,
485481
zTargetId,zText,zTargetId,zTargetId,cchLength);
486482
}
487483
}
488484
free(zText);
489
- style_copybutton_control();
485
+ builtin_request_js("copybtn.js");
490486
return zResult;
491487
}
492488
493489
/*
494490
** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
694690
695691
/*
696692
** Indicate that the table-sorting javascript is needed.
697693
*/
698694
void style_table_sorter(void){
699
- needSortJs = 1;
700
-}
701
-
702
-/*
703
-** Indicate that the accordion javascript is needed.
704
-*/
705
-void style_accordion(void){
706
- needAccordionJs = 1;
707
-}
708
-
709
-/*
710
-** Indicate that the timeline graph javascript is needed.
711
-*/
712
-void style_graph_generator(void){
713
- needGraphJs = 1;
714
-}
715
-
716
-/*
717
-** Indicate that the copy button javascript is needed.
718
-*/
719
-void style_copybutton_control(void){
720
- needCopyBtnJs = 1;
721
-}
722
-
723
-/*
724
-** Generate code to load a single javascript file
725
-*/
726
-void style_load_one_js_file(const char *zFile){
727
- @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
728
-}
729
-
730
-/*
731
-** All extra JS files to load.
732
-*/
733
-static const char *azJsToLoad[4];
734
-static int nJsToLoad = 0;
735
-
736
-/*
737
-** Register a new JS file to load at the end of the document.
738
-*/
739
-void style_load_js(const char *zName){
740
- int i;
741
- for(i=0; i<nJsToLoad; i++){
742
- if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return;
743
- }
744
- if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){
745
- fossil_panic("too many JS files");
746
- }
747
- azJsToLoad[nJsToLoad++] = zName;
695
+ builtin_request_js("sorttable.js");
748696
}
749697
750698
/*
751699
** Generate code to load all required javascript files.
752700
*/
753701
static void style_load_all_js_files(void){
754
- int i;
755702
if( needHrefJs ){
756703
int nDelay = db_get_int("auto-hyperlink-delay",0);
757704
int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
758705
@ <script id='href-data' type='application/json'>\
759706
@ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
762709
@ function debugMsg(msg){
763710
@ var n = document.getElementById("debugMsg");
764711
@ if(n){n.textContent=msg;}
765712
@ }
766713
if( needHrefJs ){
714
+ @ /* href.js */
767715
cgi_append_content(builtin_text("href.js"),-1);
768716
}
769
- if( needSortJs ){
770
- cgi_append_content(builtin_text("sorttable.js"),-1);
771
- }
772
- if( needGraphJs ){
773
- cgi_append_content(builtin_text("graph.js"),-1);
774
- }
775
- if( needCopyBtnJs ){
776
- cgi_append_content(builtin_text("copybtn.js"),-1);
777
- }
778
- if( needAccordionJs ){
779
- cgi_append_content(builtin_text("accordion.js"),-1);
780
- }
781
- for(i=0; i<nJsToLoad; i++){
782
- cgi_append_content(builtin_text(azJsToLoad[i]),-1);
783
- }
784717
if( blob_size(&blobOnLoad)>0 ){
785718
@ window.onload = function(){
786719
cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
787720
cgi_append_content("\n}\n", -1);
788721
}
789722
@ </script>
790
-}
791
-
792
-/*
793
-** Extra JS to run after all content is loaded.
794
-*/
795
-void style_js_onload(const char *zFormat, ...){
796
- va_list ap;
797
- va_start(ap, zFormat);
798
- blob_vappendf(&blobOnLoad, zFormat, ap);
799
- va_end(ap);
723
+ builtin_fulfill_js_requests();
800724
}
801725
802726
/*
803727
** Draw the footer at the bottom of the page.
804728
*/
@@ -916,11 +840,11 @@
916840
@ </div>
917841
if( nSubmenuCtrl ){
918842
cgi_query_parameters_to_hidden();
919843
cgi_tag_query_parameter(0);
920844
@ </form>
921
- style_load_one_js_file("menu.js");
845
+ builtin_request_js("menu.js");
922846
}
923847
}
924848
925849
zAd = style_adunit_text(&mAdFlags);
926850
if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1543,17 +1467,12 @@
15431467
"name:\"%T\""
15441468
"};\n", g.zPath);
15451469
CX("})();\n");
15461470
/* The remaining fossil object bootstrap code is not dependent on
15471471
** C-runtime state... */
1548
- if(asInline){
1549
- CX("%s\n", builtin_text("fossil.bootstrap.js"));
1550
- }
15511472
style_emit_script_tag(1,0);
1552
- if(asInline==0){
1553
- style_emit_script_builtin(0, "fossil.bootstrap.js");
1554
- }
1473
+ builtin_request_js("fossil.bootstrap.js");
15551474
}
15561475
}
15571476
15581477
/*
15591478
** If passed 0 as its first argument, it emits a script opener tag
@@ -1582,99 +1501,5 @@
15821501
}
15831502
}else{
15841503
CX("</script>\n");
15851504
}
15861505
}
1587
-
1588
-/*
1589
-** Emits a script tag which uses content from a builtin script file.
1590
-**
1591
-** If asInline is true, it is emitted directly as an opening tag, the
1592
-** content of the zName builtin file, and a closing tag.
1593
-**
1594
-** If it is false, a script tag loading it via
1595
-** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a
1596
-** build-time-dependent cache-buster value.
1597
-*/
1598
-void style_emit_script_builtin(int asInline, char const * zName){
1599
- if(asInline){
1600
- style_emit_script_tag(0,0);
1601
- CX("%s", builtin_text(zName));
1602
- style_emit_script_tag(1,0);
1603
- }else{
1604
- char * zFullName = mprintf("builtin/%s",zName);
1605
- const char * zHash = fossil_exe_id();
1606
- CX("<script src='%R/%T?cache=%.8s'></script>\n",
1607
- zFullName, zHash);
1608
- fossil_free(zFullName);
1609
- }
1610
-}
1611
-
1612
-/*
1613
-** The first time this is called it emits the JS code from the
1614
-** built-in file fossil.fossil.js. Subsequent calls are no-ops.
1615
-**
1616
-** If passed a true value, it emits the contents directly
1617
-** to the page output, else it emits a script tag with a
1618
-** src=builtin/... to load the script.
1619
-**
1620
-** Note that this code relies on that loaded via
1621
-** style_emit_script_fossil_bootstrap() but it does not call that
1622
-** routine.
1623
-*/
1624
-void style_emit_script_fetch(int asInline){
1625
- static int once = 0;
1626
- if(0==once++){
1627
- style_emit_script_builtin(asInline, "fossil.fetch.js");
1628
- }
1629
-}
1630
-
1631
-/*
1632
-** The first time this is called it emits the JS code from the
1633
-** built-in file fossil.dom.js. Subsequent calls are no-ops.
1634
-**
1635
-** If passed a true value, it emits the contents directly
1636
-** to the page output, else it emits a script tag with a
1637
-** src=builtin/... to load the script.
1638
-**
1639
-** Note that this code relies on that loaded via
1640
-** style_emit_script_fossil_bootstrap(), but it does not call that
1641
-** routine.
1642
-*/
1643
-void style_emit_script_dom(int asInline){
1644
- static int once = 0;
1645
- if(0==once++){
1646
- style_emit_script_builtin(asInline, "fossil.dom.js");
1647
- }
1648
-}
1649
-
1650
-/*
1651
-** The first time this is called, it calls style_emit_script_dom(),
1652
-** passing it the given asInline value, and emits the JS code from the
1653
-** built-in file fossil.tabs.js. Subsequent calls are no-ops.
1654
-**
1655
-** If passed a true value, it emits the contents directly
1656
-** to the page output, else it emits a script tag with a
1657
-** src=builtin/... to load the script.
1658
-*/
1659
-void style_emit_script_tabs(int asInline){
1660
- static int once = 0;
1661
- if(0==once++){
1662
- style_emit_script_dom(asInline);
1663
- style_emit_script_builtin(asInline, "fossil.tabs.js");
1664
- }
1665
-}
1666
-
1667
-/*
1668
-** The first time this is called it emits the JS code from the
1669
-** built-in file fossil.confirmer.js. Subsequent calls are no-ops.
1670
-**
1671
-** If passed a true value, it emits the contents directly
1672
-** to the page output, else it emits a script tag with a
1673
-** src=builtin/... to load the script.
1674
-*/
1675
-void style_emit_script_confirmer(int asInline){
1676
- static int once = 0;
1677
- if(0==once++){
1678
- style_emit_script_builtin(asInline, "fossil.confirmer.js");
1679
- }
1680
-}
16811506
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
88
89 /*
90 ** Flags for various javascript files needed prior to </body>
91 */
92 static int needHrefJs = 0; /* href.js */
93 static int needSortJs = 0; /* sorttable.js */
94 static int needGraphJs = 0; /* graph.js */
95 static int needCopyBtnJs = 0; /* copybtn.js */
96 static int needAccordionJs = 0; /* accordion.js */
97
98 /*
99 ** Extra JS added to the end of the file.
100 */
101 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
484 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
485 zTargetId,zText,zTargetId,zTargetId,cchLength);
486 }
487 }
488 free(zText);
489 style_copybutton_control();
490 return zResult;
491 }
492
493 /*
494 ** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
694
695 /*
696 ** Indicate that the table-sorting javascript is needed.
697 */
698 void style_table_sorter(void){
699 needSortJs = 1;
700 }
701
702 /*
703 ** Indicate that the accordion javascript is needed.
704 */
705 void style_accordion(void){
706 needAccordionJs = 1;
707 }
708
709 /*
710 ** Indicate that the timeline graph javascript is needed.
711 */
712 void style_graph_generator(void){
713 needGraphJs = 1;
714 }
715
716 /*
717 ** Indicate that the copy button javascript is needed.
718 */
719 void style_copybutton_control(void){
720 needCopyBtnJs = 1;
721 }
722
723 /*
724 ** Generate code to load a single javascript file
725 */
726 void style_load_one_js_file(const char *zFile){
727 @ <script src='%R/builtin/%s(zFile)?id=%S(fossil_exe_id())'></script>
728 }
729
730 /*
731 ** All extra JS files to load.
732 */
733 static const char *azJsToLoad[4];
734 static int nJsToLoad = 0;
735
736 /*
737 ** Register a new JS file to load at the end of the document.
738 */
739 void style_load_js(const char *zName){
740 int i;
741 for(i=0; i<nJsToLoad; i++){
742 if( fossil_strcmp(zName, azJsToLoad[i])==0 ) return;
743 }
744 if( nJsToLoad>=sizeof(azJsToLoad)/sizeof(azJsToLoad[0]) ){
745 fossil_panic("too many JS files");
746 }
747 azJsToLoad[nJsToLoad++] = zName;
748 }
749
750 /*
751 ** Generate code to load all required javascript files.
752 */
753 static void style_load_all_js_files(void){
754 int i;
755 if( needHrefJs ){
756 int nDelay = db_get_int("auto-hyperlink-delay",0);
757 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
758 @ <script id='href-data' type='application/json'>\
759 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
762 @ function debugMsg(msg){
763 @ var n = document.getElementById("debugMsg");
764 @ if(n){n.textContent=msg;}
765 @ }
766 if( needHrefJs ){
 
767 cgi_append_content(builtin_text("href.js"),-1);
768 }
769 if( needSortJs ){
770 cgi_append_content(builtin_text("sorttable.js"),-1);
771 }
772 if( needGraphJs ){
773 cgi_append_content(builtin_text("graph.js"),-1);
774 }
775 if( needCopyBtnJs ){
776 cgi_append_content(builtin_text("copybtn.js"),-1);
777 }
778 if( needAccordionJs ){
779 cgi_append_content(builtin_text("accordion.js"),-1);
780 }
781 for(i=0; i<nJsToLoad; i++){
782 cgi_append_content(builtin_text(azJsToLoad[i]),-1);
783 }
784 if( blob_size(&blobOnLoad)>0 ){
785 @ window.onload = function(){
786 cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
787 cgi_append_content("\n}\n", -1);
788 }
789 @ </script>
790 }
791
792 /*
793 ** Extra JS to run after all content is loaded.
794 */
795 void style_js_onload(const char *zFormat, ...){
796 va_list ap;
797 va_start(ap, zFormat);
798 blob_vappendf(&blobOnLoad, zFormat, ap);
799 va_end(ap);
800 }
801
802 /*
803 ** Draw the footer at the bottom of the page.
804 */
@@ -916,11 +840,11 @@
916 @ </div>
917 if( nSubmenuCtrl ){
918 cgi_query_parameters_to_hidden();
919 cgi_tag_query_parameter(0);
920 @ </form>
921 style_load_one_js_file("menu.js");
922 }
923 }
924
925 zAd = style_adunit_text(&mAdFlags);
926 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1543,17 +1467,12 @@
1543 "name:\"%T\""
1544 "};\n", g.zPath);
1545 CX("})();\n");
1546 /* The remaining fossil object bootstrap code is not dependent on
1547 ** C-runtime state... */
1548 if(asInline){
1549 CX("%s\n", builtin_text("fossil.bootstrap.js"));
1550 }
1551 style_emit_script_tag(1,0);
1552 if(asInline==0){
1553 style_emit_script_builtin(0, "fossil.bootstrap.js");
1554 }
1555 }
1556 }
1557
1558 /*
1559 ** If passed 0 as its first argument, it emits a script opener tag
@@ -1582,99 +1501,5 @@
1582 }
1583 }else{
1584 CX("</script>\n");
1585 }
1586 }
1587
1588 /*
1589 ** Emits a script tag which uses content from a builtin script file.
1590 **
1591 ** If asInline is true, it is emitted directly as an opening tag, the
1592 ** content of the zName builtin file, and a closing tag.
1593 **
1594 ** If it is false, a script tag loading it via
1595 ** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a
1596 ** build-time-dependent cache-buster value.
1597 */
1598 void style_emit_script_builtin(int asInline, char const * zName){
1599 if(asInline){
1600 style_emit_script_tag(0,0);
1601 CX("%s", builtin_text(zName));
1602 style_emit_script_tag(1,0);
1603 }else{
1604 char * zFullName = mprintf("builtin/%s",zName);
1605 const char * zHash = fossil_exe_id();
1606 CX("<script src='%R/%T?cache=%.8s'></script>\n",
1607 zFullName, zHash);
1608 fossil_free(zFullName);
1609 }
1610 }
1611
1612 /*
1613 ** The first time this is called it emits the JS code from the
1614 ** built-in file fossil.fossil.js. Subsequent calls are no-ops.
1615 **
1616 ** If passed a true value, it emits the contents directly
1617 ** to the page output, else it emits a script tag with a
1618 ** src=builtin/... to load the script.
1619 **
1620 ** Note that this code relies on that loaded via
1621 ** style_emit_script_fossil_bootstrap() but it does not call that
1622 ** routine.
1623 */
1624 void style_emit_script_fetch(int asInline){
1625 static int once = 0;
1626 if(0==once++){
1627 style_emit_script_builtin(asInline, "fossil.fetch.js");
1628 }
1629 }
1630
1631 /*
1632 ** The first time this is called it emits the JS code from the
1633 ** built-in file fossil.dom.js. Subsequent calls are no-ops.
1634 **
1635 ** If passed a true value, it emits the contents directly
1636 ** to the page output, else it emits a script tag with a
1637 ** src=builtin/... to load the script.
1638 **
1639 ** Note that this code relies on that loaded via
1640 ** style_emit_script_fossil_bootstrap(), but it does not call that
1641 ** routine.
1642 */
1643 void style_emit_script_dom(int asInline){
1644 static int once = 0;
1645 if(0==once++){
1646 style_emit_script_builtin(asInline, "fossil.dom.js");
1647 }
1648 }
1649
1650 /*
1651 ** The first time this is called, it calls style_emit_script_dom(),
1652 ** passing it the given asInline value, and emits the JS code from the
1653 ** built-in file fossil.tabs.js. Subsequent calls are no-ops.
1654 **
1655 ** If passed a true value, it emits the contents directly
1656 ** to the page output, else it emits a script tag with a
1657 ** src=builtin/... to load the script.
1658 */
1659 void style_emit_script_tabs(int asInline){
1660 static int once = 0;
1661 if(0==once++){
1662 style_emit_script_dom(asInline);
1663 style_emit_script_builtin(asInline, "fossil.tabs.js");
1664 }
1665 }
1666
1667 /*
1668 ** The first time this is called it emits the JS code from the
1669 ** built-in file fossil.confirmer.js. Subsequent calls are no-ops.
1670 **
1671 ** If passed a true value, it emits the contents directly
1672 ** to the page output, else it emits a script tag with a
1673 ** src=builtin/... to load the script.
1674 */
1675 void style_emit_script_confirmer(int asInline){
1676 static int once = 0;
1677 if(0==once++){
1678 style_emit_script_builtin(asInline, "fossil.confirmer.js");
1679 }
1680 }
1681
--- src/style.c
+++ src/style.c
@@ -88,14 +88,10 @@
88
89 /*
90 ** Flags for various javascript files needed prior to </body>
91 */
92 static int needHrefJs = 0; /* href.js */
 
 
 
 
93
94 /*
95 ** Extra JS added to the end of the file.
96 */
97 static Blob blobOnLoad = BLOB_INITIALIZER;
@@ -484,11 +480,11 @@
480 zBtnFmt/*works-like:"%h%s%h%h%d"*/,
481 zTargetId,zText,zTargetId,zTargetId,cchLength);
482 }
483 }
484 free(zText);
485 builtin_request_js("copybtn.js");
486 return zResult;
487 }
488
489 /*
490 ** Return a random nonce that is stored in static space. For a particular
@@ -694,66 +690,17 @@
690
691 /*
692 ** Indicate that the table-sorting javascript is needed.
693 */
694 void style_table_sorter(void){
695 builtin_request_js("sorttable.js");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
696 }
697
698 /*
699 ** Generate code to load all required javascript files.
700 */
701 static void style_load_all_js_files(void){
 
702 if( needHrefJs ){
703 int nDelay = db_get_int("auto-hyperlink-delay",0);
704 int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0);
705 @ <script id='href-data' type='application/json'>\
706 @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script>
@@ -762,43 +709,20 @@
709 @ function debugMsg(msg){
710 @ var n = document.getElementById("debugMsg");
711 @ if(n){n.textContent=msg;}
712 @ }
713 if( needHrefJs ){
714 @ /* href.js */
715 cgi_append_content(builtin_text("href.js"),-1);
716 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
717 if( blob_size(&blobOnLoad)>0 ){
718 @ window.onload = function(){
719 cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
720 cgi_append_content("\n}\n", -1);
721 }
722 @ </script>
723 builtin_fulfill_js_requests();
 
 
 
 
 
 
 
 
 
724 }
725
726 /*
727 ** Draw the footer at the bottom of the page.
728 */
@@ -916,11 +840,11 @@
840 @ </div>
841 if( nSubmenuCtrl ){
842 cgi_query_parameters_to_hidden();
843 cgi_tag_query_parameter(0);
844 @ </form>
845 builtin_request_js("menu.js");
846 }
847 }
848
849 zAd = style_adunit_text(&mAdFlags);
850 if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){
@@ -1543,17 +1467,12 @@
1467 "name:\"%T\""
1468 "};\n", g.zPath);
1469 CX("})();\n");
1470 /* The remaining fossil object bootstrap code is not dependent on
1471 ** C-runtime state... */
 
 
 
1472 style_emit_script_tag(1,0);
1473 builtin_request_js("fossil.bootstrap.js");
 
 
1474 }
1475 }
1476
1477 /*
1478 ** If passed 0 as its first argument, it emits a script opener tag
@@ -1582,99 +1501,5 @@
1501 }
1502 }else{
1503 CX("</script>\n");
1504 }
1505 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1506
+6 -2
--- src/timeline.c
+++ src/timeline.c
@@ -1083,12 +1083,12 @@
10831083
cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : "");
10841084
cgi_printf("\"h\":\"%!S\"}%s",
10851085
pRow->zUuid, pRow->pNext ? ",\n" : "]\n");
10861086
}
10871087
@ }</script>
1088
- style_graph_generator();
1089
- style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */
1088
+ builtin_request_js("graph.js");
1089
+ builtin_request_js("copybtn.js"); /* Required by graph.js */
10901090
graph_free(pGraph);
10911091
}
10921092
}
10931093
10941094
/*
@@ -1741,10 +1741,14 @@
17411741
}
17421742
}else{
17431743
z = "50";
17441744
nEntry = 50;
17451745
}
1746
+
1747
+ /* Undocumented query parameter to set JS mode */
1748
+ builtin_set_js_delivery_mode(P("jsmode"),1);
1749
+
17461750
secondaryRid = name_to_typed_rid(P("sel2"),"ci");
17471751
selectedRid = name_to_typed_rid(P("sel1"),"ci");
17481752
cgi_replace_query_parameter("n",z);
17491753
cookie_write_parameter("n","n",0);
17501754
tmFlags |= timeline_ss_submenu();
17511755
--- src/timeline.c
+++ src/timeline.c
@@ -1083,12 +1083,12 @@
1083 cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : "");
1084 cgi_printf("\"h\":\"%!S\"}%s",
1085 pRow->zUuid, pRow->pNext ? ",\n" : "]\n");
1086 }
1087 @ }</script>
1088 style_graph_generator();
1089 style_copybutton_control(); /* Dependency: graph.js requires copybtn.js. */
1090 graph_free(pGraph);
1091 }
1092 }
1093
1094 /*
@@ -1741,10 +1741,14 @@
1741 }
1742 }else{
1743 z = "50";
1744 nEntry = 50;
1745 }
 
 
 
 
1746 secondaryRid = name_to_typed_rid(P("sel2"),"ci");
1747 selectedRid = name_to_typed_rid(P("sel1"),"ci");
1748 cgi_replace_query_parameter("n",z);
1749 cookie_write_parameter("n","n",0);
1750 tmFlags |= timeline_ss_submenu();
1751
--- src/timeline.c
+++ src/timeline.c
@@ -1083,12 +1083,12 @@
1083 cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : "");
1084 cgi_printf("\"h\":\"%!S\"}%s",
1085 pRow->zUuid, pRow->pNext ? ",\n" : "]\n");
1086 }
1087 @ }</script>
1088 builtin_request_js("graph.js");
1089 builtin_request_js("copybtn.js"); /* Required by graph.js */
1090 graph_free(pGraph);
1091 }
1092 }
1093
1094 /*
@@ -1741,10 +1741,14 @@
1741 }
1742 }else{
1743 z = "50";
1744 nEntry = 50;
1745 }
1746
1747 /* Undocumented query parameter to set JS mode */
1748 builtin_set_js_delivery_mode(P("jsmode"),1);
1749
1750 secondaryRid = name_to_typed_rid(P("sel2"),"ci");
1751 selectedRid = name_to_typed_rid(P("sel1"),"ci");
1752 cgi_replace_query_parameter("n",z);
1753 cookie_write_parameter("n","n",0);
1754 tmFlags |= timeline_ss_submenu();
1755
+1 -1
--- src/wiki.c
+++ src/wiki.c
@@ -1844,8 +1844,8 @@
18441844
blob_reset(&tail);
18451845
blob_reset(&title);
18461846
blob_reset(&wiki);
18471847
}
18481848
manifest_destroy(pWiki);
1849
- style_accordion();
1849
+ builtin_request_js("accordion.js");
18501850
return 1;
18511851
}
18521852
--- src/wiki.c
+++ src/wiki.c
@@ -1844,8 +1844,8 @@
1844 blob_reset(&tail);
1845 blob_reset(&title);
1846 blob_reset(&wiki);
1847 }
1848 manifest_destroy(pWiki);
1849 style_accordion();
1850 return 1;
1851 }
1852
--- src/wiki.c
+++ src/wiki.c
@@ -1844,8 +1844,8 @@
1844 blob_reset(&tail);
1845 blob_reset(&title);
1846 blob_reset(&wiki);
1847 }
1848 manifest_destroy(pWiki);
1849 builtin_request_js("accordion.js");
1850 return 1;
1851 }
1852

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button