Fossil SCM
Merged in trunk for builtin_request_js() changes and ported wikiedit/fileedit/forumpost to use those.
Commit
2ec332a0c2208e8a657fca5c76f8b927da7131dbb1c3cf6d23fcbd412ab6d592
Parent
99f288d2a59457d…
30 files changed
+1
-1
+1
-1
+236
-10
-1
+2
+16
-11
+16
-21
+16
-21
+11
-8
+11
-8
+3
-3
+2
+1
-1
+31
+4
-1
+4
-1
+13
-4
+1
+57
-1
+1
-1
+1
-1
+39
-302
+39
-302
+6
-2
+8
-20
+8
-20
+4
-1
+4
-1
+5
-2
+5
-2
~
skins/ardoise/css.txt
~
src/browse.c
~
src/builtin.c
~
src/codecheck1.c
~
src/configure.c
~
src/doc.c
~
src/fileedit.c
~
src/fileedit.c
~
src/forum.c
~
src/forum.c
~
src/info.c
~
src/json_config.c
~
src/login.c
~
src/main.c
~
src/main.mk
~
src/main.mk
~
src/makemake.tcl
~
src/mkbuiltin.c
~
src/setup.c
~
src/setupuser.c
~
src/skins.c
~
src/style.c
~
src/style.c
~
src/timeline.c
~
src/wiki.c
~
src/wiki.c
~
win/Makefile.mingw
~
win/Makefile.mingw
~
win/Makefile.msc
~
win/Makefile.msc
+1
-1
| --- skins/ardoise/css.txt | ||
| +++ skins/ardoise/css.txt | ||
| @@ -497,11 +497,11 @@ | ||
| 497 | 497 | border: 0; |
| 498 | 498 | border-radius: 5px; |
| 499 | 499 | box-shadow: none; |
| 500 | 500 | box-sizing: border-box |
| 501 | 501 | } |
| 502 | -textarea { | |
| 502 | +textarea, select { | |
| 503 | 503 | height: initial; |
| 504 | 504 | } |
| 505 | 505 | input[type=email]:hover, |
| 506 | 506 | input[type=number]:hover, |
| 507 | 507 | input[type=password]:hover, |
| 508 | 508 |
| --- skins/ardoise/css.txt | |
| +++ skins/ardoise/css.txt | |
| @@ -497,11 +497,11 @@ | |
| 497 | border: 0; |
| 498 | border-radius: 5px; |
| 499 | box-shadow: none; |
| 500 | box-sizing: border-box |
| 501 | } |
| 502 | textarea { |
| 503 | height: initial; |
| 504 | } |
| 505 | input[type=email]:hover, |
| 506 | input[type=number]:hover, |
| 507 | input[type=password]:hover, |
| 508 |
| --- skins/ardoise/css.txt | |
| +++ skins/ardoise/css.txt | |
| @@ -497,11 +497,11 @@ | |
| 497 | border: 0; |
| 498 | border-radius: 5px; |
| 499 | box-shadow: none; |
| 500 | box-sizing: border-box |
| 501 | } |
| 502 | textarea, select { |
| 503 | height: initial; |
| 504 | } |
| 505 | input[type=email]:hover, |
| 506 | input[type=number]:hover, |
| 507 | input[type=password]:hover, |
| 508 |
+1
-1
| --- src/browse.c | ||
| +++ src/browse.c | ||
| @@ -911,11 +911,11 @@ | ||
| 911 | 911 | } |
| 912 | 912 | } |
| 913 | 913 | } |
| 914 | 914 | @ </ul> |
| 915 | 915 | @ </ul></div> |
| 916 | - style_load_one_js_file("tree.js"); | |
| 916 | + builtin_request_js("tree.js"); | |
| 917 | 917 | style_footer(); |
| 918 | 918 | |
| 919 | 919 | /* We could free memory used by sTree here if we needed to. But |
| 920 | 920 | ** the process is about to exit, so doing so would not really accomplish |
| 921 | 921 | ** anything useful. */ |
| 922 | 922 |
| --- 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 |
+236
-10
| --- src/builtin.c | ||
| +++ src/builtin.c | ||
| @@ -28,13 +28,15 @@ | ||
| 28 | 28 | ** builtin_data.h file. Include that information here: |
| 29 | 29 | */ |
| 30 | 30 | #include "builtin_data.h" |
| 31 | 31 | |
| 32 | 32 | /* |
| 33 | -** Return a pointer to built-in content | |
| 33 | +** Return the index in the aBuiltinFiles[] array for the file | |
| 34 | +** whose name is zFilename. Or return -1 if the file is not | |
| 35 | +** found. | |
| 34 | 36 | */ |
| 35 | -const unsigned char *builtin_file(const char *zFilename, int *piSize){ | |
| 37 | +static int builtin_file_index(const char *zFilename){ | |
| 36 | 38 | int lwr, upr, i, c; |
| 37 | 39 | lwr = 0; |
| 38 | 40 | upr = count(aBuiltinFiles) - 1; |
| 39 | 41 | while( upr>=lwr ){ |
| 40 | 42 | i = (upr+lwr)/2; |
| @@ -42,16 +44,28 @@ | ||
| 42 | 44 | if( c<0 ){ |
| 43 | 45 | lwr = i+1; |
| 44 | 46 | }else if( c>0 ){ |
| 45 | 47 | upr = i-1; |
| 46 | 48 | }else{ |
| 47 | - if( piSize ) *piSize = aBuiltinFiles[i].nByte; | |
| 48 | - return aBuiltinFiles[i].pData; | |
| 49 | + return i; | |
| 49 | 50 | } |
| 50 | 51 | } |
| 51 | - if( piSize ) *piSize = 0; | |
| 52 | - return 0; | |
| 52 | + return -1; | |
| 53 | +} | |
| 54 | + | |
| 55 | +/* | |
| 56 | +** Return a pointer to built-in content | |
| 57 | +*/ | |
| 58 | +const unsigned char *builtin_file(const char *zFilename, int *piSize){ | |
| 59 | + int i = builtin_file_index(zFilename); | |
| 60 | + if( i>=0 ){ | |
| 61 | + if( piSize ) *piSize = aBuiltinFiles[i].nByte; | |
| 62 | + return aBuiltinFiles[i].pData; | |
| 63 | + }else{ | |
| 64 | + if( piSize ) *piSize = 0; | |
| 65 | + return 0; | |
| 66 | + } | |
| 53 | 67 | } |
| 54 | 68 | const char *builtin_text(const char *zFilename){ |
| 55 | 69 | return (char*)builtin_file(zFilename, 0); |
| 56 | 70 | } |
| 57 | 71 | |
| @@ -65,11 +79,11 @@ | ||
| 65 | 79 | */ |
| 66 | 80 | void test_builtin_list(void){ |
| 67 | 81 | int i, size = 0;; |
| 68 | 82 | for(i=0; i<count(aBuiltinFiles); i++){ |
| 69 | 83 | const int n = aBuiltinFiles[i].nByte; |
| 70 | - fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,n); | |
| 84 | + fossil_print("%3d. %-45s %6d\n", i+1, aBuiltinFiles[i].zName,n); | |
| 71 | 85 | size += n; |
| 72 | 86 | } |
| 73 | 87 | if(find_option("verbose","v",0)!=0){ |
| 74 | 88 | fossil_print("%d entries totaling %d bytes\n", i, size); |
| 75 | 89 | } |
| @@ -81,16 +95,18 @@ | ||
| 81 | 95 | ** Show all built-in text files. |
| 82 | 96 | */ |
| 83 | 97 | void test_builtin_list_page(void){ |
| 84 | 98 | int i; |
| 85 | 99 | style_header("Built-in Text Files"); |
| 86 | - @ <ul> | |
| 100 | + @ <ol> | |
| 87 | 101 | for(i=0; i<count(aBuiltinFiles); i++){ |
| 88 | 102 | const char *z = aBuiltinFiles[i].zName; |
| 89 | - @ <li>%z(href("%R/builtin?name=%T&id=%S",z,MANIFEST_UUID))%h(z)</a> | |
| 103 | + char *zUrl = href("%R/builtin?name=%T&id=%.8s&mimetype=text/plain", | |
| 104 | + z,fossil_exe_id()); | |
| 105 | + @ <li>%z(zUrl)%h(z)</a> | |
| 90 | 106 | } |
| 91 | - @ </ul> | |
| 107 | + @ </ol> | |
| 92 | 108 | style_footer(); |
| 93 | 109 | } |
| 94 | 110 | |
| 95 | 111 | /* |
| 96 | 112 | ** COMMAND: test-builtin-get |
| @@ -110,5 +126,215 @@ | ||
| 110 | 126 | } |
| 111 | 127 | blob_init(&x, (const char*)pData, nByte); |
| 112 | 128 | blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-"); |
| 113 | 129 | blob_reset(&x); |
| 114 | 130 | } |
| 131 | + | |
| 132 | +/* | |
| 133 | +** Input zList is a list of numeric identifiers for files in | |
| 134 | +** aBuiltinFiles[]. Return the concatenation of all of those | |
| 135 | +** files using mimetype zType, or as application/javascript if | |
| 136 | +** zType is 0. | |
| 137 | +*/ | |
| 138 | +static void builtin_deliver_multiple_js_files( | |
| 139 | + const char *zList, /* List of numeric identifiers */ | |
| 140 | + const char *zType /* Override mimetype */ | |
| 141 | +){ | |
| 142 | + Blob *pOut; | |
| 143 | + if( zType==0 ) zType = "application/javascript"; | |
| 144 | + cgi_set_content_type(zType); | |
| 145 | + pOut = cgi_output_blob(); | |
| 146 | + while( zList[0] ){ | |
| 147 | + int i = atoi(zList); | |
| 148 | + if( i>0 && i<=count(aBuiltinFiles) ){ | |
| 149 | + blob_append(pOut, (const char*)aBuiltinFiles[i-1].pData, | |
| 150 | + aBuiltinFiles[i-1].nByte); | |
| 151 | + } | |
| 152 | + while( fossil_isdigit(zList[0]) ) zList++; | |
| 153 | + if( zList[0]==',' ) zList++; | |
| 154 | + } | |
| 155 | + return; | |
| 156 | +} | |
| 157 | + | |
| 158 | +/* | |
| 159 | +** WEBPAGE: builtin | |
| 160 | +** | |
| 161 | +** Return one of many built-in content files. Query parameters: | |
| 162 | +** | |
| 163 | +** name=FILENAME Return the single file whose name is FILENAME. | |
| 164 | +** mimetype=TYPE Override the mimetype in the returned file to | |
| 165 | +** be TYPE. If this query parameter is omitted | |
| 166 | +** (the usual case) then the mimetype is inferred | |
| 167 | +** from the suffix on FILENAME | |
| 168 | +** m=IDLIST IDLIST is a comma-separated list of integers | |
| 169 | +** that specify multiple javascript files to be | |
| 170 | +** concatenated and returned all at once. | |
| 171 | +** id=UNIQUEID Version number of the "builtin" files. Used | |
| 172 | +** for cache control only. | |
| 173 | +** | |
| 174 | +** At least one of the name= or m= query parameters must be present. | |
| 175 | +** | |
| 176 | +** If the id= query parameter is present, then Fossil assumes that the | |
| 177 | +** result is immutable and sets a very large cache retention time (1 year). | |
| 178 | +*/ | |
| 179 | +void builtin_webpage(void){ | |
| 180 | + Blob out; | |
| 181 | + const char *zName = P("name"); | |
| 182 | + const char *zTxt = 0; | |
| 183 | + const char *zId = P("id"); | |
| 184 | + const char *zType = P("mimetype"); | |
| 185 | + int nId; | |
| 186 | + if( zName ) zTxt = builtin_text(zName); | |
| 187 | + if( zTxt==0 ){ | |
| 188 | + const char *zM = P("m"); | |
| 189 | + if( zM ){ | |
| 190 | + builtin_deliver_multiple_js_files(zM, zType); | |
| 191 | + return; | |
| 192 | + } | |
| 193 | + cgi_set_status(404, "Not Found"); | |
| 194 | + @ File "%h(zName)" not found | |
| 195 | + return; | |
| 196 | + } | |
| 197 | + if( zType==0 ){ | |
| 198 | + if( sqlite3_strglob("*.js", zName)==0 ){ | |
| 199 | + zType = "application/javascript"; | |
| 200 | + }else{ | |
| 201 | + zType = mimetype_from_name(zName); | |
| 202 | + } | |
| 203 | + } | |
| 204 | + cgi_set_content_type(zType); | |
| 205 | + if( zId | |
| 206 | + && (nId = (int)strlen(zId))>=8 | |
| 207 | + && strncmp(zId,fossil_exe_id(),nId)==0 | |
| 208 | + ){ | |
| 209 | + g.isConst = 1; | |
| 210 | + }else{ | |
| 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 | +} | |
| 115 | 341 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -28,13 +28,15 @@ | |
| 28 | ** builtin_data.h file. Include that information here: |
| 29 | */ |
| 30 | #include "builtin_data.h" |
| 31 | |
| 32 | /* |
| 33 | ** Return a pointer to built-in content |
| 34 | */ |
| 35 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 36 | int lwr, upr, i, c; |
| 37 | lwr = 0; |
| 38 | upr = count(aBuiltinFiles) - 1; |
| 39 | while( upr>=lwr ){ |
| 40 | i = (upr+lwr)/2; |
| @@ -42,16 +44,28 @@ | |
| 42 | if( c<0 ){ |
| 43 | lwr = i+1; |
| 44 | }else if( c>0 ){ |
| 45 | upr = i-1; |
| 46 | }else{ |
| 47 | if( piSize ) *piSize = aBuiltinFiles[i].nByte; |
| 48 | return aBuiltinFiles[i].pData; |
| 49 | } |
| 50 | } |
| 51 | if( piSize ) *piSize = 0; |
| 52 | return 0; |
| 53 | } |
| 54 | const char *builtin_text(const char *zFilename){ |
| 55 | return (char*)builtin_file(zFilename, 0); |
| 56 | } |
| 57 | |
| @@ -65,11 +79,11 @@ | |
| 65 | */ |
| 66 | void test_builtin_list(void){ |
| 67 | int i, size = 0;; |
| 68 | for(i=0; i<count(aBuiltinFiles); i++){ |
| 69 | const int n = aBuiltinFiles[i].nByte; |
| 70 | fossil_print("%-30s %6d\n", aBuiltinFiles[i].zName,n); |
| 71 | size += n; |
| 72 | } |
| 73 | if(find_option("verbose","v",0)!=0){ |
| 74 | fossil_print("%d entries totaling %d bytes\n", i, size); |
| 75 | } |
| @@ -81,16 +95,18 @@ | |
| 81 | ** Show all built-in text files. |
| 82 | */ |
| 83 | void test_builtin_list_page(void){ |
| 84 | int i; |
| 85 | style_header("Built-in Text Files"); |
| 86 | @ <ul> |
| 87 | for(i=0; i<count(aBuiltinFiles); i++){ |
| 88 | const char *z = aBuiltinFiles[i].zName; |
| 89 | @ <li>%z(href("%R/builtin?name=%T&id=%S",z,MANIFEST_UUID))%h(z)</a> |
| 90 | } |
| 91 | @ </ul> |
| 92 | style_footer(); |
| 93 | } |
| 94 | |
| 95 | /* |
| 96 | ** COMMAND: test-builtin-get |
| @@ -110,5 +126,215 @@ | |
| 110 | } |
| 111 | blob_init(&x, (const char*)pData, nByte); |
| 112 | blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-"); |
| 113 | blob_reset(&x); |
| 114 | } |
| 115 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -28,13 +28,15 @@ | |
| 28 | ** builtin_data.h file. Include that information here: |
| 29 | */ |
| 30 | #include "builtin_data.h" |
| 31 | |
| 32 | /* |
| 33 | ** Return the index in the aBuiltinFiles[] array for the file |
| 34 | ** whose name is zFilename. Or return -1 if the file is not |
| 35 | ** found. |
| 36 | */ |
| 37 | static int builtin_file_index(const char *zFilename){ |
| 38 | int lwr, upr, i, c; |
| 39 | lwr = 0; |
| 40 | upr = count(aBuiltinFiles) - 1; |
| 41 | while( upr>=lwr ){ |
| 42 | i = (upr+lwr)/2; |
| @@ -42,16 +44,28 @@ | |
| 44 | if( c<0 ){ |
| 45 | lwr = i+1; |
| 46 | }else if( c>0 ){ |
| 47 | upr = i-1; |
| 48 | }else{ |
| 49 | return i; |
| 50 | } |
| 51 | } |
| 52 | return -1; |
| 53 | } |
| 54 | |
| 55 | /* |
| 56 | ** Return a pointer to built-in content |
| 57 | */ |
| 58 | const unsigned char *builtin_file(const char *zFilename, int *piSize){ |
| 59 | int i = builtin_file_index(zFilename); |
| 60 | if( i>=0 ){ |
| 61 | if( piSize ) *piSize = aBuiltinFiles[i].nByte; |
| 62 | return aBuiltinFiles[i].pData; |
| 63 | }else{ |
| 64 | if( piSize ) *piSize = 0; |
| 65 | return 0; |
| 66 | } |
| 67 | } |
| 68 | const char *builtin_text(const char *zFilename){ |
| 69 | return (char*)builtin_file(zFilename, 0); |
| 70 | } |
| 71 | |
| @@ -65,11 +79,11 @@ | |
| 79 | */ |
| 80 | void test_builtin_list(void){ |
| 81 | int i, size = 0;; |
| 82 | for(i=0; i<count(aBuiltinFiles); i++){ |
| 83 | const int n = aBuiltinFiles[i].nByte; |
| 84 | fossil_print("%3d. %-45s %6d\n", i+1, aBuiltinFiles[i].zName,n); |
| 85 | size += n; |
| 86 | } |
| 87 | if(find_option("verbose","v",0)!=0){ |
| 88 | fossil_print("%d entries totaling %d bytes\n", i, size); |
| 89 | } |
| @@ -81,16 +95,18 @@ | |
| 95 | ** Show all built-in text files. |
| 96 | */ |
| 97 | void test_builtin_list_page(void){ |
| 98 | int i; |
| 99 | style_header("Built-in Text Files"); |
| 100 | @ <ol> |
| 101 | for(i=0; i<count(aBuiltinFiles); i++){ |
| 102 | const char *z = aBuiltinFiles[i].zName; |
| 103 | char *zUrl = href("%R/builtin?name=%T&id=%.8s&mimetype=text/plain", |
| 104 | z,fossil_exe_id()); |
| 105 | @ <li>%z(zUrl)%h(z)</a> |
| 106 | } |
| 107 | @ </ol> |
| 108 | style_footer(); |
| 109 | } |
| 110 | |
| 111 | /* |
| 112 | ** COMMAND: test-builtin-get |
| @@ -110,5 +126,215 @@ | |
| 126 | } |
| 127 | blob_init(&x, (const char*)pData, nByte); |
| 128 | blob_write_to_file(&x, g.argc==4 ? g.argv[3] : "-"); |
| 129 | blob_reset(&x); |
| 130 | } |
| 131 | |
| 132 | /* |
| 133 | ** Input zList is a list of numeric identifiers for files in |
| 134 | ** aBuiltinFiles[]. Return the concatenation of all of those |
| 135 | ** files using mimetype zType, or as application/javascript if |
| 136 | ** zType is 0. |
| 137 | */ |
| 138 | static void builtin_deliver_multiple_js_files( |
| 139 | const char *zList, /* List of numeric identifiers */ |
| 140 | const char *zType /* Override mimetype */ |
| 141 | ){ |
| 142 | Blob *pOut; |
| 143 | if( zType==0 ) zType = "application/javascript"; |
| 144 | cgi_set_content_type(zType); |
| 145 | pOut = cgi_output_blob(); |
| 146 | while( zList[0] ){ |
| 147 | int i = atoi(zList); |
| 148 | if( i>0 && i<=count(aBuiltinFiles) ){ |
| 149 | blob_append(pOut, (const char*)aBuiltinFiles[i-1].pData, |
| 150 | aBuiltinFiles[i-1].nByte); |
| 151 | } |
| 152 | while( fossil_isdigit(zList[0]) ) zList++; |
| 153 | if( zList[0]==',' ) zList++; |
| 154 | } |
| 155 | return; |
| 156 | } |
| 157 | |
| 158 | /* |
| 159 | ** WEBPAGE: builtin |
| 160 | ** |
| 161 | ** Return one of many built-in content files. Query parameters: |
| 162 | ** |
| 163 | ** name=FILENAME Return the single file whose name is FILENAME. |
| 164 | ** mimetype=TYPE Override the mimetype in the returned file to |
| 165 | ** be TYPE. If this query parameter is omitted |
| 166 | ** (the usual case) then the mimetype is inferred |
| 167 | ** from the suffix on FILENAME |
| 168 | ** m=IDLIST IDLIST is a comma-separated list of integers |
| 169 | ** that specify multiple javascript files to be |
| 170 | ** concatenated and returned all at once. |
| 171 | ** id=UNIQUEID Version number of the "builtin" files. Used |
| 172 | ** for cache control only. |
| 173 | ** |
| 174 | ** At least one of the name= or m= query parameters must be present. |
| 175 | ** |
| 176 | ** If the id= query parameter is present, then Fossil assumes that the |
| 177 | ** result is immutable and sets a very large cache retention time (1 year). |
| 178 | */ |
| 179 | void builtin_webpage(void){ |
| 180 | Blob out; |
| 181 | const char *zName = P("name"); |
| 182 | const char *zTxt = 0; |
| 183 | const char *zId = P("id"); |
| 184 | const char *zType = P("mimetype"); |
| 185 | int nId; |
| 186 | if( zName ) zTxt = builtin_text(zName); |
| 187 | if( zTxt==0 ){ |
| 188 | const char *zM = P("m"); |
| 189 | if( zM ){ |
| 190 | builtin_deliver_multiple_js_files(zM, zType); |
| 191 | return; |
| 192 | } |
| 193 | cgi_set_status(404, "Not Found"); |
| 194 | @ File "%h(zName)" not found |
| 195 | return; |
| 196 | } |
| 197 | if( zType==0 ){ |
| 198 | if( sqlite3_strglob("*.js", zName)==0 ){ |
| 199 | zType = "application/javascript"; |
| 200 | }else{ |
| 201 | zType = mimetype_from_name(zName); |
| 202 | } |
| 203 | } |
| 204 | cgi_set_content_type(zType); |
| 205 | if( zId |
| 206 | && (nId = (int)strlen(zId))>=8 |
| 207 | && strncmp(zId,fossil_exe_id(),nId)==0 |
| 208 | ){ |
| 209 | g.isConst = 1; |
| 210 | }else{ |
| 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 |
-1
| --- src/codecheck1.c | ||
| +++ src/codecheck1.c | ||
| @@ -407,11 +407,10 @@ | ||
| 407 | 407 | { "smtp_send_line", 2, FMT_SAFE }, |
| 408 | 408 | { "smtp_server_send", 2, FMT_SAFE }, |
| 409 | 409 | { "socket_set_errmsg", 1, FMT_SAFE }, |
| 410 | 410 | { "ssl_set_errmsg", 1, FMT_SAFE }, |
| 411 | 411 | { "style_header", 1, FMT_HTML }, |
| 412 | - { "style_js_onload", 1, FMT_HTML }, | |
| 413 | 412 | { "style_set_current_page", 1, FMT_URL }, |
| 414 | 413 | { "style_submenu_element", 2, FMT_URL }, |
| 415 | 414 | { "style_submenu_sql", 3, FMT_SQL }, |
| 416 | 415 | { "webpage_error", 1, FMT_SAFE }, |
| 417 | 416 | { "xhref", 2, FMT_URL }, |
| 418 | 417 |
| --- 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 |
+2
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -94,10 +94,12 @@ | ||
| 94 | 94 | { "js", CONFIGSET_SKIN }, |
| 95 | 95 | { "logo-mimetype", CONFIGSET_SKIN }, |
| 96 | 96 | { "logo-image", CONFIGSET_SKIN }, |
| 97 | 97 | { "background-mimetype", CONFIGSET_SKIN }, |
| 98 | 98 | { "background-image", CONFIGSET_SKIN }, |
| 99 | + { "icon-mimetype", CONFIGSET_SKIN }, | |
| 100 | + { "icon-image", CONFIGSET_SKIN }, | |
| 99 | 101 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 100 | 102 | { "timeline-date-format", CONFIGSET_SKIN }, |
| 101 | 103 | { "timeline-default-style", CONFIGSET_SKIN }, |
| 102 | 104 | { "timeline-dwelltime", CONFIGSET_SKIN }, |
| 103 | 105 | { "timeline-closetime", CONFIGSET_SKIN }, |
| 104 | 106 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -94,10 +94,12 @@ | |
| 94 | { "js", CONFIGSET_SKIN }, |
| 95 | { "logo-mimetype", CONFIGSET_SKIN }, |
| 96 | { "logo-image", CONFIGSET_SKIN }, |
| 97 | { "background-mimetype", CONFIGSET_SKIN }, |
| 98 | { "background-image", CONFIGSET_SKIN }, |
| 99 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 100 | { "timeline-date-format", CONFIGSET_SKIN }, |
| 101 | { "timeline-default-style", CONFIGSET_SKIN }, |
| 102 | { "timeline-dwelltime", CONFIGSET_SKIN }, |
| 103 | { "timeline-closetime", CONFIGSET_SKIN }, |
| 104 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -94,10 +94,12 @@ | |
| 94 | { "js", CONFIGSET_SKIN }, |
| 95 | { "logo-mimetype", CONFIGSET_SKIN }, |
| 96 | { "logo-image", CONFIGSET_SKIN }, |
| 97 | { "background-mimetype", CONFIGSET_SKIN }, |
| 98 | { "background-image", CONFIGSET_SKIN }, |
| 99 | { "icon-mimetype", CONFIGSET_SKIN }, |
| 100 | { "icon-image", CONFIGSET_SKIN }, |
| 101 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 102 | { "timeline-date-format", CONFIGSET_SKIN }, |
| 103 | { "timeline-default-style", CONFIGSET_SKIN }, |
| 104 | { "timeline-dwelltime", CONFIGSET_SKIN }, |
| 105 | { "timeline-closetime", CONFIGSET_SKIN }, |
| 106 |
+16
-11
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -147,11 +147,11 @@ | ||
| 147 | 147 | { "jad", 3, "text/vnd.sun.j2me.app-descriptor" }, |
| 148 | 148 | { "jar", 3, "application/java-archive" }, |
| 149 | 149 | { "jpe", 3, "image/jpeg" }, |
| 150 | 150 | { "jpeg", 4, "image/jpeg" }, |
| 151 | 151 | { "jpg", 3, "image/jpeg" }, |
| 152 | - { "js", 2, "application/x-javascript" }, | |
| 152 | + { "js", 2, "application/javascript" }, | |
| 153 | 153 | { "kar", 3, "audio/midi" }, |
| 154 | 154 | { "latex", 5, "application/x-latex" }, |
| 155 | 155 | { "lha", 3, "application/octet-stream" }, |
| 156 | 156 | { "lsp", 3, "application/x-lisp" }, |
| 157 | 157 | { "lzh", 3, "application/octet-stream" }, |
| @@ -1132,29 +1132,34 @@ | ||
| 1132 | 1132 | |
| 1133 | 1133 | |
| 1134 | 1134 | /* |
| 1135 | 1135 | ** WEBPAGE: favicon.ico |
| 1136 | 1136 | ** |
| 1137 | -** Return the default favicon.ico image. The returned image is for the | |
| 1138 | -** Fossil lizard icon. | |
| 1137 | +** Return the configured "favicon.ico" image. If no "favicon.ico" image | |
| 1138 | +** is defined, the returned image is for the Fossil lizard icon. | |
| 1139 | 1139 | ** |
| 1140 | -** The intended use case here is to supply a favicon for the "fossil ui" | |
| 1140 | +** The intended use case here is to supply an icon for the "fossil ui" | |
| 1141 | 1141 | ** command. For a permanent website, the recommended process is for |
| 1142 | -** the admin to set up a project-specific favicon and reference that | |
| 1143 | -** icon in the HTML header using a line like: | |
| 1142 | +** the admin to set up a project-specific icon and reference that icon | |
| 1143 | +** in the HTML header using a line like: | |
| 1144 | 1144 | ** |
| 1145 | 1145 | ** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/> |
| 1146 | 1146 | ** |
| 1147 | 1147 | */ |
| 1148 | 1148 | void favicon_page(void){ |
| 1149 | - Blob favicon; | |
| 1149 | + Blob icon; | |
| 1150 | + char *zMime; | |
| 1150 | 1151 | |
| 1151 | 1152 | etag_check(ETAG_CONFIG, 0); |
| 1152 | - blob_zero(&favicon); | |
| 1153 | - blob_init(&favicon, (char*)aLogo, sizeof(aLogo)); | |
| 1154 | - cgi_set_content_type("image/gif"); | |
| 1155 | - cgi_set_content(&favicon); | |
| 1153 | + zMime = db_get("icon-mimetype", "image/gif"); | |
| 1154 | + blob_zero(&icon); | |
| 1155 | + db_blob(&icon, "SELECT value FROM config WHERE name='icon-image'"); | |
| 1156 | + if( blob_size(&icon)==0 ){ | |
| 1157 | + blob_init(&icon, (char*)aLogo, sizeof(aLogo)); | |
| 1158 | + } | |
| 1159 | + cgi_set_content_type(zMime); | |
| 1160 | + cgi_set_content(&icon); | |
| 1156 | 1161 | } |
| 1157 | 1162 | |
| 1158 | 1163 | /* |
| 1159 | 1164 | ** WEBPAGE: docsrch |
| 1160 | 1165 | ** |
| 1161 | 1166 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -147,11 +147,11 @@ | |
| 147 | { "jad", 3, "text/vnd.sun.j2me.app-descriptor" }, |
| 148 | { "jar", 3, "application/java-archive" }, |
| 149 | { "jpe", 3, "image/jpeg" }, |
| 150 | { "jpeg", 4, "image/jpeg" }, |
| 151 | { "jpg", 3, "image/jpeg" }, |
| 152 | { "js", 2, "application/x-javascript" }, |
| 153 | { "kar", 3, "audio/midi" }, |
| 154 | { "latex", 5, "application/x-latex" }, |
| 155 | { "lha", 3, "application/octet-stream" }, |
| 156 | { "lsp", 3, "application/x-lisp" }, |
| 157 | { "lzh", 3, "application/octet-stream" }, |
| @@ -1132,29 +1132,34 @@ | |
| 1132 | |
| 1133 | |
| 1134 | /* |
| 1135 | ** WEBPAGE: favicon.ico |
| 1136 | ** |
| 1137 | ** Return the default favicon.ico image. The returned image is for the |
| 1138 | ** Fossil lizard icon. |
| 1139 | ** |
| 1140 | ** The intended use case here is to supply a favicon for the "fossil ui" |
| 1141 | ** command. For a permanent website, the recommended process is for |
| 1142 | ** the admin to set up a project-specific favicon and reference that |
| 1143 | ** icon in the HTML header using a line like: |
| 1144 | ** |
| 1145 | ** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/> |
| 1146 | ** |
| 1147 | */ |
| 1148 | void favicon_page(void){ |
| 1149 | Blob favicon; |
| 1150 | |
| 1151 | etag_check(ETAG_CONFIG, 0); |
| 1152 | blob_zero(&favicon); |
| 1153 | blob_init(&favicon, (char*)aLogo, sizeof(aLogo)); |
| 1154 | cgi_set_content_type("image/gif"); |
| 1155 | cgi_set_content(&favicon); |
| 1156 | } |
| 1157 | |
| 1158 | /* |
| 1159 | ** WEBPAGE: docsrch |
| 1160 | ** |
| 1161 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -147,11 +147,11 @@ | |
| 147 | { "jad", 3, "text/vnd.sun.j2me.app-descriptor" }, |
| 148 | { "jar", 3, "application/java-archive" }, |
| 149 | { "jpe", 3, "image/jpeg" }, |
| 150 | { "jpeg", 4, "image/jpeg" }, |
| 151 | { "jpg", 3, "image/jpeg" }, |
| 152 | { "js", 2, "application/javascript" }, |
| 153 | { "kar", 3, "audio/midi" }, |
| 154 | { "latex", 5, "application/x-latex" }, |
| 155 | { "lha", 3, "application/octet-stream" }, |
| 156 | { "lsp", 3, "application/x-lisp" }, |
| 157 | { "lzh", 3, "application/octet-stream" }, |
| @@ -1132,29 +1132,34 @@ | |
| 1132 | |
| 1133 | |
| 1134 | /* |
| 1135 | ** WEBPAGE: favicon.ico |
| 1136 | ** |
| 1137 | ** Return the configured "favicon.ico" image. If no "favicon.ico" image |
| 1138 | ** is defined, the returned image is for the Fossil lizard icon. |
| 1139 | ** |
| 1140 | ** The intended use case here is to supply an icon for the "fossil ui" |
| 1141 | ** command. For a permanent website, the recommended process is for |
| 1142 | ** the admin to set up a project-specific icon and reference that icon |
| 1143 | ** in the HTML header using a line like: |
| 1144 | ** |
| 1145 | ** <link rel="icon" href="URL-FOR-YOUR-ICON" type="MIMETYPE"/> |
| 1146 | ** |
| 1147 | */ |
| 1148 | void favicon_page(void){ |
| 1149 | Blob icon; |
| 1150 | char *zMime; |
| 1151 | |
| 1152 | etag_check(ETAG_CONFIG, 0); |
| 1153 | zMime = db_get("icon-mimetype", "image/gif"); |
| 1154 | blob_zero(&icon); |
| 1155 | db_blob(&icon, "SELECT value FROM config WHERE name='icon-image'"); |
| 1156 | if( blob_size(&icon)==0 ){ |
| 1157 | blob_init(&icon, (char*)aLogo, sizeof(aLogo)); |
| 1158 | } |
| 1159 | cgi_set_content_type(zMime); |
| 1160 | cgi_set_content(&icon); |
| 1161 | } |
| 1162 | |
| 1163 | /* |
| 1164 | ** WEBPAGE: docsrch |
| 1165 | ** |
| 1166 |
+16
-21
| --- src/fileedit.c | ||
| +++ src/fileedit.c | ||
| @@ -1481,30 +1481,10 @@ | ||
| 1481 | 1481 | blob_reset(&err); |
| 1482 | 1482 | blob_reset(&manifest); |
| 1483 | 1483 | CheckinMiniInfo_cleanup(&cimi); |
| 1484 | 1484 | } |
| 1485 | 1485 | |
| 1486 | -/* | |
| 1487 | -** Emits all of the "core" static JS needed by /fileedit. Intended to | |
| 1488 | -** be mapped to style.c:BundleEmitters with the name "fileedit.js". | |
| 1489 | -*/ | |
| 1490 | -void fileedit_emit_js_bundle(void){ | |
| 1491 | - style_emit_script_fossil_bootstrap(1); | |
| 1492 | - style_emit_script_builtin(1,0,"sbsdiff.js"); | |
| 1493 | - style_emit_script_fetch(1,0); | |
| 1494 | - style_emit_script_tabs(1,0)/*also emits fossil.dom*/; | |
| 1495 | - style_emit_script_confirmer(1,0); | |
| 1496 | - style_emit_script_builtin(1, 0, "fossil.storage.js"); | |
| 1497 | - /* | |
| 1498 | - ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is | |
| 1499 | - ** used for dynamically toggling certain UI components on and off. | |
| 1500 | - ** Must come before fossil.page.fileedit.js. | |
| 1501 | - */ | |
| 1502 | - ajax_emit_js_preview_modes(0); | |
| 1503 | - style_emit_script_builtin(1, 0, "fossil.page.fileedit.js"); | |
| 1504 | -} | |
| 1505 | - | |
| 1506 | 1486 | /* |
| 1507 | 1487 | ** WEBPAGE: fileedit |
| 1508 | 1488 | ** |
| 1509 | 1489 | ** Enables the online editing and committing of individual text files. |
| 1510 | 1490 | ** Requires that the user have Write permissions. |
| @@ -1978,11 +1958,26 @@ | ||
| 1978 | 1958 | blob_appendf(&endScript,");\n"); |
| 1979 | 1959 | } |
| 1980 | 1960 | |
| 1981 | 1961 | blob_reset(&err); |
| 1982 | 1962 | CheckinMiniInfo_cleanup(&cimi); |
| 1983 | - style_emit_script_bundle("fileedit.js"); | |
| 1963 | + | |
| 1964 | + builtin_request_js("sbsdiff.js"); | |
| 1965 | + style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", | |
| 1966 | + "storage", 0); | |
| 1967 | + builtin_fulfill_js_requests(); | |
| 1968 | + /* | |
| 1969 | + ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is | |
| 1970 | + ** used for dynamically toggling certain UI components on and off. | |
| 1971 | + ** Must come after window.fossil has been intialized and before | |
| 1972 | + ** fossil.page.fileedit.js. Potential TODO: move this into the | |
| 1973 | + ** window.fossil bootstrapping so that we don't have to "fulfill" | |
| 1974 | + ** the JS multiple times. | |
| 1975 | + */ | |
| 1976 | + ajax_emit_js_preview_modes(1); | |
| 1977 | + builtin_request_js("fossil.page.fileedit.js"); | |
| 1978 | + builtin_fulfill_js_requests(); | |
| 1984 | 1979 | if(blob_size(&endScript)>0){ |
| 1985 | 1980 | style_emit_script_tag(0,0); |
| 1986 | 1981 | CX("\n(function(){\n"); |
| 1987 | 1982 | CX("try{\n%b}\n" |
| 1988 | 1983 | "catch(e){" |
| 1989 | 1984 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1481,30 +1481,10 @@ | |
| 1481 | blob_reset(&err); |
| 1482 | blob_reset(&manifest); |
| 1483 | CheckinMiniInfo_cleanup(&cimi); |
| 1484 | } |
| 1485 | |
| 1486 | /* |
| 1487 | ** Emits all of the "core" static JS needed by /fileedit. Intended to |
| 1488 | ** be mapped to style.c:BundleEmitters with the name "fileedit.js". |
| 1489 | */ |
| 1490 | void fileedit_emit_js_bundle(void){ |
| 1491 | style_emit_script_fossil_bootstrap(1); |
| 1492 | style_emit_script_builtin(1,0,"sbsdiff.js"); |
| 1493 | style_emit_script_fetch(1,0); |
| 1494 | style_emit_script_tabs(1,0)/*also emits fossil.dom*/; |
| 1495 | style_emit_script_confirmer(1,0); |
| 1496 | style_emit_script_builtin(1, 0, "fossil.storage.js"); |
| 1497 | /* |
| 1498 | ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is |
| 1499 | ** used for dynamically toggling certain UI components on and off. |
| 1500 | ** Must come before fossil.page.fileedit.js. |
| 1501 | */ |
| 1502 | ajax_emit_js_preview_modes(0); |
| 1503 | style_emit_script_builtin(1, 0, "fossil.page.fileedit.js"); |
| 1504 | } |
| 1505 | |
| 1506 | /* |
| 1507 | ** WEBPAGE: fileedit |
| 1508 | ** |
| 1509 | ** Enables the online editing and committing of individual text files. |
| 1510 | ** Requires that the user have Write permissions. |
| @@ -1978,11 +1958,26 @@ | |
| 1978 | blob_appendf(&endScript,");\n"); |
| 1979 | } |
| 1980 | |
| 1981 | blob_reset(&err); |
| 1982 | CheckinMiniInfo_cleanup(&cimi); |
| 1983 | style_emit_script_bundle("fileedit.js"); |
| 1984 | if(blob_size(&endScript)>0){ |
| 1985 | style_emit_script_tag(0,0); |
| 1986 | CX("\n(function(){\n"); |
| 1987 | CX("try{\n%b}\n" |
| 1988 | "catch(e){" |
| 1989 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1481,30 +1481,10 @@ | |
| 1481 | blob_reset(&err); |
| 1482 | blob_reset(&manifest); |
| 1483 | CheckinMiniInfo_cleanup(&cimi); |
| 1484 | } |
| 1485 | |
| 1486 | /* |
| 1487 | ** WEBPAGE: fileedit |
| 1488 | ** |
| 1489 | ** Enables the online editing and committing of individual text files. |
| 1490 | ** Requires that the user have Write permissions. |
| @@ -1978,11 +1958,26 @@ | |
| 1958 | blob_appendf(&endScript,");\n"); |
| 1959 | } |
| 1960 | |
| 1961 | blob_reset(&err); |
| 1962 | CheckinMiniInfo_cleanup(&cimi); |
| 1963 | |
| 1964 | builtin_request_js("sbsdiff.js"); |
| 1965 | style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", |
| 1966 | "storage", 0); |
| 1967 | builtin_fulfill_js_requests(); |
| 1968 | /* |
| 1969 | ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is |
| 1970 | ** used for dynamically toggling certain UI components on and off. |
| 1971 | ** Must come after window.fossil has been intialized and before |
| 1972 | ** fossil.page.fileedit.js. Potential TODO: move this into the |
| 1973 | ** window.fossil bootstrapping so that we don't have to "fulfill" |
| 1974 | ** the JS multiple times. |
| 1975 | */ |
| 1976 | ajax_emit_js_preview_modes(1); |
| 1977 | builtin_request_js("fossil.page.fileedit.js"); |
| 1978 | builtin_fulfill_js_requests(); |
| 1979 | if(blob_size(&endScript)>0){ |
| 1980 | style_emit_script_tag(0,0); |
| 1981 | CX("\n(function(){\n"); |
| 1982 | CX("try{\n%b}\n" |
| 1983 | "catch(e){" |
| 1984 |
+16
-21
| --- src/fileedit.c | ||
| +++ src/fileedit.c | ||
| @@ -1481,30 +1481,10 @@ | ||
| 1481 | 1481 | blob_reset(&err); |
| 1482 | 1482 | blob_reset(&manifest); |
| 1483 | 1483 | CheckinMiniInfo_cleanup(&cimi); |
| 1484 | 1484 | } |
| 1485 | 1485 | |
| 1486 | -/* | |
| 1487 | -** Emits all of the "core" static JS needed by /fileedit. Intended to | |
| 1488 | -** be mapped to style.c:BundleEmitters with the name "fileedit.js". | |
| 1489 | -*/ | |
| 1490 | -void fileedit_emit_js_bundle(void){ | |
| 1491 | - style_emit_script_fossil_bootstrap(1); | |
| 1492 | - style_emit_script_builtin(1,0,"sbsdiff.js"); | |
| 1493 | - style_emit_script_fetch(1,0); | |
| 1494 | - style_emit_script_tabs(1,0)/*also emits fossil.dom*/; | |
| 1495 | - style_emit_script_confirmer(1,0); | |
| 1496 | - style_emit_script_builtin(1, 0, "fossil.storage.js"); | |
| 1497 | - /* | |
| 1498 | - ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is | |
| 1499 | - ** used for dynamically toggling certain UI components on and off. | |
| 1500 | - ** Must come before fossil.page.fileedit.js. | |
| 1501 | - */ | |
| 1502 | - ajax_emit_js_preview_modes(0); | |
| 1503 | - style_emit_script_builtin(1, 0, "fossil.page.fileedit.js"); | |
| 1504 | -} | |
| 1505 | - | |
| 1506 | 1486 | /* |
| 1507 | 1487 | ** WEBPAGE: fileedit |
| 1508 | 1488 | ** |
| 1509 | 1489 | ** Enables the online editing and committing of individual text files. |
| 1510 | 1490 | ** Requires that the user have Write permissions. |
| @@ -1978,11 +1958,26 @@ | ||
| 1978 | 1958 | blob_appendf(&endScript,");\n"); |
| 1979 | 1959 | } |
| 1980 | 1960 | |
| 1981 | 1961 | blob_reset(&err); |
| 1982 | 1962 | CheckinMiniInfo_cleanup(&cimi); |
| 1983 | - style_emit_script_bundle("fileedit.js"); | |
| 1963 | + | |
| 1964 | + builtin_request_js("sbsdiff.js"); | |
| 1965 | + style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", | |
| 1966 | + "storage", 0); | |
| 1967 | + builtin_fulfill_js_requests(); | |
| 1968 | + /* | |
| 1969 | + ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is | |
| 1970 | + ** used for dynamically toggling certain UI components on and off. | |
| 1971 | + ** Must come after window.fossil has been intialized and before | |
| 1972 | + ** fossil.page.fileedit.js. Potential TODO: move this into the | |
| 1973 | + ** window.fossil bootstrapping so that we don't have to "fulfill" | |
| 1974 | + ** the JS multiple times. | |
| 1975 | + */ | |
| 1976 | + ajax_emit_js_preview_modes(1); | |
| 1977 | + builtin_request_js("fossil.page.fileedit.js"); | |
| 1978 | + builtin_fulfill_js_requests(); | |
| 1984 | 1979 | if(blob_size(&endScript)>0){ |
| 1985 | 1980 | style_emit_script_tag(0,0); |
| 1986 | 1981 | CX("\n(function(){\n"); |
| 1987 | 1982 | CX("try{\n%b}\n" |
| 1988 | 1983 | "catch(e){" |
| 1989 | 1984 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1481,30 +1481,10 @@ | |
| 1481 | blob_reset(&err); |
| 1482 | blob_reset(&manifest); |
| 1483 | CheckinMiniInfo_cleanup(&cimi); |
| 1484 | } |
| 1485 | |
| 1486 | /* |
| 1487 | ** Emits all of the "core" static JS needed by /fileedit. Intended to |
| 1488 | ** be mapped to style.c:BundleEmitters with the name "fileedit.js". |
| 1489 | */ |
| 1490 | void fileedit_emit_js_bundle(void){ |
| 1491 | style_emit_script_fossil_bootstrap(1); |
| 1492 | style_emit_script_builtin(1,0,"sbsdiff.js"); |
| 1493 | style_emit_script_fetch(1,0); |
| 1494 | style_emit_script_tabs(1,0)/*also emits fossil.dom*/; |
| 1495 | style_emit_script_confirmer(1,0); |
| 1496 | style_emit_script_builtin(1, 0, "fossil.storage.js"); |
| 1497 | /* |
| 1498 | ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is |
| 1499 | ** used for dynamically toggling certain UI components on and off. |
| 1500 | ** Must come before fossil.page.fileedit.js. |
| 1501 | */ |
| 1502 | ajax_emit_js_preview_modes(0); |
| 1503 | style_emit_script_builtin(1, 0, "fossil.page.fileedit.js"); |
| 1504 | } |
| 1505 | |
| 1506 | /* |
| 1507 | ** WEBPAGE: fileedit |
| 1508 | ** |
| 1509 | ** Enables the online editing and committing of individual text files. |
| 1510 | ** Requires that the user have Write permissions. |
| @@ -1978,11 +1958,26 @@ | |
| 1978 | blob_appendf(&endScript,");\n"); |
| 1979 | } |
| 1980 | |
| 1981 | blob_reset(&err); |
| 1982 | CheckinMiniInfo_cleanup(&cimi); |
| 1983 | style_emit_script_bundle("fileedit.js"); |
| 1984 | if(blob_size(&endScript)>0){ |
| 1985 | style_emit_script_tag(0,0); |
| 1986 | CX("\n(function(){\n"); |
| 1987 | CX("try{\n%b}\n" |
| 1988 | "catch(e){" |
| 1989 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1481,30 +1481,10 @@ | |
| 1481 | blob_reset(&err); |
| 1482 | blob_reset(&manifest); |
| 1483 | CheckinMiniInfo_cleanup(&cimi); |
| 1484 | } |
| 1485 | |
| 1486 | /* |
| 1487 | ** WEBPAGE: fileedit |
| 1488 | ** |
| 1489 | ** Enables the online editing and committing of individual text files. |
| 1490 | ** Requires that the user have Write permissions. |
| @@ -1978,11 +1958,26 @@ | |
| 1958 | blob_appendf(&endScript,");\n"); |
| 1959 | } |
| 1960 | |
| 1961 | blob_reset(&err); |
| 1962 | CheckinMiniInfo_cleanup(&cimi); |
| 1963 | |
| 1964 | builtin_request_js("sbsdiff.js"); |
| 1965 | style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", |
| 1966 | "storage", 0); |
| 1967 | builtin_fulfill_js_requests(); |
| 1968 | /* |
| 1969 | ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is |
| 1970 | ** used for dynamically toggling certain UI components on and off. |
| 1971 | ** Must come after window.fossil has been intialized and before |
| 1972 | ** fossil.page.fileedit.js. Potential TODO: move this into the |
| 1973 | ** window.fossil bootstrapping so that we don't have to "fulfill" |
| 1974 | ** the JS multiple times. |
| 1975 | */ |
| 1976 | ajax_emit_js_preview_modes(1); |
| 1977 | builtin_request_js("fossil.page.fileedit.js"); |
| 1978 | builtin_fulfill_js_requests(); |
| 1979 | if(blob_size(&endScript)>0){ |
| 1980 | style_emit_script_tag(0,0); |
| 1981 | CX("\n(function(){\n"); |
| 1982 | CX("try{\n%b}\n" |
| 1983 | "catch(e){" |
| 1984 |
+11
-8
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -749,18 +749,21 @@ | ||
| 749 | 749 | forumthread_delete(pThread); |
| 750 | 750 | return target; |
| 751 | 751 | } |
| 752 | 752 | |
| 753 | 753 | /* |
| 754 | -** Callback for use with style.c:BundleEmitters. Emits all JS code | |
| 755 | -** required by this page. | |
| 754 | +** Emits all JS code required by /forumpost. | |
| 756 | 755 | */ |
| 757 | -void forumpost_emit_js_bundle(void){ | |
| 758 | - style_emit_script_builtin(1, 0, "forum.js"); | |
| 759 | - style_emit_script_fossil_bootstrap(1); | |
| 760 | - style_emit_script_dom(1, 0); | |
| 761 | - style_emit_script_builtin(1, 0, "fossil.page.forumpost.js"); | |
| 756 | +static void forumpost_emit_page_js(){ | |
| 757 | + static int once = 0; | |
| 758 | + if(0==once){ | |
| 759 | + once = 1; | |
| 760 | + style_emit_script_fossil_bootstrap(1); | |
| 761 | + builtin_request_js("forum.js"); | |
| 762 | + builtin_request_js("fossil.dom.js"); | |
| 763 | + builtin_request_js("fossil.page.forumpost.js"); | |
| 764 | + } | |
| 762 | 765 | } |
| 763 | 766 | |
| 764 | 767 | /* |
| 765 | 768 | ** WEBPAGE: forumpost |
| 766 | 769 | ** |
| @@ -887,11 +890,11 @@ | ||
| 887 | 890 | }else{ |
| 888 | 891 | style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); |
| 889 | 892 | style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName); |
| 890 | 893 | forum_display_hierarchical(froot, fpid); |
| 891 | 894 | } |
| 892 | - style_emit_script_bundle("forum.js"); | |
| 895 | + forumpost_emit_page_js(); | |
| 893 | 896 | style_footer(); |
| 894 | 897 | } |
| 895 | 898 | |
| 896 | 899 | /* |
| 897 | 900 | ** Return true if a forum post should be moderated. |
| 898 | 901 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -749,18 +749,21 @@ | |
| 749 | forumthread_delete(pThread); |
| 750 | return target; |
| 751 | } |
| 752 | |
| 753 | /* |
| 754 | ** Callback for use with style.c:BundleEmitters. Emits all JS code |
| 755 | ** required by this page. |
| 756 | */ |
| 757 | void forumpost_emit_js_bundle(void){ |
| 758 | style_emit_script_builtin(1, 0, "forum.js"); |
| 759 | style_emit_script_fossil_bootstrap(1); |
| 760 | style_emit_script_dom(1, 0); |
| 761 | style_emit_script_builtin(1, 0, "fossil.page.forumpost.js"); |
| 762 | } |
| 763 | |
| 764 | /* |
| 765 | ** WEBPAGE: forumpost |
| 766 | ** |
| @@ -887,11 +890,11 @@ | |
| 887 | }else{ |
| 888 | style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); |
| 889 | style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName); |
| 890 | forum_display_hierarchical(froot, fpid); |
| 891 | } |
| 892 | style_emit_script_bundle("forum.js"); |
| 893 | style_footer(); |
| 894 | } |
| 895 | |
| 896 | /* |
| 897 | ** Return true if a forum post should be moderated. |
| 898 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -749,18 +749,21 @@ | |
| 749 | forumthread_delete(pThread); |
| 750 | return target; |
| 751 | } |
| 752 | |
| 753 | /* |
| 754 | ** Emits all JS code required by /forumpost. |
| 755 | */ |
| 756 | static void forumpost_emit_page_js(){ |
| 757 | static int once = 0; |
| 758 | if(0==once){ |
| 759 | once = 1; |
| 760 | style_emit_script_fossil_bootstrap(1); |
| 761 | builtin_request_js("forum.js"); |
| 762 | builtin_request_js("fossil.dom.js"); |
| 763 | builtin_request_js("fossil.page.forumpost.js"); |
| 764 | } |
| 765 | } |
| 766 | |
| 767 | /* |
| 768 | ** WEBPAGE: forumpost |
| 769 | ** |
| @@ -887,11 +890,11 @@ | |
| 890 | }else{ |
| 891 | style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); |
| 892 | style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName); |
| 893 | forum_display_hierarchical(froot, fpid); |
| 894 | } |
| 895 | forumpost_emit_page_js(); |
| 896 | style_footer(); |
| 897 | } |
| 898 | |
| 899 | /* |
| 900 | ** Return true if a forum post should be moderated. |
| 901 |
+11
-8
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -749,18 +749,21 @@ | ||
| 749 | 749 | forumthread_delete(pThread); |
| 750 | 750 | return target; |
| 751 | 751 | } |
| 752 | 752 | |
| 753 | 753 | /* |
| 754 | -** Callback for use with style.c:BundleEmitters. Emits all JS code | |
| 755 | -** required by this page. | |
| 754 | +** Emits all JS code required by /forumpost. | |
| 756 | 755 | */ |
| 757 | -void forumpost_emit_js_bundle(void){ | |
| 758 | - style_emit_script_builtin(1, 0, "forum.js"); | |
| 759 | - style_emit_script_fossil_bootstrap(1); | |
| 760 | - style_emit_script_dom(1, 0); | |
| 761 | - style_emit_script_builtin(1, 0, "fossil.page.forumpost.js"); | |
| 756 | +static void forumpost_emit_page_js(){ | |
| 757 | + static int once = 0; | |
| 758 | + if(0==once){ | |
| 759 | + once = 1; | |
| 760 | + style_emit_script_fossil_bootstrap(1); | |
| 761 | + builtin_request_js("forum.js"); | |
| 762 | + builtin_request_js("fossil.dom.js"); | |
| 763 | + builtin_request_js("fossil.page.forumpost.js"); | |
| 764 | + } | |
| 762 | 765 | } |
| 763 | 766 | |
| 764 | 767 | /* |
| 765 | 768 | ** WEBPAGE: forumpost |
| 766 | 769 | ** |
| @@ -887,11 +890,11 @@ | ||
| 887 | 890 | }else{ |
| 888 | 891 | style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); |
| 889 | 892 | style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName); |
| 890 | 893 | forum_display_hierarchical(froot, fpid); |
| 891 | 894 | } |
| 892 | - style_emit_script_bundle("forum.js"); | |
| 895 | + forumpost_emit_page_js(); | |
| 893 | 896 | style_footer(); |
| 894 | 897 | } |
| 895 | 898 | |
| 896 | 899 | /* |
| 897 | 900 | ** Return true if a forum post should be moderated. |
| 898 | 901 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -749,18 +749,21 @@ | |
| 749 | forumthread_delete(pThread); |
| 750 | return target; |
| 751 | } |
| 752 | |
| 753 | /* |
| 754 | ** Callback for use with style.c:BundleEmitters. Emits all JS code |
| 755 | ** required by this page. |
| 756 | */ |
| 757 | void forumpost_emit_js_bundle(void){ |
| 758 | style_emit_script_builtin(1, 0, "forum.js"); |
| 759 | style_emit_script_fossil_bootstrap(1); |
| 760 | style_emit_script_dom(1, 0); |
| 761 | style_emit_script_builtin(1, 0, "fossil.page.forumpost.js"); |
| 762 | } |
| 763 | |
| 764 | /* |
| 765 | ** WEBPAGE: forumpost |
| 766 | ** |
| @@ -887,11 +890,11 @@ | |
| 887 | }else{ |
| 888 | style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); |
| 889 | style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName); |
| 890 | forum_display_hierarchical(froot, fpid); |
| 891 | } |
| 892 | style_emit_script_bundle("forum.js"); |
| 893 | style_footer(); |
| 894 | } |
| 895 | |
| 896 | /* |
| 897 | ** Return true if a forum post should be moderated. |
| 898 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -749,18 +749,21 @@ | |
| 749 | forumthread_delete(pThread); |
| 750 | return target; |
| 751 | } |
| 752 | |
| 753 | /* |
| 754 | ** Emits all JS code required by /forumpost. |
| 755 | */ |
| 756 | static void forumpost_emit_page_js(){ |
| 757 | static int once = 0; |
| 758 | if(0==once){ |
| 759 | once = 1; |
| 760 | style_emit_script_fossil_bootstrap(1); |
| 761 | builtin_request_js("forum.js"); |
| 762 | builtin_request_js("fossil.dom.js"); |
| 763 | builtin_request_js("fossil.page.forumpost.js"); |
| 764 | } |
| 765 | } |
| 766 | |
| 767 | /* |
| 768 | ** WEBPAGE: forumpost |
| 769 | ** |
| @@ -887,11 +890,11 @@ | |
| 890 | }else{ |
| 891 | style_submenu_element("Chronological", "%R/%s/%s?t=c", g.zPath, zName); |
| 892 | style_submenu_element("Unformatted", "%R/%s/%s?t=r", g.zPath, zName); |
| 893 | forum_display_hierarchical(froot, fpid); |
| 894 | } |
| 895 | forumpost_emit_page_js(); |
| 896 | style_footer(); |
| 897 | } |
| 898 | |
| 899 | /* |
| 900 | ** Return true if a forum post should be moderated. |
| 901 |
+3
-3
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -441,11 +441,11 @@ | ||
| 441 | 441 | /* |
| 442 | 442 | ** Generate javascript to enhance HTML diffs. |
| 443 | 443 | */ |
| 444 | 444 | void append_diff_javascript(int sideBySide){ |
| 445 | 445 | if( !sideBySide ) return; |
| 446 | - style_load_one_js_file("sbsdiff.js"); | |
| 446 | + builtin_request_js("sbsdiff.js"); | |
| 447 | 447 | } |
| 448 | 448 | |
| 449 | 449 | /* |
| 450 | 450 | ** Construct an appropriate diffFlag for text_diff() based on query |
| 451 | 451 | ** parameters and the to boolean arguments. |
| @@ -2089,11 +2089,11 @@ | ||
| 2089 | 2089 | if( z[0]=='\n' ) z++; |
| 2090 | 2090 | } |
| 2091 | 2091 | if( n<iEnd ) cgi_printf("</div>"); |
| 2092 | 2092 | @ </pre> |
| 2093 | 2093 | if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){ |
| 2094 | - style_load_one_js_file("scroll.js"); | |
| 2094 | + builtin_request_js("scroll.js"); | |
| 2095 | 2095 | } |
| 2096 | 2096 | } |
| 2097 | 2097 | |
| 2098 | 2098 | |
| 2099 | 2099 | /* |
| @@ -3113,11 +3113,11 @@ | ||
| 3113 | 3113 | @ <input type="submit" name="apply" value="Apply Changes" /> |
| 3114 | 3114 | } |
| 3115 | 3115 | @ </td></tr> |
| 3116 | 3116 | @ </table> |
| 3117 | 3117 | @ </div></form> |
| 3118 | - style_load_one_js_file("ci_edit.js"); | |
| 3118 | + builtin_request_js("ci_edit.js"); | |
| 3119 | 3119 | style_footer(); |
| 3120 | 3120 | } |
| 3121 | 3121 | |
| 3122 | 3122 | /* |
| 3123 | 3123 | ** Prepare an ammended commit comment. Let the user modify it using the |
| 3124 | 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 | 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 |
+2
| --- src/json_config.c | ||
| +++ src/json_config.c | ||
| @@ -61,10 +61,12 @@ | ||
| 61 | 61 | { "details", CONFIGSET_SKIN }, |
| 62 | 62 | { "logo-mimetype", CONFIGSET_SKIN }, |
| 63 | 63 | { "logo-image", CONFIGSET_SKIN }, |
| 64 | 64 | { "background-mimetype", CONFIGSET_SKIN }, |
| 65 | 65 | { "background-image", CONFIGSET_SKIN }, |
| 66 | +{ "icon-mimetype", CONFIGSET_SKIN }, | |
| 67 | +{ "icon-image", CONFIGSET_SKIN }, | |
| 66 | 68 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 67 | 69 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 68 | 70 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 69 | 71 | { "adunit", CONFIGSET_SKIN }, |
| 70 | 72 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 71 | 73 |
| --- src/json_config.c | |
| +++ src/json_config.c | |
| @@ -61,10 +61,12 @@ | |
| 61 | { "details", CONFIGSET_SKIN }, |
| 62 | { "logo-mimetype", CONFIGSET_SKIN }, |
| 63 | { "logo-image", CONFIGSET_SKIN }, |
| 64 | { "background-mimetype", CONFIGSET_SKIN }, |
| 65 | { "background-image", CONFIGSET_SKIN }, |
| 66 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 67 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 68 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 69 | { "adunit", CONFIGSET_SKIN }, |
| 70 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 71 |
| --- src/json_config.c | |
| +++ src/json_config.c | |
| @@ -61,10 +61,12 @@ | |
| 61 | { "details", CONFIGSET_SKIN }, |
| 62 | { "logo-mimetype", CONFIGSET_SKIN }, |
| 63 | { "logo-image", CONFIGSET_SKIN }, |
| 64 | { "background-mimetype", CONFIGSET_SKIN }, |
| 65 | { "background-image", CONFIGSET_SKIN }, |
| 66 | { "icon-mimetype", CONFIGSET_SKIN }, |
| 67 | { "icon-image", CONFIGSET_SKIN }, |
| 68 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 69 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 70 | { "timeline-plaintext", CONFIGSET_SKIN }, |
| 71 | { "adunit", CONFIGSET_SKIN }, |
| 72 | { "adunit-omit-if-admin", CONFIGSET_SKIN }, |
| 73 |
+1
-1
| --- src/login.c | ||
| +++ src/login.c | ||
| @@ -752,11 +752,11 @@ | ||
| 752 | 752 | @ %h(zCaptcha) |
| 753 | 753 | @ </pre></td></tr></table> |
| 754 | 754 | if( bAutoCaptcha ) { |
| 755 | 755 | @ <input type="button" value="Fill out captcha" id='autofillButton' \ |
| 756 | 756 | @ data-af='%s(zDecoded)' /> |
| 757 | - style_load_one_js_file("login.js"); | |
| 757 | + builtin_request_js("login.js"); | |
| 758 | 758 | } |
| 759 | 759 | @ </div> |
| 760 | 760 | free(zCaptcha); |
| 761 | 761 | } |
| 762 | 762 | @ </form> |
| 763 | 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 | 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 @@ | ||
| 2270 | 2270 | ** this directive is a silent no-op. |
| 2271 | 2271 | */ |
| 2272 | 2272 | skin_use_alternative(blob_str(&value)); |
| 2273 | 2273 | blob_reset(&value); |
| 2274 | 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; | |
| 2275 | 2288 | } |
| 2276 | 2289 | if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){ |
| 2277 | 2290 | /* cgi-debug: FILENAME |
| 2278 | 2291 | ** |
| 2279 | 2292 | ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go |
| @@ -2455,10 +2468,18 @@ | ||
| 2455 | 2468 | ** --files GLOB comma-separate glob patterns for static file to serve |
| 2456 | 2469 | ** --host NAME specify hostname of the server |
| 2457 | 2470 | ** --https signal a request coming in via https |
| 2458 | 2471 | ** --in FILE Take input from FILE instead of standard input |
| 2459 | 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. | |
| 2460 | 2481 | ** --localauth enable automatic login for local connections |
| 2461 | 2482 | ** --nocompress do not compress HTTP replies |
| 2462 | 2483 | ** --nodelay omit backoffice processing if it would delay process exit |
| 2463 | 2484 | ** --nojail drop root privilege but do not enter the chroot jail |
| 2464 | 2485 | ** --nossl signal that no SSL connections are available |
| @@ -2484,10 +2505,11 @@ | ||
| 2484 | 2505 | int useSCGI; |
| 2485 | 2506 | int noJail; |
| 2486 | 2507 | int allowRepoList; |
| 2487 | 2508 | |
| 2488 | 2509 | Th_InitTraceLog(); |
| 2510 | + builtin_set_js_delivery_mode(find_option("jsmode",0,1),0); | |
| 2489 | 2511 | |
| 2490 | 2512 | /* The winhttp module passes the --files option as --files-urlenc with |
| 2491 | 2513 | ** the argument being URL encoded, to avoid wildcard expansion in the |
| 2492 | 2514 | ** shell. This option is for internal use and is undocumented. |
| 2493 | 2515 | */ |
| @@ -2714,10 +2736,18 @@ | ||
| 2714 | 2736 | ** --files GLOBLIST Comma-separated list of glob patterns for static files |
| 2715 | 2737 | ** --localauth enable automatic login for requests from localhost |
| 2716 | 2738 | ** --localhost listen on 127.0.0.1 only (always true for "ui") |
| 2717 | 2739 | ** --https Indicates that the input is coming through a reverse |
| 2718 | 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. | |
| 2719 | 2749 | ** --max-latency N Do not let any single HTTP request run for more than N |
| 2720 | 2750 | ** seconds (only works on unix) |
| 2721 | 2751 | ** --nocompress Do not compress HTTP replies |
| 2722 | 2752 | ** --nojail Drop root privileges but do not enter the chroot jail |
| 2723 | 2753 | ** --nossl signal that no SSL connections are available (Always |
| @@ -2760,10 +2790,11 @@ | ||
| 2760 | 2790 | |
| 2761 | 2791 | if( g.zErrlog==0 ){ |
| 2762 | 2792 | g.zErrlog = "-"; |
| 2763 | 2793 | } |
| 2764 | 2794 | g.zExtRoot = find_option("extroot",0,1); |
| 2795 | + builtin_set_js_delivery_mode(find_option("jsmode",0,1),0); | |
| 2765 | 2796 | zFileGlob = find_option("files-urlenc",0,1); |
| 2766 | 2797 | if( zFileGlob ){ |
| 2767 | 2798 | char *z = mprintf("%s", zFileGlob); |
| 2768 | 2799 | dehttpize(z); |
| 2769 | 2800 | zFileGlob = z; |
| 2770 | 2801 |
| --- 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 |
+4
-1
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -600,13 +600,16 @@ | ||
| 600 | 600 | # the run to just those test cases. |
| 601 | 601 | # |
| 602 | 602 | test: $(OBJDIR) $(APPNAME) |
| 603 | 603 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 604 | 604 | |
| 605 | -$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion | |
| 605 | +$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h | |
| 606 | 606 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 607 | 607 | |
| 608 | +$(OBJDIR)/phony.h: | |
| 609 | + # Force rebuild of VERSION.h every time we run "make" | |
| 610 | + | |
| 608 | 611 | # Setup the options used to compile the included SQLite library. |
| 609 | 612 | SQLITE_OPTIONS = -DNDEBUG=1 \ |
| 610 | 613 | -DSQLITE_DQS=0 \ |
| 611 | 614 | -DSQLITE_THREADSAFE=0 \ |
| 612 | 615 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 613 | 616 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -600,13 +600,16 @@ | |
| 600 | # the run to just those test cases. |
| 601 | # |
| 602 | test: $(OBJDIR) $(APPNAME) |
| 603 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 604 | |
| 605 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion |
| 606 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 607 | |
| 608 | # Setup the options used to compile the included SQLite library. |
| 609 | SQLITE_OPTIONS = -DNDEBUG=1 \ |
| 610 | -DSQLITE_DQS=0 \ |
| 611 | -DSQLITE_THREADSAFE=0 \ |
| 612 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 613 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -600,13 +600,16 @@ | |
| 600 | # the run to just those test cases. |
| 601 | # |
| 602 | test: $(OBJDIR) $(APPNAME) |
| 603 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 604 | |
| 605 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h |
| 606 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 607 | |
| 608 | $(OBJDIR)/phony.h: |
| 609 | # Force rebuild of VERSION.h every time we run "make" |
| 610 | |
| 611 | # Setup the options used to compile the included SQLite library. |
| 612 | SQLITE_OPTIONS = -DNDEBUG=1 \ |
| 613 | -DSQLITE_DQS=0 \ |
| 614 | -DSQLITE_THREADSAFE=0 \ |
| 615 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 616 |
+4
-1
| --- src/main.mk | ||
| +++ src/main.mk | ||
| @@ -600,13 +600,16 @@ | ||
| 600 | 600 | # the run to just those test cases. |
| 601 | 601 | # |
| 602 | 602 | test: $(OBJDIR) $(APPNAME) |
| 603 | 603 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 604 | 604 | |
| 605 | -$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion | |
| 605 | +$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h | |
| 606 | 606 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 607 | 607 | |
| 608 | +$(OBJDIR)/phony.h: | |
| 609 | + # Force rebuild of VERSION.h every time we run "make" | |
| 610 | + | |
| 608 | 611 | # Setup the options used to compile the included SQLite library. |
| 609 | 612 | SQLITE_OPTIONS = -DNDEBUG=1 \ |
| 610 | 613 | -DSQLITE_DQS=0 \ |
| 611 | 614 | -DSQLITE_THREADSAFE=0 \ |
| 612 | 615 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 613 | 616 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -600,13 +600,16 @@ | |
| 600 | # the run to just those test cases. |
| 601 | # |
| 602 | test: $(OBJDIR) $(APPNAME) |
| 603 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 604 | |
| 605 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion |
| 606 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 607 | |
| 608 | # Setup the options used to compile the included SQLite library. |
| 609 | SQLITE_OPTIONS = -DNDEBUG=1 \ |
| 610 | -DSQLITE_DQS=0 \ |
| 611 | -DSQLITE_THREADSAFE=0 \ |
| 612 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 613 |
| --- src/main.mk | |
| +++ src/main.mk | |
| @@ -600,13 +600,16 @@ | |
| 600 | # the run to just those test cases. |
| 601 | # |
| 602 | test: $(OBJDIR) $(APPNAME) |
| 603 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 604 | |
| 605 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h |
| 606 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 607 | |
| 608 | $(OBJDIR)/phony.h: |
| 609 | # Force rebuild of VERSION.h every time we run "make" |
| 610 | |
| 611 | # Setup the options used to compile the included SQLite library. |
| 612 | SQLITE_OPTIONS = -DNDEBUG=1 \ |
| 613 | -DSQLITE_DQS=0 \ |
| 614 | -DSQLITE_THREADSAFE=0 \ |
| 615 | -DSQLITE_DEFAULT_MEMSTATUS=0 \ |
| 616 |
+13
-4
| --- src/makemake.tcl | ||
| +++ src/makemake.tcl | ||
| @@ -370,15 +370,18 @@ | ||
| 370 | 370 | # the run to just those test cases. |
| 371 | 371 | # |
| 372 | 372 | test: $(OBJDIR) $(APPNAME) |
| 373 | 373 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 374 | 374 | |
| 375 | -$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion | |
| 375 | +$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h | |
| 376 | 376 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \ |
| 377 | 377 | $(SRCDIR)/../manifest \ |
| 378 | 378 | $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 379 | 379 | |
| 380 | +$(OBJDIR)/phony.h: | |
| 381 | + # Force rebuild of VERSION.h every time we run "make" | |
| 382 | + | |
| 380 | 383 | # Setup the options used to compile the included SQLite library. |
| 381 | 384 | SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>> |
| 382 | 385 | |
| 383 | 386 | # Setup the options used to compile the included SQLite shell. |
| 384 | 387 | SHELL_OPTIONS = <<<SHELL_OPTIONS>>> |
| @@ -1081,13 +1084,16 @@ | ||
| 1081 | 1084 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1082 | 1085 | # the repository after running the tests. |
| 1083 | 1086 | test: $(OBJDIR) $(APPNAME) |
| 1084 | 1087 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1085 | 1088 | |
| 1086 | -$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) | |
| 1089 | +$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h | |
| 1087 | 1090 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1088 | 1091 | |
| 1092 | +$(OBJDIR)/phony.h: | |
| 1093 | + # Force rebuild of VERSION.h every time "make" is run | |
| 1094 | + | |
| 1089 | 1095 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1090 | 1096 | # to 1. If it is set to 1, then there is no need to build or link |
| 1091 | 1097 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1092 | 1098 | # using -lsqlite3. |
| 1093 | 1099 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| @@ -1907,12 +1913,15 @@ | ||
| 1907 | 1913 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1908 | 1914 | |
| 1909 | 1915 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1910 | 1916 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1911 | 1917 | |
| 1912 | -"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" | |
| 1913 | - $** > $@ | |
| 1918 | +"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h" | |
| 1919 | + "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@ | |
| 1920 | + | |
| 1921 | +"$(B)\phony.h" : | |
| 1922 | + rem Force rebuild of VERSION.h whenever nmake is run | |
| 1914 | 1923 | |
| 1915 | 1924 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1916 | 1925 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1917 | 1926 | |
| 1918 | 1927 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1919 | 1928 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -370,15 +370,18 @@ | |
| 370 | # the run to just those test cases. |
| 371 | # |
| 372 | test: $(OBJDIR) $(APPNAME) |
| 373 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 374 | |
| 375 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion |
| 376 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \ |
| 377 | $(SRCDIR)/../manifest \ |
| 378 | $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 379 | |
| 380 | # Setup the options used to compile the included SQLite library. |
| 381 | SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>> |
| 382 | |
| 383 | # Setup the options used to compile the included SQLite shell. |
| 384 | SHELL_OPTIONS = <<<SHELL_OPTIONS>>> |
| @@ -1081,13 +1084,16 @@ | |
| 1081 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1082 | # the repository after running the tests. |
| 1083 | test: $(OBJDIR) $(APPNAME) |
| 1084 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1085 | |
| 1086 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) |
| 1087 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1088 | |
| 1089 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1090 | # to 1. If it is set to 1, then there is no need to build or link |
| 1091 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1092 | # using -lsqlite3. |
| 1093 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| @@ -1907,12 +1913,15 @@ | |
| 1907 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1908 | |
| 1909 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1910 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1911 | |
| 1912 | "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" |
| 1913 | $** > $@ |
| 1914 | |
| 1915 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1916 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1917 | |
| 1918 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1919 |
| --- src/makemake.tcl | |
| +++ src/makemake.tcl | |
| @@ -370,15 +370,18 @@ | |
| 370 | # the run to just those test cases. |
| 371 | # |
| 372 | test: $(OBJDIR) $(APPNAME) |
| 373 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) $(TESTFLAGS) |
| 374 | |
| 375 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION $(OBJDIR)/mkversion $(OBJDIR)/phony.h |
| 376 | $(OBJDIR)/mkversion $(SRCDIR)/../manifest.uuid \ |
| 377 | $(SRCDIR)/../manifest \ |
| 378 | $(SRCDIR)/../VERSION >$(OBJDIR)/VERSION.h |
| 379 | |
| 380 | $(OBJDIR)/phony.h: |
| 381 | # Force rebuild of VERSION.h every time we run "make" |
| 382 | |
| 383 | # Setup the options used to compile the included SQLite library. |
| 384 | SQLITE_OPTIONS = <<<SQLITE_OPTIONS>>> |
| 385 | |
| 386 | # Setup the options used to compile the included SQLite shell. |
| 387 | SHELL_OPTIONS = <<<SHELL_OPTIONS>>> |
| @@ -1081,13 +1084,16 @@ | |
| 1084 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1085 | # the repository after running the tests. |
| 1086 | test: $(OBJDIR) $(APPNAME) |
| 1087 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1088 | |
| 1089 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h |
| 1090 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1091 | |
| 1092 | $(OBJDIR)/phony.h: |
| 1093 | # Force rebuild of VERSION.h every time "make" is run |
| 1094 | |
| 1095 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1096 | # to 1. If it is set to 1, then there is no need to build or link |
| 1097 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1098 | # using -lsqlite3. |
| 1099 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| @@ -1907,12 +1913,15 @@ | |
| 1913 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1914 | |
| 1915 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1916 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1917 | |
| 1918 | "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h" |
| 1919 | "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@ |
| 1920 | |
| 1921 | "$(B)\phony.h" : |
| 1922 | rem Force rebuild of VERSION.h whenever nmake is run |
| 1923 | |
| 1924 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1925 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1926 | |
| 1927 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1928 |
+1
| --- src/mkbuiltin.c | ||
| +++ src/mkbuiltin.c | ||
| @@ -88,10 +88,11 @@ | ||
| 88 | 88 | i = k-1; |
| 89 | 89 | continue; |
| 90 | 90 | } |
| 91 | 91 | } |
| 92 | 92 | if( c=='\n' ){ |
| 93 | + if( j==0 ) continue; | |
| 93 | 94 | while( j>0 && isspace(z[j-1]) ) j--; |
| 94 | 95 | z[j++] = '\n'; |
| 95 | 96 | while( i+1<n && isspace(z[i+1]) ) i++; |
| 96 | 97 | continue; |
| 97 | 98 | } |
| 98 | 99 |
| --- 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 |
+57
-1
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -1235,11 +1235,11 @@ | ||
| 1235 | 1235 | } |
| 1236 | 1236 | |
| 1237 | 1237 | /* |
| 1238 | 1238 | ** WEBPAGE: setup_logo |
| 1239 | 1239 | ** |
| 1240 | -** Administrative page for changing the logo image. | |
| 1240 | +** Administrative page for changing the logo, background, and icon images. | |
| 1241 | 1241 | */ |
| 1242 | 1242 | void setup_logo(void){ |
| 1243 | 1243 | const char *zLogoMtime = db_get_mtime("logo-image", 0, 0); |
| 1244 | 1244 | const char *zLogoMime = db_get("logo-mimetype","image/gif"); |
| 1245 | 1245 | const char *aLogoImg = P("logoim"); |
| @@ -1246,16 +1246,23 @@ | ||
| 1246 | 1246 | int szLogoImg = atoi(PD("logoim:bytes","0")); |
| 1247 | 1247 | const char *zBgMtime = db_get_mtime("background-image", 0, 0); |
| 1248 | 1248 | const char *zBgMime = db_get("background-mimetype","image/gif"); |
| 1249 | 1249 | const char *aBgImg = P("bgim"); |
| 1250 | 1250 | int szBgImg = atoi(PD("bgim:bytes","0")); |
| 1251 | + const char *zIconMtime = db_get_mtime("icon-image", 0, 0); | |
| 1252 | + const char *zIconMime = db_get("icon-mimetype","image/gif"); | |
| 1253 | + const char *aIconImg = P("iconim"); | |
| 1254 | + int szIconImg = atoi(PD("iconim:bytes","0")); | |
| 1251 | 1255 | if( szLogoImg>0 ){ |
| 1252 | 1256 | zLogoMime = PD("logoim:mimetype","image/gif"); |
| 1253 | 1257 | } |
| 1254 | 1258 | if( szBgImg>0 ){ |
| 1255 | 1259 | zBgMime = PD("bgim:mimetype","image/gif"); |
| 1256 | 1260 | } |
| 1261 | + if( szIconImg>0 ){ | |
| 1262 | + zIconMime = PD("iconim:mimetype","image/gif"); | |
| 1263 | + } | |
| 1257 | 1264 | login_check_credentials(); |
| 1258 | 1265 | if( !g.perm.Admin ){ |
| 1259 | 1266 | login_needed(0); |
| 1260 | 1267 | return; |
| 1261 | 1268 | } |
| @@ -1309,10 +1316,35 @@ | ||
| 1309 | 1316 | "DELETE FROM config WHERE name IN " |
| 1310 | 1317 | "('background-image','background-mimetype')" |
| 1311 | 1318 | ); |
| 1312 | 1319 | db_end_transaction(0); |
| 1313 | 1320 | cgi_redirect("setup_logo"); |
| 1321 | + }else if( P("seticon")!=0 && zIconMime && zIconMime[0] && szIconImg>0 ){ | |
| 1322 | + Blob img; | |
| 1323 | + Stmt ins; | |
| 1324 | + blob_init(&img, aIconImg, szIconImg); | |
| 1325 | + db_prepare(&ins, | |
| 1326 | + "REPLACE INTO config(name,value,mtime)" | |
| 1327 | + " VALUES('icon-image',:bytes,now())" | |
| 1328 | + ); | |
| 1329 | + db_bind_blob(&ins, ":bytes", &img); | |
| 1330 | + db_step(&ins); | |
| 1331 | + db_finalize(&ins); | |
| 1332 | + db_multi_exec( | |
| 1333 | + "REPLACE INTO config(name,value,mtime)" | |
| 1334 | + " VALUES('icon-mimetype',%Q,now())", | |
| 1335 | + zIconMime | |
| 1336 | + ); | |
| 1337 | + db_end_transaction(0); | |
| 1338 | + cgi_redirect("setup_logo"); | |
| 1339 | + }else if( P("clricon")!=0 ){ | |
| 1340 | + db_multi_exec( | |
| 1341 | + "DELETE FROM config WHERE name IN " | |
| 1342 | + "('icon-image','icon-mimetype')" | |
| 1343 | + ); | |
| 1344 | + db_end_transaction(0); | |
| 1345 | + cgi_redirect("setup_logo"); | |
| 1314 | 1346 | } |
| 1315 | 1347 | style_header("Edit Project Logo And Background"); |
| 1316 | 1348 | @ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b> |
| 1317 | 1349 | @ and looks like this:</p> |
| 1318 | 1350 | @ <blockquote><p><img src="%s(g.zTop)/logo/%z(zLogoMtime)" \ |
| @@ -1358,10 +1390,34 @@ | ||
| 1358 | 1390 | @ <input type="submit" name="setbg" value="Change Background" /> |
| 1359 | 1391 | @ <input type="submit" name="clrbg" value="Revert To Default" /></p> |
| 1360 | 1392 | @ </div></form> |
| 1361 | 1393 | @ <p>(Properties: "background-image" and "background-mimetype") |
| 1362 | 1394 | @ <hr /> |
| 1395 | + @ | |
| 1396 | + @ <p>The current icon image has a MIME-Type of <b>%h(zIconMime)</b> | |
| 1397 | + @ and looks like this:</p> | |
| 1398 | + @ <blockquote><p><img src="%s(g.zTop)/favicon.ico/%z(zIconMtime)" \ | |
| 1399 | + @ alt="icon" border=1 /> | |
| 1400 | + @ </p></blockquote> | |
| 1401 | + @ | |
| 1402 | + @ <form action="%s(g.zTop)/setup_logo" method="post" | |
| 1403 | + @ enctype="multipart/form-data"><div> | |
| 1404 | + @ <p>The icon image is accessible to all users at this URL: | |
| 1405 | + @ <a href="%s(g.zBaseURL)/favicon.ico">%s(g.zBaseURL)/favicon.ico</a>. | |
| 1406 | + @ The icon image may or may not appear on each | |
| 1407 | + @ page depending on the web browser in use and the MIME-Types that it | |
| 1408 | + @ supports for icon images. | |
| 1409 | + @ To change the icon image, use the following form:</p> | |
| 1410 | + login_insert_csrf_secret(); | |
| 1411 | + @ Icon image file: | |
| 1412 | + @ <input type="file" name="iconim" size="60" accept="image/*" /> | |
| 1413 | + @ <p align="center"> | |
| 1414 | + @ <input type="submit" name="seticon" value="Change Icon" /> | |
| 1415 | + @ <input type="submit" name="clricon" value="Revert To Default" /></p> | |
| 1416 | + @ </div></form> | |
| 1417 | + @ <p>(Properties: "icon-image" and "icon-mimetype") | |
| 1418 | + @ <hr /> | |
| 1363 | 1419 | @ |
| 1364 | 1420 | @ <p><span class="note">Note:</span> Your browser has probably cached these |
| 1365 | 1421 | @ images, so you may need to press the Reload button before changes will |
| 1366 | 1422 | @ take effect. </p> |
| 1367 | 1423 | style_footer(); |
| 1368 | 1424 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1235,11 +1235,11 @@ | |
| 1235 | } |
| 1236 | |
| 1237 | /* |
| 1238 | ** WEBPAGE: setup_logo |
| 1239 | ** |
| 1240 | ** Administrative page for changing the logo image. |
| 1241 | */ |
| 1242 | void setup_logo(void){ |
| 1243 | const char *zLogoMtime = db_get_mtime("logo-image", 0, 0); |
| 1244 | const char *zLogoMime = db_get("logo-mimetype","image/gif"); |
| 1245 | const char *aLogoImg = P("logoim"); |
| @@ -1246,16 +1246,23 @@ | |
| 1246 | int szLogoImg = atoi(PD("logoim:bytes","0")); |
| 1247 | const char *zBgMtime = db_get_mtime("background-image", 0, 0); |
| 1248 | const char *zBgMime = db_get("background-mimetype","image/gif"); |
| 1249 | const char *aBgImg = P("bgim"); |
| 1250 | int szBgImg = atoi(PD("bgim:bytes","0")); |
| 1251 | if( szLogoImg>0 ){ |
| 1252 | zLogoMime = PD("logoim:mimetype","image/gif"); |
| 1253 | } |
| 1254 | if( szBgImg>0 ){ |
| 1255 | zBgMime = PD("bgim:mimetype","image/gif"); |
| 1256 | } |
| 1257 | login_check_credentials(); |
| 1258 | if( !g.perm.Admin ){ |
| 1259 | login_needed(0); |
| 1260 | return; |
| 1261 | } |
| @@ -1309,10 +1316,35 @@ | |
| 1309 | "DELETE FROM config WHERE name IN " |
| 1310 | "('background-image','background-mimetype')" |
| 1311 | ); |
| 1312 | db_end_transaction(0); |
| 1313 | cgi_redirect("setup_logo"); |
| 1314 | } |
| 1315 | style_header("Edit Project Logo And Background"); |
| 1316 | @ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b> |
| 1317 | @ and looks like this:</p> |
| 1318 | @ <blockquote><p><img src="%s(g.zTop)/logo/%z(zLogoMtime)" \ |
| @@ -1358,10 +1390,34 @@ | |
| 1358 | @ <input type="submit" name="setbg" value="Change Background" /> |
| 1359 | @ <input type="submit" name="clrbg" value="Revert To Default" /></p> |
| 1360 | @ </div></form> |
| 1361 | @ <p>(Properties: "background-image" and "background-mimetype") |
| 1362 | @ <hr /> |
| 1363 | @ |
| 1364 | @ <p><span class="note">Note:</span> Your browser has probably cached these |
| 1365 | @ images, so you may need to press the Reload button before changes will |
| 1366 | @ take effect. </p> |
| 1367 | style_footer(); |
| 1368 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -1235,11 +1235,11 @@ | |
| 1235 | } |
| 1236 | |
| 1237 | /* |
| 1238 | ** WEBPAGE: setup_logo |
| 1239 | ** |
| 1240 | ** Administrative page for changing the logo, background, and icon images. |
| 1241 | */ |
| 1242 | void setup_logo(void){ |
| 1243 | const char *zLogoMtime = db_get_mtime("logo-image", 0, 0); |
| 1244 | const char *zLogoMime = db_get("logo-mimetype","image/gif"); |
| 1245 | const char *aLogoImg = P("logoim"); |
| @@ -1246,16 +1246,23 @@ | |
| 1246 | int szLogoImg = atoi(PD("logoim:bytes","0")); |
| 1247 | const char *zBgMtime = db_get_mtime("background-image", 0, 0); |
| 1248 | const char *zBgMime = db_get("background-mimetype","image/gif"); |
| 1249 | const char *aBgImg = P("bgim"); |
| 1250 | int szBgImg = atoi(PD("bgim:bytes","0")); |
| 1251 | const char *zIconMtime = db_get_mtime("icon-image", 0, 0); |
| 1252 | const char *zIconMime = db_get("icon-mimetype","image/gif"); |
| 1253 | const char *aIconImg = P("iconim"); |
| 1254 | int szIconImg = atoi(PD("iconim:bytes","0")); |
| 1255 | if( szLogoImg>0 ){ |
| 1256 | zLogoMime = PD("logoim:mimetype","image/gif"); |
| 1257 | } |
| 1258 | if( szBgImg>0 ){ |
| 1259 | zBgMime = PD("bgim:mimetype","image/gif"); |
| 1260 | } |
| 1261 | if( szIconImg>0 ){ |
| 1262 | zIconMime = PD("iconim:mimetype","image/gif"); |
| 1263 | } |
| 1264 | login_check_credentials(); |
| 1265 | if( !g.perm.Admin ){ |
| 1266 | login_needed(0); |
| 1267 | return; |
| 1268 | } |
| @@ -1309,10 +1316,35 @@ | |
| 1316 | "DELETE FROM config WHERE name IN " |
| 1317 | "('background-image','background-mimetype')" |
| 1318 | ); |
| 1319 | db_end_transaction(0); |
| 1320 | cgi_redirect("setup_logo"); |
| 1321 | }else if( P("seticon")!=0 && zIconMime && zIconMime[0] && szIconImg>0 ){ |
| 1322 | Blob img; |
| 1323 | Stmt ins; |
| 1324 | blob_init(&img, aIconImg, szIconImg); |
| 1325 | db_prepare(&ins, |
| 1326 | "REPLACE INTO config(name,value,mtime)" |
| 1327 | " VALUES('icon-image',:bytes,now())" |
| 1328 | ); |
| 1329 | db_bind_blob(&ins, ":bytes", &img); |
| 1330 | db_step(&ins); |
| 1331 | db_finalize(&ins); |
| 1332 | db_multi_exec( |
| 1333 | "REPLACE INTO config(name,value,mtime)" |
| 1334 | " VALUES('icon-mimetype',%Q,now())", |
| 1335 | zIconMime |
| 1336 | ); |
| 1337 | db_end_transaction(0); |
| 1338 | cgi_redirect("setup_logo"); |
| 1339 | }else if( P("clricon")!=0 ){ |
| 1340 | db_multi_exec( |
| 1341 | "DELETE FROM config WHERE name IN " |
| 1342 | "('icon-image','icon-mimetype')" |
| 1343 | ); |
| 1344 | db_end_transaction(0); |
| 1345 | cgi_redirect("setup_logo"); |
| 1346 | } |
| 1347 | style_header("Edit Project Logo And Background"); |
| 1348 | @ <p>The current project logo has a MIME-Type of <b>%h(zLogoMime)</b> |
| 1349 | @ and looks like this:</p> |
| 1350 | @ <blockquote><p><img src="%s(g.zTop)/logo/%z(zLogoMtime)" \ |
| @@ -1358,10 +1390,34 @@ | |
| 1390 | @ <input type="submit" name="setbg" value="Change Background" /> |
| 1391 | @ <input type="submit" name="clrbg" value="Revert To Default" /></p> |
| 1392 | @ </div></form> |
| 1393 | @ <p>(Properties: "background-image" and "background-mimetype") |
| 1394 | @ <hr /> |
| 1395 | @ |
| 1396 | @ <p>The current icon image has a MIME-Type of <b>%h(zIconMime)</b> |
| 1397 | @ and looks like this:</p> |
| 1398 | @ <blockquote><p><img src="%s(g.zTop)/favicon.ico/%z(zIconMtime)" \ |
| 1399 | @ alt="icon" border=1 /> |
| 1400 | @ </p></blockquote> |
| 1401 | @ |
| 1402 | @ <form action="%s(g.zTop)/setup_logo" method="post" |
| 1403 | @ enctype="multipart/form-data"><div> |
| 1404 | @ <p>The icon image is accessible to all users at this URL: |
| 1405 | @ <a href="%s(g.zBaseURL)/favicon.ico">%s(g.zBaseURL)/favicon.ico</a>. |
| 1406 | @ The icon image may or may not appear on each |
| 1407 | @ page depending on the web browser in use and the MIME-Types that it |
| 1408 | @ supports for icon images. |
| 1409 | @ To change the icon image, use the following form:</p> |
| 1410 | login_insert_csrf_secret(); |
| 1411 | @ Icon image file: |
| 1412 | @ <input type="file" name="iconim" size="60" accept="image/*" /> |
| 1413 | @ <p align="center"> |
| 1414 | @ <input type="submit" name="seticon" value="Change Icon" /> |
| 1415 | @ <input type="submit" name="clricon" value="Revert To Default" /></p> |
| 1416 | @ </div></form> |
| 1417 | @ <p>(Properties: "icon-image" and "icon-mimetype") |
| 1418 | @ <hr /> |
| 1419 | @ |
| 1420 | @ <p><span class="note">Note:</span> Your browser has probably cached these |
| 1421 | @ images, so you may need to press the Reload button before changes will |
| 1422 | @ take effect. </p> |
| 1423 | style_footer(); |
| 1424 |
+1
-1
| --- src/setupuser.c | ||
| +++ src/setupuser.c | ||
| @@ -702,11 +702,11 @@ | ||
| 702 | 702 | @ </tr> |
| 703 | 703 | } |
| 704 | 704 | @ </table> |
| 705 | 705 | @ </div></form> |
| 706 | 706 | @ </div> |
| 707 | - style_load_one_js_file("useredit.js"); | |
| 707 | + builtin_request_js("useredit.js"); | |
| 708 | 708 | @ <hr> |
| 709 | 709 | @ <h1>Notes On Privileges And Capabilities:</h1> |
| 710 | 710 | @ <ul> |
| 711 | 711 | if( higherUser ){ |
| 712 | 712 | @ <li><p class="missingPriv"> |
| 713 | 713 |
| --- 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 @@ | ||
| 1101 | 1101 | @ undo a prior publish. |
| 1102 | 1102 | }else{ |
| 1103 | 1103 | @ <p>Visit the <a href='%R/setup_skin_admin'>Skin Admin</a> page |
| 1104 | 1104 | @ for cleanup and recovery actions. |
| 1105 | 1105 | } |
| 1106 | - style_load_one_js_file("skin.js"); | |
| 1106 | + builtin_request_js("skin.js"); | |
| 1107 | 1107 | style_footer(); |
| 1108 | 1108 | } |
| 1109 | 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 | 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 |
+39
-302
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -88,14 +88,10 @@ | ||
| 88 | 88 | |
| 89 | 89 | /* |
| 90 | 90 | ** Flags for various javascript files needed prior to </body> |
| 91 | 91 | */ |
| 92 | 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 | 93 | |
| 98 | 94 | /* |
| 99 | 95 | ** Extra JS added to the end of the file. |
| 100 | 96 | */ |
| 101 | 97 | static Blob blobOnLoad = BLOB_INITIALIZER; |
| @@ -484,11 +480,11 @@ | ||
| 484 | 480 | zBtnFmt/*works-like:"%h%s%h%h%d"*/, |
| 485 | 481 | zTargetId,zText,zTargetId,zTargetId,cchLength); |
| 486 | 482 | } |
| 487 | 483 | } |
| 488 | 484 | free(zText); |
| 489 | - style_copybutton_control(); | |
| 485 | + builtin_request_js("copybtn.js"); | |
| 490 | 486 | return zResult; |
| 491 | 487 | } |
| 492 | 488 | |
| 493 | 489 | /* |
| 494 | 490 | ** Return a random nonce that is stored in static space. For a particular |
| @@ -694,66 +690,17 @@ | ||
| 694 | 690 | |
| 695 | 691 | /* |
| 696 | 692 | ** Indicate that the table-sorting javascript is needed. |
| 697 | 693 | */ |
| 698 | 694 | 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"); | |
| 748 | 696 | } |
| 749 | 697 | |
| 750 | 698 | /* |
| 751 | 699 | ** Generate code to load all required javascript files. |
| 752 | 700 | */ |
| 753 | 701 | static void style_load_all_js_files(void){ |
| 754 | - int i; | |
| 755 | 702 | if( needHrefJs ){ |
| 756 | 703 | int nDelay = db_get_int("auto-hyperlink-delay",0); |
| 757 | 704 | int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0); |
| 758 | 705 | @ <script id='href-data' type='application/json'>\ |
| 759 | 706 | @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script> |
| @@ -762,43 +709,20 @@ | ||
| 762 | 709 | @ function debugMsg(msg){ |
| 763 | 710 | @ var n = document.getElementById("debugMsg"); |
| 764 | 711 | @ if(n){n.textContent=msg;} |
| 765 | 712 | @ } |
| 766 | 713 | if( needHrefJs ){ |
| 714 | + @ /* href.js */ | |
| 767 | 715 | cgi_append_content(builtin_text("href.js"),-1); |
| 768 | 716 | } |
| 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 | 717 | if( blob_size(&blobOnLoad)>0 ){ |
| 785 | 718 | @ window.onload = function(){ |
| 786 | 719 | cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad)); |
| 787 | 720 | cgi_append_content("\n}\n", -1); |
| 788 | 721 | } |
| 789 | 722 | @ </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(); | |
| 800 | 724 | } |
| 801 | 725 | |
| 802 | 726 | /* |
| 803 | 727 | ** Draw the footer at the bottom of the page. |
| 804 | 728 | */ |
| @@ -916,11 +840,11 @@ | ||
| 916 | 840 | @ </div> |
| 917 | 841 | if( nSubmenuCtrl ){ |
| 918 | 842 | cgi_query_parameters_to_hidden(); |
| 919 | 843 | cgi_tag_query_parameter(0); |
| 920 | 844 | @ </form> |
| 921 | - style_load_one_js_file("menu.js"); | |
| 845 | + builtin_request_js("menu.js"); | |
| 922 | 846 | } |
| 923 | 847 | } |
| 924 | 848 | |
| 925 | 849 | zAd = style_adunit_text(&mAdFlags); |
| 926 | 850 | if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ |
| @@ -1127,109 +1051,10 @@ | ||
| 1127 | 1051 | |
| 1128 | 1052 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 1129 | 1053 | g.isConst = 1; |
| 1130 | 1054 | } |
| 1131 | 1055 | |
| 1132 | -/* | |
| 1133 | -** Maps a "bundle" name to a callback which emits the text of that | |
| 1134 | -** bundle. For use in consolidating scripts for certain pages into a | |
| 1135 | -** single cacheable request. | |
| 1136 | -*/ | |
| 1137 | -typedef struct { | |
| 1138 | - const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */ | |
| 1139 | - void (*xEmit)(void); /* Emits amalgamated text output for this | |
| 1140 | - bundle */ | |
| 1141 | -} BundleEmitter; | |
| 1142 | -/* | |
| 1143 | -** Map each required bundle here... | |
| 1144 | -*/ | |
| 1145 | -static const BundleEmitter BundleEmitters[] = { | |
| 1146 | -/* Keep these sorted for bsearch() */ | |
| 1147 | -{"fileedit.js", fileedit_emit_js_bundle}, | |
| 1148 | -{"forum.js", forumpost_emit_js_bundle}, | |
| 1149 | -{"wikiedit.js", wikiedit_emit_js_bundle} | |
| 1150 | -}; | |
| 1151 | - | |
| 1152 | -/* | |
| 1153 | -** Comparison function for bsearch() for searching a BundleEmitter | |
| 1154 | -** list for a matching name. | |
| 1155 | -*/ | |
| 1156 | -static int cmp_builtin_bundle_name(const void *a, const void *b){ | |
| 1157 | - const BundleEmitter * rA = (const BundleEmitter*)a; | |
| 1158 | - const BundleEmitter * rB = (const BundleEmitter*)b; | |
| 1159 | - return fossil_strcmp(rA->zName, rB->zName); | |
| 1160 | -} | |
| 1161 | - | |
| 1162 | -/* | |
| 1163 | -** Internal helper for /builtin/FILENAME for dispatching "bundles" | |
| 1164 | -** of amalgamated text (primarily JS) code. | |
| 1165 | -** | |
| 1166 | -** Returns true if it finds a bundle matcing the given name, else | |
| 1167 | -** false. On success it outputs the amalgamated bundle without any | |
| 1168 | -** sort of wrapper, e.g. SCRIPT tag | |
| 1169 | -*/ | |
| 1170 | -static int page_builtin_text_bundle(const char * zFilename){ | |
| 1171 | - const BundleEmitter * pBH; | |
| 1172 | - BundleEmitter needle = {zFilename, 0}; | |
| 1173 | - | |
| 1174 | - pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters, | |
| 1175 | - count(BundleEmitters), | |
| 1176 | - sizeof BundleEmitters[0], | |
| 1177 | - cmp_builtin_bundle_name); | |
| 1178 | - if(pBH!=0){ | |
| 1179 | - pBH->xEmit(); | |
| 1180 | - } | |
| 1181 | - return pBH!=0; | |
| 1182 | -} | |
| 1183 | - | |
| 1184 | -/* | |
| 1185 | -** WEBPAGE: builtin | |
| 1186 | -** URL: builtin/FILENAME | |
| 1187 | -** | |
| 1188 | -** Return the built-in text given by FILENAME. This is used internally | |
| 1189 | -** by many Fossil web pages to load built-in javascript files. | |
| 1190 | -** | |
| 1191 | -** If the id= parameter is present, then Fossil assumes that the | |
| 1192 | -** result is immutable and sets a very large cache retention time (1 | |
| 1193 | -** year). | |
| 1194 | -*/ | |
| 1195 | -void page_builtin_text(void){ | |
| 1196 | - Blob out; | |
| 1197 | - const char *zName = P("name"); | |
| 1198 | - const char *zTxt = 0; | |
| 1199 | - const char *zId = P("id"); | |
| 1200 | - int nId; | |
| 1201 | - int isBundle = 0; | |
| 1202 | - | |
| 1203 | - if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){ | |
| 1204 | - g.isConst = 1; | |
| 1205 | - }else{ | |
| 1206 | - etag_check(0,0)/*might not return*/; | |
| 1207 | - } | |
| 1208 | - if( zName ){ | |
| 1209 | - if( sqlite3_strglob("*.js", zName)==0 ){ | |
| 1210 | - cgi_set_content_type("application/javascript"); | |
| 1211 | - }else{ | |
| 1212 | - cgi_set_content_type("text/plain"); | |
| 1213 | - } | |
| 1214 | - if(':'==zName[0]){ | |
| 1215 | - isBundle = 1; | |
| 1216 | - zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL; | |
| 1217 | - }else{ | |
| 1218 | - zTxt = builtin_text(zName); | |
| 1219 | - } | |
| 1220 | - } | |
| 1221 | - if( zTxt==0 ){ | |
| 1222 | - cgi_set_content_type("text/html"); | |
| 1223 | - cgi_set_status(404, "Not Found"); | |
| 1224 | - @ File "%h(zName)" not found | |
| 1225 | - }else if(isBundle==0){ | |
| 1226 | - blob_init(&out, zTxt, -1); | |
| 1227 | - cgi_set_content(&out); | |
| 1228 | - } | |
| 1229 | -} | |
| 1230 | - | |
| 1231 | 1056 | /* |
| 1232 | 1057 | ** All possible capabilities |
| 1233 | 1058 | */ |
| 1234 | 1059 | static const char allCap[] = |
| 1235 | 1060 | "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL"; |
| @@ -1605,21 +1430,18 @@ | ||
| 1605 | 1430 | ** 1) window.fossil core object, some of which depends on C-lelel |
| 1606 | 1431 | ** runtime data. That part of the script is always emitted inline. If |
| 1607 | 1432 | ** addScripTag is true then it is wrapped in its own SCRIPT tag, else |
| 1608 | 1433 | ** it is assumed that the caller already opened a tag. |
| 1609 | 1434 | ** |
| 1610 | -** 2) Emits the static fossil.bootstrap.js. If asInline is true then | |
| 1611 | -** it is emitted inline with the components from (1), else it is | |
| 1612 | -** emitted as a separate SCRIPT tag with | |
| 1613 | -** src=/builtin/fossil.bootstrap.js (so causes another HTTP request). | |
| 1435 | +** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). | |
| 1614 | 1436 | */ |
| 1615 | -void style_emit_script_fossil_bootstrap(int asInline){ | |
| 1437 | +void style_emit_script_fossil_bootstrap(int addScriptTag){ | |
| 1616 | 1438 | static int once = 0; |
| 1617 | 1439 | if(0==once++){ |
| 1618 | 1440 | /* Set up the generic/app-agnostic parts of window.fossil |
| 1619 | 1441 | ** which require C-level state... */ |
| 1620 | - if(asInline==0){ | |
| 1442 | + if(addScriptTag!=0){ | |
| 1621 | 1443 | style_emit_script_tag(0,0); |
| 1622 | 1444 | } |
| 1623 | 1445 | CX("(function(){\n" |
| 1624 | 1446 | "if(!window.fossil) window.fossil={};\n" |
| 1625 | 1447 | "window.fossil.version = %!j;\n" |
| @@ -1646,18 +1468,16 @@ | ||
| 1646 | 1468 | */ |
| 1647 | 1469 | CX("window.fossil.page = {" |
| 1648 | 1470 | "name:\"%T\"" |
| 1649 | 1471 | "};\n", g.zPath); |
| 1650 | 1472 | CX("})();\n"); |
| 1651 | - /* The remaining fossil object bootstrap code is not dependent on | |
| 1652 | - ** C-runtime state... */ | |
| 1653 | - if(asInline!=0){ | |
| 1654 | - CX("%s\n", builtin_text("fossil.bootstrap.js")); | |
| 1655 | - }else{ | |
| 1473 | + if(addScriptTag!=0){ | |
| 1656 | 1474 | style_emit_script_tag(1,0); |
| 1657 | - style_emit_script_builtin(0,1,"fossil.bootstrap.js"); | |
| 1658 | 1475 | } |
| 1476 | + /* The remaining window.fossil bootstrap code is not dependent on | |
| 1477 | + ** C-runtime state... */ | |
| 1478 | + builtin_request_js("fossil.bootstrap.js"); | |
| 1659 | 1479 | } |
| 1660 | 1480 | } |
| 1661 | 1481 | |
| 1662 | 1482 | /* |
| 1663 | 1483 | ** If passed 0 as its first argument, it emits a script opener tag |
| @@ -1688,116 +1508,33 @@ | ||
| 1688 | 1508 | CX("</script>\n"); |
| 1689 | 1509 | } |
| 1690 | 1510 | } |
| 1691 | 1511 | |
| 1692 | 1512 | /* |
| 1693 | -** Emits a script tag which uses content from a builtin script file. | |
| 1694 | -** | |
| 1695 | -** If asInline is false, the script is emitted as a SCRIPT tag with a | |
| 1696 | -** src attribute of /builtin/zName and the 2nd parameter is | |
| 1697 | -** ignored. If asInline is true then the contents of the script are | |
| 1698 | -** emitted directly, with a wrapping SCRIPT tag if addScripTag is | |
| 1699 | -** true, else no wrapping script tag.. | |
| 1700 | -** | |
| 1701 | -** If it is false, a script tag loading it via | |
| 1702 | -** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a | |
| 1703 | -** build-time-dependent cache-buster value. | |
| 1704 | -*/ | |
| 1705 | -void style_emit_script_builtin(int asInline, int addScripTag, | |
| 1706 | - char const * zName){ | |
| 1707 | - if(asInline){ | |
| 1708 | - if(addScripTag){ | |
| 1709 | - style_emit_script_tag(0,0); | |
| 1710 | - } | |
| 1711 | - CX("%s", builtin_text(zName)); | |
| 1712 | - if(addScripTag){ | |
| 1713 | - style_emit_script_tag(1,0); | |
| 1714 | - } | |
| 1715 | - }else{ | |
| 1716 | - char * zFullName = mprintf("builtin/%s",zName); | |
| 1717 | - const char * zHash = fossil_exe_id(); | |
| 1718 | - CX("<script src='%R/%T?cache=%.8s'></script>\n", | |
| 1719 | - zFullName, zHash); | |
| 1720 | - fossil_free(zFullName); | |
| 1721 | - } | |
| 1722 | -} | |
| 1723 | - | |
| 1724 | -/* | |
| 1725 | -** A convenience wrapper arond style_emit_script_builtin() which | |
| 1726 | -** prepends a ':' to zName and passes (0,0,newName) to that | |
| 1727 | -** function. i.e. it emits a SCRIPT tag with | |
| 1728 | -** src=.../builtin/:${zName}?cache=.... The given name is assumed to | |
| 1729 | -** have been added to the style.c:BundleEmitters map. | |
| 1730 | -*/ | |
| 1731 | -void style_emit_script_bundle(char const * zName){ | |
| 1732 | - char *zBundle = mprintf(":%s", zName); | |
| 1733 | - style_emit_script_builtin(0, 0, zBundle); | |
| 1734 | - fossil_free(zBundle); | |
| 1735 | -} | |
| 1736 | - | |
| 1737 | -/* | |
| 1738 | -** The first time this is called it emits the JS code from the | |
| 1739 | -** built-in file fossil.fossil.js. Subsequent calls are no-ops. | |
| 1740 | -** | |
| 1741 | -** If passed a true first argument, it emits the contents directly | |
| 1742 | -** to the page output, else it emits a script tag with a | |
| 1743 | -** src=builtin/... to load the script. | |
| 1744 | -** | |
| 1745 | -** If asInline is true and addScripTag is true then the contents | |
| 1746 | -** are emitted directly but wrapped in a SCRIPT tag. If asInline | |
| 1747 | -** is false, addScriptTag is ignored. | |
| 1748 | -** | |
| 1749 | -** Note that this code relies on that loaded via | |
| 1750 | -** style_emit_script_fossil_bootstrap() but it does not call that | |
| 1751 | -** routine. | |
| 1752 | -*/ | |
| 1753 | -void style_emit_script_fetch(int asInline, int addScripTag){ | |
| 1754 | - static int once = 0; | |
| 1755 | - if(0==once++){ | |
| 1756 | - style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js"); | |
| 1757 | - } | |
| 1758 | -} | |
| 1759 | - | |
| 1760 | -/* | |
| 1761 | -** The first time this is called it emits the JS code from the | |
| 1762 | -** built-in file fossil.dom.js. Subsequent calls are no-ops. | |
| 1763 | -** | |
| 1764 | -** If passed a true first argument, it emits the contents directly | |
| 1765 | -** to the page output, else it emits a script tag with a | |
| 1766 | -** src=builtin/... to load the script. | |
| 1767 | -** | |
| 1768 | -** If asInline is true and addScripTag is true then the contents | |
| 1769 | -** are emitted directly but wrapped in a SCRIPT tag. If asInline | |
| 1770 | -** is false, addScriptTag is ignored. | |
| 1771 | -** | |
| 1772 | -** Note that this code relies on that loaded via | |
| 1773 | -** style_emit_script_fossil_bootstrap(), but it does not call that | |
| 1774 | -** routine. | |
| 1775 | -*/ | |
| 1776 | -void style_emit_script_dom(int asInline, int addScripTag){ | |
| 1777 | - static int once = 0; | |
| 1778 | - if(0==once++){ | |
| 1779 | - style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js"); | |
| 1780 | - } | |
| 1781 | -} | |
| 1782 | - | |
| 1783 | -/* | |
| 1784 | -** The fossil.tabs.js counterpart of style_emit_script_fetch(). | |
| 1785 | -** Also emits fossil.dom.js. | |
| 1786 | -*/ | |
| 1787 | -void style_emit_script_tabs(int asInline, int addScripTag){ | |
| 1788 | - static int once = 0; | |
| 1789 | - if(0==once++){ | |
| 1790 | - style_emit_script_dom(asInline, addScripTag); | |
| 1791 | - style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js"); | |
| 1792 | - } | |
| 1793 | -} | |
| 1794 | - | |
| 1795 | -/* | |
| 1796 | -** The fossil.confirmer.js counterpart of style_emit_script_fetch(). | |
| 1797 | -*/ | |
| 1798 | -void style_emit_script_confirmer(int asInline, int addScripTag){ | |
| 1799 | - static int once = 0; | |
| 1800 | - if(0==once++){ | |
| 1801 | - style_emit_script_builtin(asInline, 0, "fossil.confirmer.js"); | |
| 1802 | - } | |
| 1513 | +** Convenience wrapper which calls builtin_request_js() for a series | |
| 1514 | +** of builtin scripts named fossil.NAME.js. The first time it is | |
| 1515 | +** called, it also calls style_emit_script_fossil_bootstrap() to | |
| 1516 | +** initialize the window.fossil JS API. The first argument is a | |
| 1517 | +** no-meaning dummy required by the va_start() interface. All | |
| 1518 | +** subsequent arguments must be strings of the NAME part of | |
| 1519 | +** fossil.NAME.js, followed by a NULL argument to terminate the list. | |
| 1520 | +** | |
| 1521 | +** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3 | |
| 1522 | +** APIs. Do not forget the trailing 0! | |
| 1523 | +*/ | |
| 1524 | +void style_emit_fossil_js_apis( int dummy, ... ) { | |
| 1525 | + static int once = 0; | |
| 1526 | + const char *zArg; | |
| 1527 | + char * zName; | |
| 1528 | + va_list vargs; | |
| 1529 | + | |
| 1530 | + if(0==once++){ | |
| 1531 | + style_emit_script_fossil_bootstrap(1); | |
| 1532 | + } | |
| 1533 | + va_start(vargs,dummy); | |
| 1534 | + while( (zArg = va_arg (vargs, const char *))!=0 ){ | |
| 1535 | + zName = mprintf("fossil.%s.js", zArg); | |
| 1536 | + builtin_request_js(zName); | |
| 1537 | + fossil_free(zName); | |
| 1538 | + } | |
| 1539 | + va_end(vargs); | |
| 1803 | 1540 | } |
| 1804 | 1541 |
| --- 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 ){ |
| @@ -1127,109 +1051,10 @@ | |
| 1127 | |
| 1128 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 1129 | g.isConst = 1; |
| 1130 | } |
| 1131 | |
| 1132 | /* |
| 1133 | ** Maps a "bundle" name to a callback which emits the text of that |
| 1134 | ** bundle. For use in consolidating scripts for certain pages into a |
| 1135 | ** single cacheable request. |
| 1136 | */ |
| 1137 | typedef struct { |
| 1138 | const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */ |
| 1139 | void (*xEmit)(void); /* Emits amalgamated text output for this |
| 1140 | bundle */ |
| 1141 | } BundleEmitter; |
| 1142 | /* |
| 1143 | ** Map each required bundle here... |
| 1144 | */ |
| 1145 | static const BundleEmitter BundleEmitters[] = { |
| 1146 | /* Keep these sorted for bsearch() */ |
| 1147 | {"fileedit.js", fileedit_emit_js_bundle}, |
| 1148 | {"forum.js", forumpost_emit_js_bundle}, |
| 1149 | {"wikiedit.js", wikiedit_emit_js_bundle} |
| 1150 | }; |
| 1151 | |
| 1152 | /* |
| 1153 | ** Comparison function for bsearch() for searching a BundleEmitter |
| 1154 | ** list for a matching name. |
| 1155 | */ |
| 1156 | static int cmp_builtin_bundle_name(const void *a, const void *b){ |
| 1157 | const BundleEmitter * rA = (const BundleEmitter*)a; |
| 1158 | const BundleEmitter * rB = (const BundleEmitter*)b; |
| 1159 | return fossil_strcmp(rA->zName, rB->zName); |
| 1160 | } |
| 1161 | |
| 1162 | /* |
| 1163 | ** Internal helper for /builtin/FILENAME for dispatching "bundles" |
| 1164 | ** of amalgamated text (primarily JS) code. |
| 1165 | ** |
| 1166 | ** Returns true if it finds a bundle matcing the given name, else |
| 1167 | ** false. On success it outputs the amalgamated bundle without any |
| 1168 | ** sort of wrapper, e.g. SCRIPT tag |
| 1169 | */ |
| 1170 | static int page_builtin_text_bundle(const char * zFilename){ |
| 1171 | const BundleEmitter * pBH; |
| 1172 | BundleEmitter needle = {zFilename, 0}; |
| 1173 | |
| 1174 | pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters, |
| 1175 | count(BundleEmitters), |
| 1176 | sizeof BundleEmitters[0], |
| 1177 | cmp_builtin_bundle_name); |
| 1178 | if(pBH!=0){ |
| 1179 | pBH->xEmit(); |
| 1180 | } |
| 1181 | return pBH!=0; |
| 1182 | } |
| 1183 | |
| 1184 | /* |
| 1185 | ** WEBPAGE: builtin |
| 1186 | ** URL: builtin/FILENAME |
| 1187 | ** |
| 1188 | ** Return the built-in text given by FILENAME. This is used internally |
| 1189 | ** by many Fossil web pages to load built-in javascript files. |
| 1190 | ** |
| 1191 | ** If the id= parameter is present, then Fossil assumes that the |
| 1192 | ** result is immutable and sets a very large cache retention time (1 |
| 1193 | ** year). |
| 1194 | */ |
| 1195 | void page_builtin_text(void){ |
| 1196 | Blob out; |
| 1197 | const char *zName = P("name"); |
| 1198 | const char *zTxt = 0; |
| 1199 | const char *zId = P("id"); |
| 1200 | int nId; |
| 1201 | int isBundle = 0; |
| 1202 | |
| 1203 | if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){ |
| 1204 | g.isConst = 1; |
| 1205 | }else{ |
| 1206 | etag_check(0,0)/*might not return*/; |
| 1207 | } |
| 1208 | if( zName ){ |
| 1209 | if( sqlite3_strglob("*.js", zName)==0 ){ |
| 1210 | cgi_set_content_type("application/javascript"); |
| 1211 | }else{ |
| 1212 | cgi_set_content_type("text/plain"); |
| 1213 | } |
| 1214 | if(':'==zName[0]){ |
| 1215 | isBundle = 1; |
| 1216 | zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL; |
| 1217 | }else{ |
| 1218 | zTxt = builtin_text(zName); |
| 1219 | } |
| 1220 | } |
| 1221 | if( zTxt==0 ){ |
| 1222 | cgi_set_content_type("text/html"); |
| 1223 | cgi_set_status(404, "Not Found"); |
| 1224 | @ File "%h(zName)" not found |
| 1225 | }else if(isBundle==0){ |
| 1226 | blob_init(&out, zTxt, -1); |
| 1227 | cgi_set_content(&out); |
| 1228 | } |
| 1229 | } |
| 1230 | |
| 1231 | /* |
| 1232 | ** All possible capabilities |
| 1233 | */ |
| 1234 | static const char allCap[] = |
| 1235 | "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL"; |
| @@ -1605,21 +1430,18 @@ | |
| 1605 | ** 1) window.fossil core object, some of which depends on C-lelel |
| 1606 | ** runtime data. That part of the script is always emitted inline. If |
| 1607 | ** addScripTag is true then it is wrapped in its own SCRIPT tag, else |
| 1608 | ** it is assumed that the caller already opened a tag. |
| 1609 | ** |
| 1610 | ** 2) Emits the static fossil.bootstrap.js. If asInline is true then |
| 1611 | ** it is emitted inline with the components from (1), else it is |
| 1612 | ** emitted as a separate SCRIPT tag with |
| 1613 | ** src=/builtin/fossil.bootstrap.js (so causes another HTTP request). |
| 1614 | */ |
| 1615 | void style_emit_script_fossil_bootstrap(int asInline){ |
| 1616 | static int once = 0; |
| 1617 | if(0==once++){ |
| 1618 | /* Set up the generic/app-agnostic parts of window.fossil |
| 1619 | ** which require C-level state... */ |
| 1620 | if(asInline==0){ |
| 1621 | style_emit_script_tag(0,0); |
| 1622 | } |
| 1623 | CX("(function(){\n" |
| 1624 | "if(!window.fossil) window.fossil={};\n" |
| 1625 | "window.fossil.version = %!j;\n" |
| @@ -1646,18 +1468,16 @@ | |
| 1646 | */ |
| 1647 | CX("window.fossil.page = {" |
| 1648 | "name:\"%T\"" |
| 1649 | "};\n", g.zPath); |
| 1650 | CX("})();\n"); |
| 1651 | /* The remaining fossil object bootstrap code is not dependent on |
| 1652 | ** C-runtime state... */ |
| 1653 | if(asInline!=0){ |
| 1654 | CX("%s\n", builtin_text("fossil.bootstrap.js")); |
| 1655 | }else{ |
| 1656 | style_emit_script_tag(1,0); |
| 1657 | style_emit_script_builtin(0,1,"fossil.bootstrap.js"); |
| 1658 | } |
| 1659 | } |
| 1660 | } |
| 1661 | |
| 1662 | /* |
| 1663 | ** If passed 0 as its first argument, it emits a script opener tag |
| @@ -1688,116 +1508,33 @@ | |
| 1688 | CX("</script>\n"); |
| 1689 | } |
| 1690 | } |
| 1691 | |
| 1692 | /* |
| 1693 | ** Emits a script tag which uses content from a builtin script file. |
| 1694 | ** |
| 1695 | ** If asInline is false, the script is emitted as a SCRIPT tag with a |
| 1696 | ** src attribute of /builtin/zName and the 2nd parameter is |
| 1697 | ** ignored. If asInline is true then the contents of the script are |
| 1698 | ** emitted directly, with a wrapping SCRIPT tag if addScripTag is |
| 1699 | ** true, else no wrapping script tag.. |
| 1700 | ** |
| 1701 | ** If it is false, a script tag loading it via |
| 1702 | ** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a |
| 1703 | ** build-time-dependent cache-buster value. |
| 1704 | */ |
| 1705 | void style_emit_script_builtin(int asInline, int addScripTag, |
| 1706 | char const * zName){ |
| 1707 | if(asInline){ |
| 1708 | if(addScripTag){ |
| 1709 | style_emit_script_tag(0,0); |
| 1710 | } |
| 1711 | CX("%s", builtin_text(zName)); |
| 1712 | if(addScripTag){ |
| 1713 | style_emit_script_tag(1,0); |
| 1714 | } |
| 1715 | }else{ |
| 1716 | char * zFullName = mprintf("builtin/%s",zName); |
| 1717 | const char * zHash = fossil_exe_id(); |
| 1718 | CX("<script src='%R/%T?cache=%.8s'></script>\n", |
| 1719 | zFullName, zHash); |
| 1720 | fossil_free(zFullName); |
| 1721 | } |
| 1722 | } |
| 1723 | |
| 1724 | /* |
| 1725 | ** A convenience wrapper arond style_emit_script_builtin() which |
| 1726 | ** prepends a ':' to zName and passes (0,0,newName) to that |
| 1727 | ** function. i.e. it emits a SCRIPT tag with |
| 1728 | ** src=.../builtin/:${zName}?cache=.... The given name is assumed to |
| 1729 | ** have been added to the style.c:BundleEmitters map. |
| 1730 | */ |
| 1731 | void style_emit_script_bundle(char const * zName){ |
| 1732 | char *zBundle = mprintf(":%s", zName); |
| 1733 | style_emit_script_builtin(0, 0, zBundle); |
| 1734 | fossil_free(zBundle); |
| 1735 | } |
| 1736 | |
| 1737 | /* |
| 1738 | ** The first time this is called it emits the JS code from the |
| 1739 | ** built-in file fossil.fossil.js. Subsequent calls are no-ops. |
| 1740 | ** |
| 1741 | ** If passed a true first argument, it emits the contents directly |
| 1742 | ** to the page output, else it emits a script tag with a |
| 1743 | ** src=builtin/... to load the script. |
| 1744 | ** |
| 1745 | ** If asInline is true and addScripTag is true then the contents |
| 1746 | ** are emitted directly but wrapped in a SCRIPT tag. If asInline |
| 1747 | ** is false, addScriptTag is ignored. |
| 1748 | ** |
| 1749 | ** Note that this code relies on that loaded via |
| 1750 | ** style_emit_script_fossil_bootstrap() but it does not call that |
| 1751 | ** routine. |
| 1752 | */ |
| 1753 | void style_emit_script_fetch(int asInline, int addScripTag){ |
| 1754 | static int once = 0; |
| 1755 | if(0==once++){ |
| 1756 | style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js"); |
| 1757 | } |
| 1758 | } |
| 1759 | |
| 1760 | /* |
| 1761 | ** The first time this is called it emits the JS code from the |
| 1762 | ** built-in file fossil.dom.js. Subsequent calls are no-ops. |
| 1763 | ** |
| 1764 | ** If passed a true first argument, it emits the contents directly |
| 1765 | ** to the page output, else it emits a script tag with a |
| 1766 | ** src=builtin/... to load the script. |
| 1767 | ** |
| 1768 | ** If asInline is true and addScripTag is true then the contents |
| 1769 | ** are emitted directly but wrapped in a SCRIPT tag. If asInline |
| 1770 | ** is false, addScriptTag is ignored. |
| 1771 | ** |
| 1772 | ** Note that this code relies on that loaded via |
| 1773 | ** style_emit_script_fossil_bootstrap(), but it does not call that |
| 1774 | ** routine. |
| 1775 | */ |
| 1776 | void style_emit_script_dom(int asInline, int addScripTag){ |
| 1777 | static int once = 0; |
| 1778 | if(0==once++){ |
| 1779 | style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js"); |
| 1780 | } |
| 1781 | } |
| 1782 | |
| 1783 | /* |
| 1784 | ** The fossil.tabs.js counterpart of style_emit_script_fetch(). |
| 1785 | ** Also emits fossil.dom.js. |
| 1786 | */ |
| 1787 | void style_emit_script_tabs(int asInline, int addScripTag){ |
| 1788 | static int once = 0; |
| 1789 | if(0==once++){ |
| 1790 | style_emit_script_dom(asInline, addScripTag); |
| 1791 | style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js"); |
| 1792 | } |
| 1793 | } |
| 1794 | |
| 1795 | /* |
| 1796 | ** The fossil.confirmer.js counterpart of style_emit_script_fetch(). |
| 1797 | */ |
| 1798 | void style_emit_script_confirmer(int asInline, int addScripTag){ |
| 1799 | static int once = 0; |
| 1800 | if(0==once++){ |
| 1801 | style_emit_script_builtin(asInline, 0, "fossil.confirmer.js"); |
| 1802 | } |
| 1803 | } |
| 1804 |
| --- 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 ){ |
| @@ -1127,109 +1051,10 @@ | |
| 1051 | |
| 1052 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 1053 | g.isConst = 1; |
| 1054 | } |
| 1055 | |
| 1056 | /* |
| 1057 | ** All possible capabilities |
| 1058 | */ |
| 1059 | static const char allCap[] = |
| 1060 | "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL"; |
| @@ -1605,21 +1430,18 @@ | |
| 1430 | ** 1) window.fossil core object, some of which depends on C-lelel |
| 1431 | ** runtime data. That part of the script is always emitted inline. If |
| 1432 | ** addScripTag is true then it is wrapped in its own SCRIPT tag, else |
| 1433 | ** it is assumed that the caller already opened a tag. |
| 1434 | ** |
| 1435 | ** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). |
| 1436 | */ |
| 1437 | void style_emit_script_fossil_bootstrap(int addScriptTag){ |
| 1438 | static int once = 0; |
| 1439 | if(0==once++){ |
| 1440 | /* Set up the generic/app-agnostic parts of window.fossil |
| 1441 | ** which require C-level state... */ |
| 1442 | if(addScriptTag!=0){ |
| 1443 | style_emit_script_tag(0,0); |
| 1444 | } |
| 1445 | CX("(function(){\n" |
| 1446 | "if(!window.fossil) window.fossil={};\n" |
| 1447 | "window.fossil.version = %!j;\n" |
| @@ -1646,18 +1468,16 @@ | |
| 1468 | */ |
| 1469 | CX("window.fossil.page = {" |
| 1470 | "name:\"%T\"" |
| 1471 | "};\n", g.zPath); |
| 1472 | CX("})();\n"); |
| 1473 | if(addScriptTag!=0){ |
| 1474 | style_emit_script_tag(1,0); |
| 1475 | } |
| 1476 | /* The remaining window.fossil bootstrap code is not dependent on |
| 1477 | ** C-runtime state... */ |
| 1478 | builtin_request_js("fossil.bootstrap.js"); |
| 1479 | } |
| 1480 | } |
| 1481 | |
| 1482 | /* |
| 1483 | ** If passed 0 as its first argument, it emits a script opener tag |
| @@ -1688,116 +1508,33 @@ | |
| 1508 | CX("</script>\n"); |
| 1509 | } |
| 1510 | } |
| 1511 | |
| 1512 | /* |
| 1513 | ** Convenience wrapper which calls builtin_request_js() for a series |
| 1514 | ** of builtin scripts named fossil.NAME.js. The first time it is |
| 1515 | ** called, it also calls style_emit_script_fossil_bootstrap() to |
| 1516 | ** initialize the window.fossil JS API. The first argument is a |
| 1517 | ** no-meaning dummy required by the va_start() interface. All |
| 1518 | ** subsequent arguments must be strings of the NAME part of |
| 1519 | ** fossil.NAME.js, followed by a NULL argument to terminate the list. |
| 1520 | ** |
| 1521 | ** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3 |
| 1522 | ** APIs. Do not forget the trailing 0! |
| 1523 | */ |
| 1524 | void style_emit_fossil_js_apis( int dummy, ... ) { |
| 1525 | static int once = 0; |
| 1526 | const char *zArg; |
| 1527 | char * zName; |
| 1528 | va_list vargs; |
| 1529 | |
| 1530 | if(0==once++){ |
| 1531 | style_emit_script_fossil_bootstrap(1); |
| 1532 | } |
| 1533 | va_start(vargs,dummy); |
| 1534 | while( (zArg = va_arg (vargs, const char *))!=0 ){ |
| 1535 | zName = mprintf("fossil.%s.js", zArg); |
| 1536 | builtin_request_js(zName); |
| 1537 | fossil_free(zName); |
| 1538 | } |
| 1539 | va_end(vargs); |
| 1540 | } |
| 1541 |
+39
-302
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -88,14 +88,10 @@ | ||
| 88 | 88 | |
| 89 | 89 | /* |
| 90 | 90 | ** Flags for various javascript files needed prior to </body> |
| 91 | 91 | */ |
| 92 | 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 | 93 | |
| 98 | 94 | /* |
| 99 | 95 | ** Extra JS added to the end of the file. |
| 100 | 96 | */ |
| 101 | 97 | static Blob blobOnLoad = BLOB_INITIALIZER; |
| @@ -484,11 +480,11 @@ | ||
| 484 | 480 | zBtnFmt/*works-like:"%h%s%h%h%d"*/, |
| 485 | 481 | zTargetId,zText,zTargetId,zTargetId,cchLength); |
| 486 | 482 | } |
| 487 | 483 | } |
| 488 | 484 | free(zText); |
| 489 | - style_copybutton_control(); | |
| 485 | + builtin_request_js("copybtn.js"); | |
| 490 | 486 | return zResult; |
| 491 | 487 | } |
| 492 | 488 | |
| 493 | 489 | /* |
| 494 | 490 | ** Return a random nonce that is stored in static space. For a particular |
| @@ -694,66 +690,17 @@ | ||
| 694 | 690 | |
| 695 | 691 | /* |
| 696 | 692 | ** Indicate that the table-sorting javascript is needed. |
| 697 | 693 | */ |
| 698 | 694 | 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"); | |
| 748 | 696 | } |
| 749 | 697 | |
| 750 | 698 | /* |
| 751 | 699 | ** Generate code to load all required javascript files. |
| 752 | 700 | */ |
| 753 | 701 | static void style_load_all_js_files(void){ |
| 754 | - int i; | |
| 755 | 702 | if( needHrefJs ){ |
| 756 | 703 | int nDelay = db_get_int("auto-hyperlink-delay",0); |
| 757 | 704 | int bMouseover = db_get_boolean("auto-hyperlink-mouseover",0); |
| 758 | 705 | @ <script id='href-data' type='application/json'>\ |
| 759 | 706 | @ {"delay":%d(nDelay),"mouseover":%d(bMouseover)}</script> |
| @@ -762,43 +709,20 @@ | ||
| 762 | 709 | @ function debugMsg(msg){ |
| 763 | 710 | @ var n = document.getElementById("debugMsg"); |
| 764 | 711 | @ if(n){n.textContent=msg;} |
| 765 | 712 | @ } |
| 766 | 713 | if( needHrefJs ){ |
| 714 | + @ /* href.js */ | |
| 767 | 715 | cgi_append_content(builtin_text("href.js"),-1); |
| 768 | 716 | } |
| 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 | 717 | if( blob_size(&blobOnLoad)>0 ){ |
| 785 | 718 | @ window.onload = function(){ |
| 786 | 719 | cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad)); |
| 787 | 720 | cgi_append_content("\n}\n", -1); |
| 788 | 721 | } |
| 789 | 722 | @ </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(); | |
| 800 | 724 | } |
| 801 | 725 | |
| 802 | 726 | /* |
| 803 | 727 | ** Draw the footer at the bottom of the page. |
| 804 | 728 | */ |
| @@ -916,11 +840,11 @@ | ||
| 916 | 840 | @ </div> |
| 917 | 841 | if( nSubmenuCtrl ){ |
| 918 | 842 | cgi_query_parameters_to_hidden(); |
| 919 | 843 | cgi_tag_query_parameter(0); |
| 920 | 844 | @ </form> |
| 921 | - style_load_one_js_file("menu.js"); | |
| 845 | + builtin_request_js("menu.js"); | |
| 922 | 846 | } |
| 923 | 847 | } |
| 924 | 848 | |
| 925 | 849 | zAd = style_adunit_text(&mAdFlags); |
| 926 | 850 | if( (mAdFlags & ADUNIT_RIGHT_OK)!=0 ){ |
| @@ -1127,109 +1051,10 @@ | ||
| 1127 | 1051 | |
| 1128 | 1052 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 1129 | 1053 | g.isConst = 1; |
| 1130 | 1054 | } |
| 1131 | 1055 | |
| 1132 | -/* | |
| 1133 | -** Maps a "bundle" name to a callback which emits the text of that | |
| 1134 | -** bundle. For use in consolidating scripts for certain pages into a | |
| 1135 | -** single cacheable request. | |
| 1136 | -*/ | |
| 1137 | -typedef struct { | |
| 1138 | - const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */ | |
| 1139 | - void (*xEmit)(void); /* Emits amalgamated text output for this | |
| 1140 | - bundle */ | |
| 1141 | -} BundleEmitter; | |
| 1142 | -/* | |
| 1143 | -** Map each required bundle here... | |
| 1144 | -*/ | |
| 1145 | -static const BundleEmitter BundleEmitters[] = { | |
| 1146 | -/* Keep these sorted for bsearch() */ | |
| 1147 | -{"fileedit.js", fileedit_emit_js_bundle}, | |
| 1148 | -{"forum.js", forumpost_emit_js_bundle}, | |
| 1149 | -{"wikiedit.js", wikiedit_emit_js_bundle} | |
| 1150 | -}; | |
| 1151 | - | |
| 1152 | -/* | |
| 1153 | -** Comparison function for bsearch() for searching a BundleEmitter | |
| 1154 | -** list for a matching name. | |
| 1155 | -*/ | |
| 1156 | -static int cmp_builtin_bundle_name(const void *a, const void *b){ | |
| 1157 | - const BundleEmitter * rA = (const BundleEmitter*)a; | |
| 1158 | - const BundleEmitter * rB = (const BundleEmitter*)b; | |
| 1159 | - return fossil_strcmp(rA->zName, rB->zName); | |
| 1160 | -} | |
| 1161 | - | |
| 1162 | -/* | |
| 1163 | -** Internal helper for /builtin/FILENAME for dispatching "bundles" | |
| 1164 | -** of amalgamated text (primarily JS) code. | |
| 1165 | -** | |
| 1166 | -** Returns true if it finds a bundle matcing the given name, else | |
| 1167 | -** false. On success it outputs the amalgamated bundle without any | |
| 1168 | -** sort of wrapper, e.g. SCRIPT tag | |
| 1169 | -*/ | |
| 1170 | -static int page_builtin_text_bundle(const char * zFilename){ | |
| 1171 | - const BundleEmitter * pBH; | |
| 1172 | - BundleEmitter needle = {zFilename, 0}; | |
| 1173 | - | |
| 1174 | - pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters, | |
| 1175 | - count(BundleEmitters), | |
| 1176 | - sizeof BundleEmitters[0], | |
| 1177 | - cmp_builtin_bundle_name); | |
| 1178 | - if(pBH!=0){ | |
| 1179 | - pBH->xEmit(); | |
| 1180 | - } | |
| 1181 | - return pBH!=0; | |
| 1182 | -} | |
| 1183 | - | |
| 1184 | -/* | |
| 1185 | -** WEBPAGE: builtin | |
| 1186 | -** URL: builtin/FILENAME | |
| 1187 | -** | |
| 1188 | -** Return the built-in text given by FILENAME. This is used internally | |
| 1189 | -** by many Fossil web pages to load built-in javascript files. | |
| 1190 | -** | |
| 1191 | -** If the id= parameter is present, then Fossil assumes that the | |
| 1192 | -** result is immutable and sets a very large cache retention time (1 | |
| 1193 | -** year). | |
| 1194 | -*/ | |
| 1195 | -void page_builtin_text(void){ | |
| 1196 | - Blob out; | |
| 1197 | - const char *zName = P("name"); | |
| 1198 | - const char *zTxt = 0; | |
| 1199 | - const char *zId = P("id"); | |
| 1200 | - int nId; | |
| 1201 | - int isBundle = 0; | |
| 1202 | - | |
| 1203 | - if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){ | |
| 1204 | - g.isConst = 1; | |
| 1205 | - }else{ | |
| 1206 | - etag_check(0,0)/*might not return*/; | |
| 1207 | - } | |
| 1208 | - if( zName ){ | |
| 1209 | - if( sqlite3_strglob("*.js", zName)==0 ){ | |
| 1210 | - cgi_set_content_type("application/javascript"); | |
| 1211 | - }else{ | |
| 1212 | - cgi_set_content_type("text/plain"); | |
| 1213 | - } | |
| 1214 | - if(':'==zName[0]){ | |
| 1215 | - isBundle = 1; | |
| 1216 | - zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL; | |
| 1217 | - }else{ | |
| 1218 | - zTxt = builtin_text(zName); | |
| 1219 | - } | |
| 1220 | - } | |
| 1221 | - if( zTxt==0 ){ | |
| 1222 | - cgi_set_content_type("text/html"); | |
| 1223 | - cgi_set_status(404, "Not Found"); | |
| 1224 | - @ File "%h(zName)" not found | |
| 1225 | - }else if(isBundle==0){ | |
| 1226 | - blob_init(&out, zTxt, -1); | |
| 1227 | - cgi_set_content(&out); | |
| 1228 | - } | |
| 1229 | -} | |
| 1230 | - | |
| 1231 | 1056 | /* |
| 1232 | 1057 | ** All possible capabilities |
| 1233 | 1058 | */ |
| 1234 | 1059 | static const char allCap[] = |
| 1235 | 1060 | "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL"; |
| @@ -1605,21 +1430,18 @@ | ||
| 1605 | 1430 | ** 1) window.fossil core object, some of which depends on C-lelel |
| 1606 | 1431 | ** runtime data. That part of the script is always emitted inline. If |
| 1607 | 1432 | ** addScripTag is true then it is wrapped in its own SCRIPT tag, else |
| 1608 | 1433 | ** it is assumed that the caller already opened a tag. |
| 1609 | 1434 | ** |
| 1610 | -** 2) Emits the static fossil.bootstrap.js. If asInline is true then | |
| 1611 | -** it is emitted inline with the components from (1), else it is | |
| 1612 | -** emitted as a separate SCRIPT tag with | |
| 1613 | -** src=/builtin/fossil.bootstrap.js (so causes another HTTP request). | |
| 1435 | +** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). | |
| 1614 | 1436 | */ |
| 1615 | -void style_emit_script_fossil_bootstrap(int asInline){ | |
| 1437 | +void style_emit_script_fossil_bootstrap(int addScriptTag){ | |
| 1616 | 1438 | static int once = 0; |
| 1617 | 1439 | if(0==once++){ |
| 1618 | 1440 | /* Set up the generic/app-agnostic parts of window.fossil |
| 1619 | 1441 | ** which require C-level state... */ |
| 1620 | - if(asInline==0){ | |
| 1442 | + if(addScriptTag!=0){ | |
| 1621 | 1443 | style_emit_script_tag(0,0); |
| 1622 | 1444 | } |
| 1623 | 1445 | CX("(function(){\n" |
| 1624 | 1446 | "if(!window.fossil) window.fossil={};\n" |
| 1625 | 1447 | "window.fossil.version = %!j;\n" |
| @@ -1646,18 +1468,16 @@ | ||
| 1646 | 1468 | */ |
| 1647 | 1469 | CX("window.fossil.page = {" |
| 1648 | 1470 | "name:\"%T\"" |
| 1649 | 1471 | "};\n", g.zPath); |
| 1650 | 1472 | CX("})();\n"); |
| 1651 | - /* The remaining fossil object bootstrap code is not dependent on | |
| 1652 | - ** C-runtime state... */ | |
| 1653 | - if(asInline!=0){ | |
| 1654 | - CX("%s\n", builtin_text("fossil.bootstrap.js")); | |
| 1655 | - }else{ | |
| 1473 | + if(addScriptTag!=0){ | |
| 1656 | 1474 | style_emit_script_tag(1,0); |
| 1657 | - style_emit_script_builtin(0,1,"fossil.bootstrap.js"); | |
| 1658 | 1475 | } |
| 1476 | + /* The remaining window.fossil bootstrap code is not dependent on | |
| 1477 | + ** C-runtime state... */ | |
| 1478 | + builtin_request_js("fossil.bootstrap.js"); | |
| 1659 | 1479 | } |
| 1660 | 1480 | } |
| 1661 | 1481 | |
| 1662 | 1482 | /* |
| 1663 | 1483 | ** If passed 0 as its first argument, it emits a script opener tag |
| @@ -1688,116 +1508,33 @@ | ||
| 1688 | 1508 | CX("</script>\n"); |
| 1689 | 1509 | } |
| 1690 | 1510 | } |
| 1691 | 1511 | |
| 1692 | 1512 | /* |
| 1693 | -** Emits a script tag which uses content from a builtin script file. | |
| 1694 | -** | |
| 1695 | -** If asInline is false, the script is emitted as a SCRIPT tag with a | |
| 1696 | -** src attribute of /builtin/zName and the 2nd parameter is | |
| 1697 | -** ignored. If asInline is true then the contents of the script are | |
| 1698 | -** emitted directly, with a wrapping SCRIPT tag if addScripTag is | |
| 1699 | -** true, else no wrapping script tag.. | |
| 1700 | -** | |
| 1701 | -** If it is false, a script tag loading it via | |
| 1702 | -** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a | |
| 1703 | -** build-time-dependent cache-buster value. | |
| 1704 | -*/ | |
| 1705 | -void style_emit_script_builtin(int asInline, int addScripTag, | |
| 1706 | - char const * zName){ | |
| 1707 | - if(asInline){ | |
| 1708 | - if(addScripTag){ | |
| 1709 | - style_emit_script_tag(0,0); | |
| 1710 | - } | |
| 1711 | - CX("%s", builtin_text(zName)); | |
| 1712 | - if(addScripTag){ | |
| 1713 | - style_emit_script_tag(1,0); | |
| 1714 | - } | |
| 1715 | - }else{ | |
| 1716 | - char * zFullName = mprintf("builtin/%s",zName); | |
| 1717 | - const char * zHash = fossil_exe_id(); | |
| 1718 | - CX("<script src='%R/%T?cache=%.8s'></script>\n", | |
| 1719 | - zFullName, zHash); | |
| 1720 | - fossil_free(zFullName); | |
| 1721 | - } | |
| 1722 | -} | |
| 1723 | - | |
| 1724 | -/* | |
| 1725 | -** A convenience wrapper arond style_emit_script_builtin() which | |
| 1726 | -** prepends a ':' to zName and passes (0,0,newName) to that | |
| 1727 | -** function. i.e. it emits a SCRIPT tag with | |
| 1728 | -** src=.../builtin/:${zName}?cache=.... The given name is assumed to | |
| 1729 | -** have been added to the style.c:BundleEmitters map. | |
| 1730 | -*/ | |
| 1731 | -void style_emit_script_bundle(char const * zName){ | |
| 1732 | - char *zBundle = mprintf(":%s", zName); | |
| 1733 | - style_emit_script_builtin(0, 0, zBundle); | |
| 1734 | - fossil_free(zBundle); | |
| 1735 | -} | |
| 1736 | - | |
| 1737 | -/* | |
| 1738 | -** The first time this is called it emits the JS code from the | |
| 1739 | -** built-in file fossil.fossil.js. Subsequent calls are no-ops. | |
| 1740 | -** | |
| 1741 | -** If passed a true first argument, it emits the contents directly | |
| 1742 | -** to the page output, else it emits a script tag with a | |
| 1743 | -** src=builtin/... to load the script. | |
| 1744 | -** | |
| 1745 | -** If asInline is true and addScripTag is true then the contents | |
| 1746 | -** are emitted directly but wrapped in a SCRIPT tag. If asInline | |
| 1747 | -** is false, addScriptTag is ignored. | |
| 1748 | -** | |
| 1749 | -** Note that this code relies on that loaded via | |
| 1750 | -** style_emit_script_fossil_bootstrap() but it does not call that | |
| 1751 | -** routine. | |
| 1752 | -*/ | |
| 1753 | -void style_emit_script_fetch(int asInline, int addScripTag){ | |
| 1754 | - static int once = 0; | |
| 1755 | - if(0==once++){ | |
| 1756 | - style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js"); | |
| 1757 | - } | |
| 1758 | -} | |
| 1759 | - | |
| 1760 | -/* | |
| 1761 | -** The first time this is called it emits the JS code from the | |
| 1762 | -** built-in file fossil.dom.js. Subsequent calls are no-ops. | |
| 1763 | -** | |
| 1764 | -** If passed a true first argument, it emits the contents directly | |
| 1765 | -** to the page output, else it emits a script tag with a | |
| 1766 | -** src=builtin/... to load the script. | |
| 1767 | -** | |
| 1768 | -** If asInline is true and addScripTag is true then the contents | |
| 1769 | -** are emitted directly but wrapped in a SCRIPT tag. If asInline | |
| 1770 | -** is false, addScriptTag is ignored. | |
| 1771 | -** | |
| 1772 | -** Note that this code relies on that loaded via | |
| 1773 | -** style_emit_script_fossil_bootstrap(), but it does not call that | |
| 1774 | -** routine. | |
| 1775 | -*/ | |
| 1776 | -void style_emit_script_dom(int asInline, int addScripTag){ | |
| 1777 | - static int once = 0; | |
| 1778 | - if(0==once++){ | |
| 1779 | - style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js"); | |
| 1780 | - } | |
| 1781 | -} | |
| 1782 | - | |
| 1783 | -/* | |
| 1784 | -** The fossil.tabs.js counterpart of style_emit_script_fetch(). | |
| 1785 | -** Also emits fossil.dom.js. | |
| 1786 | -*/ | |
| 1787 | -void style_emit_script_tabs(int asInline, int addScripTag){ | |
| 1788 | - static int once = 0; | |
| 1789 | - if(0==once++){ | |
| 1790 | - style_emit_script_dom(asInline, addScripTag); | |
| 1791 | - style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js"); | |
| 1792 | - } | |
| 1793 | -} | |
| 1794 | - | |
| 1795 | -/* | |
| 1796 | -** The fossil.confirmer.js counterpart of style_emit_script_fetch(). | |
| 1797 | -*/ | |
| 1798 | -void style_emit_script_confirmer(int asInline, int addScripTag){ | |
| 1799 | - static int once = 0; | |
| 1800 | - if(0==once++){ | |
| 1801 | - style_emit_script_builtin(asInline, 0, "fossil.confirmer.js"); | |
| 1802 | - } | |
| 1513 | +** Convenience wrapper which calls builtin_request_js() for a series | |
| 1514 | +** of builtin scripts named fossil.NAME.js. The first time it is | |
| 1515 | +** called, it also calls style_emit_script_fossil_bootstrap() to | |
| 1516 | +** initialize the window.fossil JS API. The first argument is a | |
| 1517 | +** no-meaning dummy required by the va_start() interface. All | |
| 1518 | +** subsequent arguments must be strings of the NAME part of | |
| 1519 | +** fossil.NAME.js, followed by a NULL argument to terminate the list. | |
| 1520 | +** | |
| 1521 | +** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3 | |
| 1522 | +** APIs. Do not forget the trailing 0! | |
| 1523 | +*/ | |
| 1524 | +void style_emit_fossil_js_apis( int dummy, ... ) { | |
| 1525 | + static int once = 0; | |
| 1526 | + const char *zArg; | |
| 1527 | + char * zName; | |
| 1528 | + va_list vargs; | |
| 1529 | + | |
| 1530 | + if(0==once++){ | |
| 1531 | + style_emit_script_fossil_bootstrap(1); | |
| 1532 | + } | |
| 1533 | + va_start(vargs,dummy); | |
| 1534 | + while( (zArg = va_arg (vargs, const char *))!=0 ){ | |
| 1535 | + zName = mprintf("fossil.%s.js", zArg); | |
| 1536 | + builtin_request_js(zName); | |
| 1537 | + fossil_free(zName); | |
| 1538 | + } | |
| 1539 | + va_end(vargs); | |
| 1803 | 1540 | } |
| 1804 | 1541 |
| --- 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 ){ |
| @@ -1127,109 +1051,10 @@ | |
| 1127 | |
| 1128 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 1129 | g.isConst = 1; |
| 1130 | } |
| 1131 | |
| 1132 | /* |
| 1133 | ** Maps a "bundle" name to a callback which emits the text of that |
| 1134 | ** bundle. For use in consolidating scripts for certain pages into a |
| 1135 | ** single cacheable request. |
| 1136 | */ |
| 1137 | typedef struct { |
| 1138 | const char * zName; /* Name of the bundle (maps to /builtin/:NAME) */ |
| 1139 | void (*xEmit)(void); /* Emits amalgamated text output for this |
| 1140 | bundle */ |
| 1141 | } BundleEmitter; |
| 1142 | /* |
| 1143 | ** Map each required bundle here... |
| 1144 | */ |
| 1145 | static const BundleEmitter BundleEmitters[] = { |
| 1146 | /* Keep these sorted for bsearch() */ |
| 1147 | {"fileedit.js", fileedit_emit_js_bundle}, |
| 1148 | {"forum.js", forumpost_emit_js_bundle}, |
| 1149 | {"wikiedit.js", wikiedit_emit_js_bundle} |
| 1150 | }; |
| 1151 | |
| 1152 | /* |
| 1153 | ** Comparison function for bsearch() for searching a BundleEmitter |
| 1154 | ** list for a matching name. |
| 1155 | */ |
| 1156 | static int cmp_builtin_bundle_name(const void *a, const void *b){ |
| 1157 | const BundleEmitter * rA = (const BundleEmitter*)a; |
| 1158 | const BundleEmitter * rB = (const BundleEmitter*)b; |
| 1159 | return fossil_strcmp(rA->zName, rB->zName); |
| 1160 | } |
| 1161 | |
| 1162 | /* |
| 1163 | ** Internal helper for /builtin/FILENAME for dispatching "bundles" |
| 1164 | ** of amalgamated text (primarily JS) code. |
| 1165 | ** |
| 1166 | ** Returns true if it finds a bundle matcing the given name, else |
| 1167 | ** false. On success it outputs the amalgamated bundle without any |
| 1168 | ** sort of wrapper, e.g. SCRIPT tag |
| 1169 | */ |
| 1170 | static int page_builtin_text_bundle(const char * zFilename){ |
| 1171 | const BundleEmitter * pBH; |
| 1172 | BundleEmitter needle = {zFilename, 0}; |
| 1173 | |
| 1174 | pBH = (const BundleEmitter *)bsearch(&needle, BundleEmitters, |
| 1175 | count(BundleEmitters), |
| 1176 | sizeof BundleEmitters[0], |
| 1177 | cmp_builtin_bundle_name); |
| 1178 | if(pBH!=0){ |
| 1179 | pBH->xEmit(); |
| 1180 | } |
| 1181 | return pBH!=0; |
| 1182 | } |
| 1183 | |
| 1184 | /* |
| 1185 | ** WEBPAGE: builtin |
| 1186 | ** URL: builtin/FILENAME |
| 1187 | ** |
| 1188 | ** Return the built-in text given by FILENAME. This is used internally |
| 1189 | ** by many Fossil web pages to load built-in javascript files. |
| 1190 | ** |
| 1191 | ** If the id= parameter is present, then Fossil assumes that the |
| 1192 | ** result is immutable and sets a very large cache retention time (1 |
| 1193 | ** year). |
| 1194 | */ |
| 1195 | void page_builtin_text(void){ |
| 1196 | Blob out; |
| 1197 | const char *zName = P("name"); |
| 1198 | const char *zTxt = 0; |
| 1199 | const char *zId = P("id"); |
| 1200 | int nId; |
| 1201 | int isBundle = 0; |
| 1202 | |
| 1203 | if( zId && (nId = (int)strlen(zId))>=8 && strncmp(zId,MANIFEST_UUID,nId)==0 ){ |
| 1204 | g.isConst = 1; |
| 1205 | }else{ |
| 1206 | etag_check(0,0)/*might not return*/; |
| 1207 | } |
| 1208 | if( zName ){ |
| 1209 | if( sqlite3_strglob("*.js", zName)==0 ){ |
| 1210 | cgi_set_content_type("application/javascript"); |
| 1211 | }else{ |
| 1212 | cgi_set_content_type("text/plain"); |
| 1213 | } |
| 1214 | if(':'==zName[0]){ |
| 1215 | isBundle = 1; |
| 1216 | zTxt = page_builtin_text_bundle(zName+1) ? "" : NULL; |
| 1217 | }else{ |
| 1218 | zTxt = builtin_text(zName); |
| 1219 | } |
| 1220 | } |
| 1221 | if( zTxt==0 ){ |
| 1222 | cgi_set_content_type("text/html"); |
| 1223 | cgi_set_status(404, "Not Found"); |
| 1224 | @ File "%h(zName)" not found |
| 1225 | }else if(isBundle==0){ |
| 1226 | blob_init(&out, zTxt, -1); |
| 1227 | cgi_set_content(&out); |
| 1228 | } |
| 1229 | } |
| 1230 | |
| 1231 | /* |
| 1232 | ** All possible capabilities |
| 1233 | */ |
| 1234 | static const char allCap[] = |
| 1235 | "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL"; |
| @@ -1605,21 +1430,18 @@ | |
| 1605 | ** 1) window.fossil core object, some of which depends on C-lelel |
| 1606 | ** runtime data. That part of the script is always emitted inline. If |
| 1607 | ** addScripTag is true then it is wrapped in its own SCRIPT tag, else |
| 1608 | ** it is assumed that the caller already opened a tag. |
| 1609 | ** |
| 1610 | ** 2) Emits the static fossil.bootstrap.js. If asInline is true then |
| 1611 | ** it is emitted inline with the components from (1), else it is |
| 1612 | ** emitted as a separate SCRIPT tag with |
| 1613 | ** src=/builtin/fossil.bootstrap.js (so causes another HTTP request). |
| 1614 | */ |
| 1615 | void style_emit_script_fossil_bootstrap(int asInline){ |
| 1616 | static int once = 0; |
| 1617 | if(0==once++){ |
| 1618 | /* Set up the generic/app-agnostic parts of window.fossil |
| 1619 | ** which require C-level state... */ |
| 1620 | if(asInline==0){ |
| 1621 | style_emit_script_tag(0,0); |
| 1622 | } |
| 1623 | CX("(function(){\n" |
| 1624 | "if(!window.fossil) window.fossil={};\n" |
| 1625 | "window.fossil.version = %!j;\n" |
| @@ -1646,18 +1468,16 @@ | |
| 1646 | */ |
| 1647 | CX("window.fossil.page = {" |
| 1648 | "name:\"%T\"" |
| 1649 | "};\n", g.zPath); |
| 1650 | CX("})();\n"); |
| 1651 | /* The remaining fossil object bootstrap code is not dependent on |
| 1652 | ** C-runtime state... */ |
| 1653 | if(asInline!=0){ |
| 1654 | CX("%s\n", builtin_text("fossil.bootstrap.js")); |
| 1655 | }else{ |
| 1656 | style_emit_script_tag(1,0); |
| 1657 | style_emit_script_builtin(0,1,"fossil.bootstrap.js"); |
| 1658 | } |
| 1659 | } |
| 1660 | } |
| 1661 | |
| 1662 | /* |
| 1663 | ** If passed 0 as its first argument, it emits a script opener tag |
| @@ -1688,116 +1508,33 @@ | |
| 1688 | CX("</script>\n"); |
| 1689 | } |
| 1690 | } |
| 1691 | |
| 1692 | /* |
| 1693 | ** Emits a script tag which uses content from a builtin script file. |
| 1694 | ** |
| 1695 | ** If asInline is false, the script is emitted as a SCRIPT tag with a |
| 1696 | ** src attribute of /builtin/zName and the 2nd parameter is |
| 1697 | ** ignored. If asInline is true then the contents of the script are |
| 1698 | ** emitted directly, with a wrapping SCRIPT tag if addScripTag is |
| 1699 | ** true, else no wrapping script tag.. |
| 1700 | ** |
| 1701 | ** If it is false, a script tag loading it via |
| 1702 | ** src=builtin/{{zName}}?cache=XYZ is emitted, where XYZ is a |
| 1703 | ** build-time-dependent cache-buster value. |
| 1704 | */ |
| 1705 | void style_emit_script_builtin(int asInline, int addScripTag, |
| 1706 | char const * zName){ |
| 1707 | if(asInline){ |
| 1708 | if(addScripTag){ |
| 1709 | style_emit_script_tag(0,0); |
| 1710 | } |
| 1711 | CX("%s", builtin_text(zName)); |
| 1712 | if(addScripTag){ |
| 1713 | style_emit_script_tag(1,0); |
| 1714 | } |
| 1715 | }else{ |
| 1716 | char * zFullName = mprintf("builtin/%s",zName); |
| 1717 | const char * zHash = fossil_exe_id(); |
| 1718 | CX("<script src='%R/%T?cache=%.8s'></script>\n", |
| 1719 | zFullName, zHash); |
| 1720 | fossil_free(zFullName); |
| 1721 | } |
| 1722 | } |
| 1723 | |
| 1724 | /* |
| 1725 | ** A convenience wrapper arond style_emit_script_builtin() which |
| 1726 | ** prepends a ':' to zName and passes (0,0,newName) to that |
| 1727 | ** function. i.e. it emits a SCRIPT tag with |
| 1728 | ** src=.../builtin/:${zName}?cache=.... The given name is assumed to |
| 1729 | ** have been added to the style.c:BundleEmitters map. |
| 1730 | */ |
| 1731 | void style_emit_script_bundle(char const * zName){ |
| 1732 | char *zBundle = mprintf(":%s", zName); |
| 1733 | style_emit_script_builtin(0, 0, zBundle); |
| 1734 | fossil_free(zBundle); |
| 1735 | } |
| 1736 | |
| 1737 | /* |
| 1738 | ** The first time this is called it emits the JS code from the |
| 1739 | ** built-in file fossil.fossil.js. Subsequent calls are no-ops. |
| 1740 | ** |
| 1741 | ** If passed a true first argument, it emits the contents directly |
| 1742 | ** to the page output, else it emits a script tag with a |
| 1743 | ** src=builtin/... to load the script. |
| 1744 | ** |
| 1745 | ** If asInline is true and addScripTag is true then the contents |
| 1746 | ** are emitted directly but wrapped in a SCRIPT tag. If asInline |
| 1747 | ** is false, addScriptTag is ignored. |
| 1748 | ** |
| 1749 | ** Note that this code relies on that loaded via |
| 1750 | ** style_emit_script_fossil_bootstrap() but it does not call that |
| 1751 | ** routine. |
| 1752 | */ |
| 1753 | void style_emit_script_fetch(int asInline, int addScripTag){ |
| 1754 | static int once = 0; |
| 1755 | if(0==once++){ |
| 1756 | style_emit_script_builtin(asInline, addScripTag, "fossil.fetch.js"); |
| 1757 | } |
| 1758 | } |
| 1759 | |
| 1760 | /* |
| 1761 | ** The first time this is called it emits the JS code from the |
| 1762 | ** built-in file fossil.dom.js. Subsequent calls are no-ops. |
| 1763 | ** |
| 1764 | ** If passed a true first argument, it emits the contents directly |
| 1765 | ** to the page output, else it emits a script tag with a |
| 1766 | ** src=builtin/... to load the script. |
| 1767 | ** |
| 1768 | ** If asInline is true and addScripTag is true then the contents |
| 1769 | ** are emitted directly but wrapped in a SCRIPT tag. If asInline |
| 1770 | ** is false, addScriptTag is ignored. |
| 1771 | ** |
| 1772 | ** Note that this code relies on that loaded via |
| 1773 | ** style_emit_script_fossil_bootstrap(), but it does not call that |
| 1774 | ** routine. |
| 1775 | */ |
| 1776 | void style_emit_script_dom(int asInline, int addScripTag){ |
| 1777 | static int once = 0; |
| 1778 | if(0==once++){ |
| 1779 | style_emit_script_builtin(asInline, addScripTag, "fossil.dom.js"); |
| 1780 | } |
| 1781 | } |
| 1782 | |
| 1783 | /* |
| 1784 | ** The fossil.tabs.js counterpart of style_emit_script_fetch(). |
| 1785 | ** Also emits fossil.dom.js. |
| 1786 | */ |
| 1787 | void style_emit_script_tabs(int asInline, int addScripTag){ |
| 1788 | static int once = 0; |
| 1789 | if(0==once++){ |
| 1790 | style_emit_script_dom(asInline, addScripTag); |
| 1791 | style_emit_script_builtin(asInline, addScripTag, "fossil.tabs.js"); |
| 1792 | } |
| 1793 | } |
| 1794 | |
| 1795 | /* |
| 1796 | ** The fossil.confirmer.js counterpart of style_emit_script_fetch(). |
| 1797 | */ |
| 1798 | void style_emit_script_confirmer(int asInline, int addScripTag){ |
| 1799 | static int once = 0; |
| 1800 | if(0==once++){ |
| 1801 | style_emit_script_builtin(asInline, 0, "fossil.confirmer.js"); |
| 1802 | } |
| 1803 | } |
| 1804 |
| --- 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 ){ |
| @@ -1127,109 +1051,10 @@ | |
| 1051 | |
| 1052 | /* Tell CGI that the content returned by this page is considered cacheable */ |
| 1053 | g.isConst = 1; |
| 1054 | } |
| 1055 | |
| 1056 | /* |
| 1057 | ** All possible capabilities |
| 1058 | */ |
| 1059 | static const char allCap[] = |
| 1060 | "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKL"; |
| @@ -1605,21 +1430,18 @@ | |
| 1430 | ** 1) window.fossil core object, some of which depends on C-lelel |
| 1431 | ** runtime data. That part of the script is always emitted inline. If |
| 1432 | ** addScripTag is true then it is wrapped in its own SCRIPT tag, else |
| 1433 | ** it is assumed that the caller already opened a tag. |
| 1434 | ** |
| 1435 | ** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). |
| 1436 | */ |
| 1437 | void style_emit_script_fossil_bootstrap(int addScriptTag){ |
| 1438 | static int once = 0; |
| 1439 | if(0==once++){ |
| 1440 | /* Set up the generic/app-agnostic parts of window.fossil |
| 1441 | ** which require C-level state... */ |
| 1442 | if(addScriptTag!=0){ |
| 1443 | style_emit_script_tag(0,0); |
| 1444 | } |
| 1445 | CX("(function(){\n" |
| 1446 | "if(!window.fossil) window.fossil={};\n" |
| 1447 | "window.fossil.version = %!j;\n" |
| @@ -1646,18 +1468,16 @@ | |
| 1468 | */ |
| 1469 | CX("window.fossil.page = {" |
| 1470 | "name:\"%T\"" |
| 1471 | "};\n", g.zPath); |
| 1472 | CX("})();\n"); |
| 1473 | if(addScriptTag!=0){ |
| 1474 | style_emit_script_tag(1,0); |
| 1475 | } |
| 1476 | /* The remaining window.fossil bootstrap code is not dependent on |
| 1477 | ** C-runtime state... */ |
| 1478 | builtin_request_js("fossil.bootstrap.js"); |
| 1479 | } |
| 1480 | } |
| 1481 | |
| 1482 | /* |
| 1483 | ** If passed 0 as its first argument, it emits a script opener tag |
| @@ -1688,116 +1508,33 @@ | |
| 1508 | CX("</script>\n"); |
| 1509 | } |
| 1510 | } |
| 1511 | |
| 1512 | /* |
| 1513 | ** Convenience wrapper which calls builtin_request_js() for a series |
| 1514 | ** of builtin scripts named fossil.NAME.js. The first time it is |
| 1515 | ** called, it also calls style_emit_script_fossil_bootstrap() to |
| 1516 | ** initialize the window.fossil JS API. The first argument is a |
| 1517 | ** no-meaning dummy required by the va_start() interface. All |
| 1518 | ** subsequent arguments must be strings of the NAME part of |
| 1519 | ** fossil.NAME.js, followed by a NULL argument to terminate the list. |
| 1520 | ** |
| 1521 | ** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3 |
| 1522 | ** APIs. Do not forget the trailing 0! |
| 1523 | */ |
| 1524 | void style_emit_fossil_js_apis( int dummy, ... ) { |
| 1525 | static int once = 0; |
| 1526 | const char *zArg; |
| 1527 | char * zName; |
| 1528 | va_list vargs; |
| 1529 | |
| 1530 | if(0==once++){ |
| 1531 | style_emit_script_fossil_bootstrap(1); |
| 1532 | } |
| 1533 | va_start(vargs,dummy); |
| 1534 | while( (zArg = va_arg (vargs, const char *))!=0 ){ |
| 1535 | zName = mprintf("fossil.%s.js", zArg); |
| 1536 | builtin_request_js(zName); |
| 1537 | fossil_free(zName); |
| 1538 | } |
| 1539 | va_end(vargs); |
| 1540 | } |
| 1541 |
+6
-2
| --- src/timeline.c | ||
| +++ src/timeline.c | ||
| @@ -1083,12 +1083,12 @@ | ||
| 1083 | 1083 | cgi_printf("\"br\":\"%j\",", pRow->zBranch ? pRow->zBranch : ""); |
| 1084 | 1084 | cgi_printf("\"h\":\"%!S\"}%s", |
| 1085 | 1085 | pRow->zUuid, pRow->pNext ? ",\n" : "]\n"); |
| 1086 | 1086 | } |
| 1087 | 1087 | @ }</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 */ | |
| 1090 | 1090 | graph_free(pGraph); |
| 1091 | 1091 | } |
| 1092 | 1092 | } |
| 1093 | 1093 | |
| 1094 | 1094 | /* |
| @@ -1741,10 +1741,14 @@ | ||
| 1741 | 1741 | } |
| 1742 | 1742 | }else{ |
| 1743 | 1743 | z = "50"; |
| 1744 | 1744 | nEntry = 50; |
| 1745 | 1745 | } |
| 1746 | + | |
| 1747 | + /* Undocumented query parameter to set JS mode */ | |
| 1748 | + builtin_set_js_delivery_mode(P("jsmode"),1); | |
| 1749 | + | |
| 1746 | 1750 | secondaryRid = name_to_typed_rid(P("sel2"),"ci"); |
| 1747 | 1751 | selectedRid = name_to_typed_rid(P("sel1"),"ci"); |
| 1748 | 1752 | cgi_replace_query_parameter("n",z); |
| 1749 | 1753 | cookie_write_parameter("n","n",0); |
| 1750 | 1754 | tmFlags |= timeline_ss_submenu(); |
| 1751 | 1755 |
| --- 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 |
+8
-20
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -1059,24 +1059,10 @@ | ||
| 1059 | 1059 | return; |
| 1060 | 1060 | } |
| 1061 | 1061 | pRoute->xCallback(); |
| 1062 | 1062 | } |
| 1063 | 1063 | |
| 1064 | -/* | |
| 1065 | -** Emits all of the "core" static JS needed by /wikiedit. Intended to | |
| 1066 | -** be mapped to style.c:BundleEmitters with the name "wikiedit.js". | |
| 1067 | -*/ | |
| 1068 | -void wikiedit_emit_js_bundle(void){ | |
| 1069 | - style_emit_script_fossil_bootstrap(1); | |
| 1070 | - style_emit_script_builtin(1,0,"sbsdiff.js"); | |
| 1071 | - style_emit_script_fetch(1, 0); | |
| 1072 | - style_emit_script_tabs(1,0)/*also emits fossil.dom*/; | |
| 1073 | - style_emit_script_confirmer(1,0); | |
| 1074 | - style_emit_script_builtin(1, 0, "fossil.storage.js"); | |
| 1075 | - style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js"); | |
| 1076 | -} | |
| 1077 | - | |
| 1078 | 1064 | /* |
| 1079 | 1065 | ** WEBPAGE: wikiedit |
| 1080 | 1066 | ** URL: /wikedit?name=PAGENAME |
| 1081 | 1067 | ** |
| 1082 | 1068 | ** The main front-end for the Ajax-based wiki editor app. Passing |
| @@ -1258,20 +1244,20 @@ | ||
| 1258 | 1244 | CX("<hr><h3>Wiki Name Rules</h3>"); |
| 1259 | 1245 | well_formed_wiki_name_rules(); |
| 1260 | 1246 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1261 | 1247 | } |
| 1262 | 1248 | |
| 1263 | - style_emit_script_bundle("wikiedit.js"); | |
| 1264 | - | |
| 1249 | + builtin_request_js("sbsdiff.js"); | |
| 1250 | + style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", | |
| 1251 | + "storage", "page.wikiedit", 0); | |
| 1252 | + builtin_fulfill_js_requests(); | |
| 1265 | 1253 | /* Dynamically populate the editor... */ |
| 1266 | 1254 | style_emit_script_tag(0,0); |
| 1267 | 1255 | CX("\nfossil.onPageLoad(function(){\n"); |
| 1268 | 1256 | CX("const P = fossil.page;\n" |
| 1269 | 1257 | "try{\n"); |
| 1270 | - if(found){ | |
| 1271 | - CX("P.loadPage(%!j);\n", zPageName); | |
| 1272 | - }else if(zPageName && *zPageName){ | |
| 1258 | + if(!found && zPageName && *zPageName){ | |
| 1273 | 1259 | /* For a new page, stick a dummy entry in the JS-side stash |
| 1274 | 1260 | and "load" it from there. */ |
| 1275 | 1261 | CX("const winfo = {" |
| 1276 | 1262 | "\"name\": %!j, \"mimetype\": %!j, " |
| 1277 | 1263 | "\"type\": %!j, " |
| @@ -1284,10 +1270,12 @@ | ||
| 1284 | 1270 | copy from the stash, otherwise inject a new stash entry |
| 1285 | 1271 | for it and load *that* one... */ |
| 1286 | 1272 | CX("if(!P.$stash.getWinfo(winfo)){" |
| 1287 | 1273 | "P.$stash.updateWinfo(winfo,'');" |
| 1288 | 1274 | "}\n"); |
| 1275 | + } | |
| 1276 | + if(zPageName && *zPageName){ | |
| 1289 | 1277 | CX("P.loadPage(%!j);\n", zPageName); |
| 1290 | 1278 | } |
| 1291 | 1279 | CX("}catch(e){" |
| 1292 | 1280 | "fossil.error(e); console.error('Exception:',e);" |
| 1293 | 1281 | "}\n"); |
| @@ -2520,8 +2508,8 @@ | ||
| 2520 | 2508 | blob_reset(&tail); |
| 2521 | 2509 | blob_reset(&title); |
| 2522 | 2510 | blob_reset(&wiki); |
| 2523 | 2511 | } |
| 2524 | 2512 | manifest_destroy(pWiki); |
| 2525 | - style_accordion(); | |
| 2513 | + builtin_request_js("accordion.js"); | |
| 2526 | 2514 | return 1; |
| 2527 | 2515 | } |
| 2528 | 2516 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1059,24 +1059,10 @@ | |
| 1059 | return; |
| 1060 | } |
| 1061 | pRoute->xCallback(); |
| 1062 | } |
| 1063 | |
| 1064 | /* |
| 1065 | ** Emits all of the "core" static JS needed by /wikiedit. Intended to |
| 1066 | ** be mapped to style.c:BundleEmitters with the name "wikiedit.js". |
| 1067 | */ |
| 1068 | void wikiedit_emit_js_bundle(void){ |
| 1069 | style_emit_script_fossil_bootstrap(1); |
| 1070 | style_emit_script_builtin(1,0,"sbsdiff.js"); |
| 1071 | style_emit_script_fetch(1, 0); |
| 1072 | style_emit_script_tabs(1,0)/*also emits fossil.dom*/; |
| 1073 | style_emit_script_confirmer(1,0); |
| 1074 | style_emit_script_builtin(1, 0, "fossil.storage.js"); |
| 1075 | style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js"); |
| 1076 | } |
| 1077 | |
| 1078 | /* |
| 1079 | ** WEBPAGE: wikiedit |
| 1080 | ** URL: /wikedit?name=PAGENAME |
| 1081 | ** |
| 1082 | ** The main front-end for the Ajax-based wiki editor app. Passing |
| @@ -1258,20 +1244,20 @@ | |
| 1258 | CX("<hr><h3>Wiki Name Rules</h3>"); |
| 1259 | well_formed_wiki_name_rules(); |
| 1260 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1261 | } |
| 1262 | |
| 1263 | style_emit_script_bundle("wikiedit.js"); |
| 1264 | |
| 1265 | /* Dynamically populate the editor... */ |
| 1266 | style_emit_script_tag(0,0); |
| 1267 | CX("\nfossil.onPageLoad(function(){\n"); |
| 1268 | CX("const P = fossil.page;\n" |
| 1269 | "try{\n"); |
| 1270 | if(found){ |
| 1271 | CX("P.loadPage(%!j);\n", zPageName); |
| 1272 | }else if(zPageName && *zPageName){ |
| 1273 | /* For a new page, stick a dummy entry in the JS-side stash |
| 1274 | and "load" it from there. */ |
| 1275 | CX("const winfo = {" |
| 1276 | "\"name\": %!j, \"mimetype\": %!j, " |
| 1277 | "\"type\": %!j, " |
| @@ -1284,10 +1270,12 @@ | |
| 1284 | copy from the stash, otherwise inject a new stash entry |
| 1285 | for it and load *that* one... */ |
| 1286 | CX("if(!P.$stash.getWinfo(winfo)){" |
| 1287 | "P.$stash.updateWinfo(winfo,'');" |
| 1288 | "}\n"); |
| 1289 | CX("P.loadPage(%!j);\n", zPageName); |
| 1290 | } |
| 1291 | CX("}catch(e){" |
| 1292 | "fossil.error(e); console.error('Exception:',e);" |
| 1293 | "}\n"); |
| @@ -2520,8 +2508,8 @@ | |
| 2520 | blob_reset(&tail); |
| 2521 | blob_reset(&title); |
| 2522 | blob_reset(&wiki); |
| 2523 | } |
| 2524 | manifest_destroy(pWiki); |
| 2525 | style_accordion(); |
| 2526 | return 1; |
| 2527 | } |
| 2528 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1059,24 +1059,10 @@ | |
| 1059 | return; |
| 1060 | } |
| 1061 | pRoute->xCallback(); |
| 1062 | } |
| 1063 | |
| 1064 | /* |
| 1065 | ** WEBPAGE: wikiedit |
| 1066 | ** URL: /wikedit?name=PAGENAME |
| 1067 | ** |
| 1068 | ** The main front-end for the Ajax-based wiki editor app. Passing |
| @@ -1258,20 +1244,20 @@ | |
| 1244 | CX("<hr><h3>Wiki Name Rules</h3>"); |
| 1245 | well_formed_wiki_name_rules(); |
| 1246 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1247 | } |
| 1248 | |
| 1249 | builtin_request_js("sbsdiff.js"); |
| 1250 | style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", |
| 1251 | "storage", "page.wikiedit", 0); |
| 1252 | builtin_fulfill_js_requests(); |
| 1253 | /* Dynamically populate the editor... */ |
| 1254 | style_emit_script_tag(0,0); |
| 1255 | CX("\nfossil.onPageLoad(function(){\n"); |
| 1256 | CX("const P = fossil.page;\n" |
| 1257 | "try{\n"); |
| 1258 | if(!found && zPageName && *zPageName){ |
| 1259 | /* For a new page, stick a dummy entry in the JS-side stash |
| 1260 | and "load" it from there. */ |
| 1261 | CX("const winfo = {" |
| 1262 | "\"name\": %!j, \"mimetype\": %!j, " |
| 1263 | "\"type\": %!j, " |
| @@ -1284,10 +1270,12 @@ | |
| 1270 | copy from the stash, otherwise inject a new stash entry |
| 1271 | for it and load *that* one... */ |
| 1272 | CX("if(!P.$stash.getWinfo(winfo)){" |
| 1273 | "P.$stash.updateWinfo(winfo,'');" |
| 1274 | "}\n"); |
| 1275 | } |
| 1276 | if(zPageName && *zPageName){ |
| 1277 | CX("P.loadPage(%!j);\n", zPageName); |
| 1278 | } |
| 1279 | CX("}catch(e){" |
| 1280 | "fossil.error(e); console.error('Exception:',e);" |
| 1281 | "}\n"); |
| @@ -2520,8 +2508,8 @@ | |
| 2508 | blob_reset(&tail); |
| 2509 | blob_reset(&title); |
| 2510 | blob_reset(&wiki); |
| 2511 | } |
| 2512 | manifest_destroy(pWiki); |
| 2513 | builtin_request_js("accordion.js"); |
| 2514 | return 1; |
| 2515 | } |
| 2516 |
+8
-20
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -1059,24 +1059,10 @@ | ||
| 1059 | 1059 | return; |
| 1060 | 1060 | } |
| 1061 | 1061 | pRoute->xCallback(); |
| 1062 | 1062 | } |
| 1063 | 1063 | |
| 1064 | -/* | |
| 1065 | -** Emits all of the "core" static JS needed by /wikiedit. Intended to | |
| 1066 | -** be mapped to style.c:BundleEmitters with the name "wikiedit.js". | |
| 1067 | -*/ | |
| 1068 | -void wikiedit_emit_js_bundle(void){ | |
| 1069 | - style_emit_script_fossil_bootstrap(1); | |
| 1070 | - style_emit_script_builtin(1,0,"sbsdiff.js"); | |
| 1071 | - style_emit_script_fetch(1, 0); | |
| 1072 | - style_emit_script_tabs(1,0)/*also emits fossil.dom*/; | |
| 1073 | - style_emit_script_confirmer(1,0); | |
| 1074 | - style_emit_script_builtin(1, 0, "fossil.storage.js"); | |
| 1075 | - style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js"); | |
| 1076 | -} | |
| 1077 | - | |
| 1078 | 1064 | /* |
| 1079 | 1065 | ** WEBPAGE: wikiedit |
| 1080 | 1066 | ** URL: /wikedit?name=PAGENAME |
| 1081 | 1067 | ** |
| 1082 | 1068 | ** The main front-end for the Ajax-based wiki editor app. Passing |
| @@ -1258,20 +1244,20 @@ | ||
| 1258 | 1244 | CX("<hr><h3>Wiki Name Rules</h3>"); |
| 1259 | 1245 | well_formed_wiki_name_rules(); |
| 1260 | 1246 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1261 | 1247 | } |
| 1262 | 1248 | |
| 1263 | - style_emit_script_bundle("wikiedit.js"); | |
| 1264 | - | |
| 1249 | + builtin_request_js("sbsdiff.js"); | |
| 1250 | + style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", | |
| 1251 | + "storage", "page.wikiedit", 0); | |
| 1252 | + builtin_fulfill_js_requests(); | |
| 1265 | 1253 | /* Dynamically populate the editor... */ |
| 1266 | 1254 | style_emit_script_tag(0,0); |
| 1267 | 1255 | CX("\nfossil.onPageLoad(function(){\n"); |
| 1268 | 1256 | CX("const P = fossil.page;\n" |
| 1269 | 1257 | "try{\n"); |
| 1270 | - if(found){ | |
| 1271 | - CX("P.loadPage(%!j);\n", zPageName); | |
| 1272 | - }else if(zPageName && *zPageName){ | |
| 1258 | + if(!found && zPageName && *zPageName){ | |
| 1273 | 1259 | /* For a new page, stick a dummy entry in the JS-side stash |
| 1274 | 1260 | and "load" it from there. */ |
| 1275 | 1261 | CX("const winfo = {" |
| 1276 | 1262 | "\"name\": %!j, \"mimetype\": %!j, " |
| 1277 | 1263 | "\"type\": %!j, " |
| @@ -1284,10 +1270,12 @@ | ||
| 1284 | 1270 | copy from the stash, otherwise inject a new stash entry |
| 1285 | 1271 | for it and load *that* one... */ |
| 1286 | 1272 | CX("if(!P.$stash.getWinfo(winfo)){" |
| 1287 | 1273 | "P.$stash.updateWinfo(winfo,'');" |
| 1288 | 1274 | "}\n"); |
| 1275 | + } | |
| 1276 | + if(zPageName && *zPageName){ | |
| 1289 | 1277 | CX("P.loadPage(%!j);\n", zPageName); |
| 1290 | 1278 | } |
| 1291 | 1279 | CX("}catch(e){" |
| 1292 | 1280 | "fossil.error(e); console.error('Exception:',e);" |
| 1293 | 1281 | "}\n"); |
| @@ -2520,8 +2508,8 @@ | ||
| 2520 | 2508 | blob_reset(&tail); |
| 2521 | 2509 | blob_reset(&title); |
| 2522 | 2510 | blob_reset(&wiki); |
| 2523 | 2511 | } |
| 2524 | 2512 | manifest_destroy(pWiki); |
| 2525 | - style_accordion(); | |
| 2513 | + builtin_request_js("accordion.js"); | |
| 2526 | 2514 | return 1; |
| 2527 | 2515 | } |
| 2528 | 2516 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1059,24 +1059,10 @@ | |
| 1059 | return; |
| 1060 | } |
| 1061 | pRoute->xCallback(); |
| 1062 | } |
| 1063 | |
| 1064 | /* |
| 1065 | ** Emits all of the "core" static JS needed by /wikiedit. Intended to |
| 1066 | ** be mapped to style.c:BundleEmitters with the name "wikiedit.js". |
| 1067 | */ |
| 1068 | void wikiedit_emit_js_bundle(void){ |
| 1069 | style_emit_script_fossil_bootstrap(1); |
| 1070 | style_emit_script_builtin(1,0,"sbsdiff.js"); |
| 1071 | style_emit_script_fetch(1, 0); |
| 1072 | style_emit_script_tabs(1,0)/*also emits fossil.dom*/; |
| 1073 | style_emit_script_confirmer(1,0); |
| 1074 | style_emit_script_builtin(1, 0, "fossil.storage.js"); |
| 1075 | style_emit_script_builtin(1, 0, "fossil.page.wikiedit.js"); |
| 1076 | } |
| 1077 | |
| 1078 | /* |
| 1079 | ** WEBPAGE: wikiedit |
| 1080 | ** URL: /wikedit?name=PAGENAME |
| 1081 | ** |
| 1082 | ** The main front-end for the Ajax-based wiki editor app. Passing |
| @@ -1258,20 +1244,20 @@ | |
| 1258 | CX("<hr><h3>Wiki Name Rules</h3>"); |
| 1259 | well_formed_wiki_name_rules(); |
| 1260 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1261 | } |
| 1262 | |
| 1263 | style_emit_script_bundle("wikiedit.js"); |
| 1264 | |
| 1265 | /* Dynamically populate the editor... */ |
| 1266 | style_emit_script_tag(0,0); |
| 1267 | CX("\nfossil.onPageLoad(function(){\n"); |
| 1268 | CX("const P = fossil.page;\n" |
| 1269 | "try{\n"); |
| 1270 | if(found){ |
| 1271 | CX("P.loadPage(%!j);\n", zPageName); |
| 1272 | }else if(zPageName && *zPageName){ |
| 1273 | /* For a new page, stick a dummy entry in the JS-side stash |
| 1274 | and "load" it from there. */ |
| 1275 | CX("const winfo = {" |
| 1276 | "\"name\": %!j, \"mimetype\": %!j, " |
| 1277 | "\"type\": %!j, " |
| @@ -1284,10 +1270,12 @@ | |
| 1284 | copy from the stash, otherwise inject a new stash entry |
| 1285 | for it and load *that* one... */ |
| 1286 | CX("if(!P.$stash.getWinfo(winfo)){" |
| 1287 | "P.$stash.updateWinfo(winfo,'');" |
| 1288 | "}\n"); |
| 1289 | CX("P.loadPage(%!j);\n", zPageName); |
| 1290 | } |
| 1291 | CX("}catch(e){" |
| 1292 | "fossil.error(e); console.error('Exception:',e);" |
| 1293 | "}\n"); |
| @@ -2520,8 +2508,8 @@ | |
| 2520 | blob_reset(&tail); |
| 2521 | blob_reset(&title); |
| 2522 | blob_reset(&wiki); |
| 2523 | } |
| 2524 | manifest_destroy(pWiki); |
| 2525 | style_accordion(); |
| 2526 | return 1; |
| 2527 | } |
| 2528 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1059,24 +1059,10 @@ | |
| 1059 | return; |
| 1060 | } |
| 1061 | pRoute->xCallback(); |
| 1062 | } |
| 1063 | |
| 1064 | /* |
| 1065 | ** WEBPAGE: wikiedit |
| 1066 | ** URL: /wikedit?name=PAGENAME |
| 1067 | ** |
| 1068 | ** The main front-end for the Ajax-based wiki editor app. Passing |
| @@ -1258,20 +1244,20 @@ | |
| 1244 | CX("<hr><h3>Wiki Name Rules</h3>"); |
| 1245 | well_formed_wiki_name_rules(); |
| 1246 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1247 | } |
| 1248 | |
| 1249 | builtin_request_js("sbsdiff.js"); |
| 1250 | style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", |
| 1251 | "storage", "page.wikiedit", 0); |
| 1252 | builtin_fulfill_js_requests(); |
| 1253 | /* Dynamically populate the editor... */ |
| 1254 | style_emit_script_tag(0,0); |
| 1255 | CX("\nfossil.onPageLoad(function(){\n"); |
| 1256 | CX("const P = fossil.page;\n" |
| 1257 | "try{\n"); |
| 1258 | if(!found && zPageName && *zPageName){ |
| 1259 | /* For a new page, stick a dummy entry in the JS-side stash |
| 1260 | and "load" it from there. */ |
| 1261 | CX("const winfo = {" |
| 1262 | "\"name\": %!j, \"mimetype\": %!j, " |
| 1263 | "\"type\": %!j, " |
| @@ -1284,10 +1270,12 @@ | |
| 1270 | copy from the stash, otherwise inject a new stash entry |
| 1271 | for it and load *that* one... */ |
| 1272 | CX("if(!P.$stash.getWinfo(winfo)){" |
| 1273 | "P.$stash.updateWinfo(winfo,'');" |
| 1274 | "}\n"); |
| 1275 | } |
| 1276 | if(zPageName && *zPageName){ |
| 1277 | CX("P.loadPage(%!j);\n", zPageName); |
| 1278 | } |
| 1279 | CX("}catch(e){" |
| 1280 | "fossil.error(e); console.error('Exception:',e);" |
| 1281 | "}\n"); |
| @@ -2520,8 +2508,8 @@ | |
| 2508 | blob_reset(&tail); |
| 2509 | blob_reset(&title); |
| 2510 | blob_reset(&wiki); |
| 2511 | } |
| 2512 | manifest_destroy(pWiki); |
| 2513 | builtin_request_js("accordion.js"); |
| 2514 | return 1; |
| 2515 | } |
| 2516 |
+4
-1
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -1063,13 +1063,16 @@ | ||
| 1063 | 1063 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1064 | 1064 | # the repository after running the tests. |
| 1065 | 1065 | test: $(OBJDIR) $(APPNAME) |
| 1066 | 1066 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1067 | 1067 | |
| 1068 | -$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) | |
| 1068 | +$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h | |
| 1069 | 1069 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1070 | 1070 | |
| 1071 | +$(OBJDIR)/phony.h: | |
| 1072 | + # Force rebuild of VERSION.h every time "make" is run | |
| 1073 | + | |
| 1071 | 1074 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1072 | 1075 | # to 1. If it is set to 1, then there is no need to build or link |
| 1073 | 1076 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1074 | 1077 | # using -lsqlite3. |
| 1075 | 1078 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| 1076 | 1079 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -1063,13 +1063,16 @@ | |
| 1063 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1064 | # the repository after running the tests. |
| 1065 | test: $(OBJDIR) $(APPNAME) |
| 1066 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1067 | |
| 1068 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) |
| 1069 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1070 | |
| 1071 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1072 | # to 1. If it is set to 1, then there is no need to build or link |
| 1073 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1074 | # using -lsqlite3. |
| 1075 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| 1076 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -1063,13 +1063,16 @@ | |
| 1063 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1064 | # the repository after running the tests. |
| 1065 | test: $(OBJDIR) $(APPNAME) |
| 1066 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1067 | |
| 1068 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h |
| 1069 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1070 | |
| 1071 | $(OBJDIR)/phony.h: |
| 1072 | # Force rebuild of VERSION.h every time "make" is run |
| 1073 | |
| 1074 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1075 | # to 1. If it is set to 1, then there is no need to build or link |
| 1076 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1077 | # using -lsqlite3. |
| 1078 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| 1079 |
+4
-1
| --- win/Makefile.mingw | ||
| +++ win/Makefile.mingw | ||
| @@ -1063,13 +1063,16 @@ | ||
| 1063 | 1063 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1064 | 1064 | # the repository after running the tests. |
| 1065 | 1065 | test: $(OBJDIR) $(APPNAME) |
| 1066 | 1066 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1067 | 1067 | |
| 1068 | -$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) | |
| 1068 | +$(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h | |
| 1069 | 1069 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1070 | 1070 | |
| 1071 | +$(OBJDIR)/phony.h: | |
| 1072 | + # Force rebuild of VERSION.h every time "make" is run | |
| 1073 | + | |
| 1071 | 1074 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1072 | 1075 | # to 1. If it is set to 1, then there is no need to build or link |
| 1073 | 1076 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1074 | 1077 | # using -lsqlite3. |
| 1075 | 1078 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| 1076 | 1079 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -1063,13 +1063,16 @@ | |
| 1063 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1064 | # the repository after running the tests. |
| 1065 | test: $(OBJDIR) $(APPNAME) |
| 1066 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1067 | |
| 1068 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) |
| 1069 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1070 | |
| 1071 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1072 | # to 1. If it is set to 1, then there is no need to build or link |
| 1073 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1074 | # using -lsqlite3. |
| 1075 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| 1076 |
| --- win/Makefile.mingw | |
| +++ win/Makefile.mingw | |
| @@ -1063,13 +1063,16 @@ | |
| 1063 | # build is done from, i.e. the checkout belongs to. Do not sync/push |
| 1064 | # the repository after running the tests. |
| 1065 | test: $(OBJDIR) $(APPNAME) |
| 1066 | $(TCLSH) $(SRCDIR)/../test/tester.tcl $(APPNAME) |
| 1067 | |
| 1068 | $(OBJDIR)/VERSION.h: $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(MKVERSION) $(OBJDIR)/phony.h |
| 1069 | $(MKVERSION) $(SRCDIR)/../manifest.uuid $(SRCDIR)/../manifest $(SRCDIR)/../VERSION >$@ |
| 1070 | |
| 1071 | $(OBJDIR)/phony.h: |
| 1072 | # Force rebuild of VERSION.h every time "make" is run |
| 1073 | |
| 1074 | # The USE_SYSTEM_SQLITE variable may be undefined, set to 0, or set |
| 1075 | # to 1. If it is set to 1, then there is no need to build or link |
| 1076 | # the sqlite3.o object. Instead, the system SQLite will be linked |
| 1077 | # using -lsqlite3. |
| 1078 | SQLITE3_OBJ.0 = $(OBJDIR)/sqlite3.o |
| 1079 |
+5
-2
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -1024,12 +1024,15 @@ | ||
| 1024 | 1024 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1025 | 1025 | |
| 1026 | 1026 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1027 | 1027 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1028 | 1028 | |
| 1029 | -"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" | |
| 1030 | - $** > $@ | |
| 1029 | +"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h" | |
| 1030 | + "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@ | |
| 1031 | + | |
| 1032 | +"$(B)\phony.h" : | |
| 1033 | + rem Force rebuild of VERSION.h whenever nmake is run | |
| 1031 | 1034 | |
| 1032 | 1035 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1033 | 1036 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1034 | 1037 | |
| 1035 | 1038 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1036 | 1039 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -1024,12 +1024,15 @@ | |
| 1024 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1025 | |
| 1026 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1027 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1028 | |
| 1029 | "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" |
| 1030 | $** > $@ |
| 1031 | |
| 1032 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1033 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1034 | |
| 1035 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1036 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -1024,12 +1024,15 @@ | |
| 1024 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1025 | |
| 1026 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1027 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1028 | |
| 1029 | "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h" |
| 1030 | "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@ |
| 1031 | |
| 1032 | "$(B)\phony.h" : |
| 1033 | rem Force rebuild of VERSION.h whenever nmake is run |
| 1034 | |
| 1035 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1036 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1037 | |
| 1038 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1039 |
+5
-2
| --- win/Makefile.msc | ||
| +++ win/Makefile.msc | ||
| @@ -1024,12 +1024,15 @@ | ||
| 1024 | 1024 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1025 | 1025 | |
| 1026 | 1026 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1027 | 1027 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1028 | 1028 | |
| 1029 | -"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" | |
| 1030 | - $** > $@ | |
| 1029 | +"$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h" | |
| 1030 | + "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@ | |
| 1031 | + | |
| 1032 | +"$(B)\phony.h" : | |
| 1033 | + rem Force rebuild of VERSION.h whenever nmake is run | |
| 1031 | 1034 | |
| 1032 | 1035 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1033 | 1036 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1034 | 1037 | |
| 1035 | 1038 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1036 | 1039 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -1024,12 +1024,15 @@ | |
| 1024 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1025 | |
| 1026 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1027 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1028 | |
| 1029 | "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" |
| 1030 | $** > $@ |
| 1031 | |
| 1032 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1033 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1034 | |
| 1035 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1036 |
| --- win/Makefile.msc | |
| +++ win/Makefile.msc | |
| @@ -1024,12 +1024,15 @@ | |
| 1024 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1025 | |
| 1026 | "$(OX)\miniz$O" : "$(SRCDIR)\miniz.c" |
| 1027 | $(TCC) /Fo$@ /Fd$(@D)\ -c $(MINIZ_OPTIONS) $** |
| 1028 | |
| 1029 | "$(OX)\VERSION.h" : "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" "$(B)\phony.h" |
| 1030 | "$(OBJDIR)\mkversion$E" "$(B)\manifest.uuid" "$(B)\manifest" "$(B)\VERSION" > $@ |
| 1031 | |
| 1032 | "$(B)\phony.h" : |
| 1033 | rem Force rebuild of VERSION.h whenever nmake is run |
| 1034 | |
| 1035 | "$(OX)\cson_amalgamation$O" : "$(SRCDIR)\cson_amalgamation.c" |
| 1036 | $(TCC) /Fo$@ /Fd$(@D)\ -c $** |
| 1037 | |
| 1038 | "$(OX)\page_index.h": "$(OBJDIR)\mkindex$E" $(SRC) |
| 1039 |