Fossil SCM
Moved C routines which emit fossil.XYZ JS APIs from style.c to builtin.c, and renamed appropriately. Added flag to output_text_with_line_numbers() to disable emit of JS (needed for fileedit preview, at a minimum). The experimental emitting of all fossil.XYZ APIs at once is now limited to bundled mode, as that's the only place it's potentially of benefit.
Commit
c515e5fd9f41fc3f311a74af3c598c28879cd532ac2bd117d2674ae03231e89b
Parent
9edbb7eab1b0fe4…
14 files changed
+2
-2
+1
-1
+159
+1
-1
+21
-19
+1
-1
+4
-4
+13
-10
+1
-1
+22
-12
-130
+9
-2
+7
-11
+2
-2
| --- src/ajax.c | ||
| +++ src/ajax.c | ||
| @@ -41,11 +41,11 @@ | ||
| 41 | 41 | ** and symbolic names for use by client-side scripts. |
| 42 | 42 | ** |
| 43 | 43 | ** If addScriptTag is true then the output is wrapped in a SCRIPT tag |
| 44 | 44 | ** with the current nonce, else no SCRIPT tag is emitted. |
| 45 | 45 | ** |
| 46 | -** Requires that style_emit_script_fossil_bootstrap() has already been | |
| 46 | +** Requires that builtin_emit_script_fossil_bootstrap() has already been | |
| 47 | 47 | ** called in order to initialize the window.fossil.page object. |
| 48 | 48 | */ |
| 49 | 49 | void ajax_emit_js_preview_modes(int addScriptTag){ |
| 50 | 50 | if(addScriptTag){ |
| 51 | 51 | style_emit_script_tag(0,0); |
| @@ -131,11 +131,11 @@ | ||
| 131 | 131 | break; |
| 132 | 132 | default:{ |
| 133 | 133 | const char *zContent = blob_str(pContent); |
| 134 | 134 | if(AJAX_PREVIEW_LINE_NUMBERS & flags){ |
| 135 | 135 | output_text_with_line_numbers(zContent, blob_size(pContent), |
| 136 | - zName, "on"); | |
| 136 | + zName, "on", 0); | |
| 137 | 137 | }else{ |
| 138 | 138 | const char *zExt = strrchr(zName,'.'); |
| 139 | 139 | if(zExt && zExt[1]){ |
| 140 | 140 | CX("<pre><code class='language-%s'>%h</code></pre>", |
| 141 | 141 | zExt+1, zContent); |
| 142 | 142 |
| --- src/ajax.c | |
| +++ src/ajax.c | |
| @@ -41,11 +41,11 @@ | |
| 41 | ** and symbolic names for use by client-side scripts. |
| 42 | ** |
| 43 | ** If addScriptTag is true then the output is wrapped in a SCRIPT tag |
| 44 | ** with the current nonce, else no SCRIPT tag is emitted. |
| 45 | ** |
| 46 | ** Requires that style_emit_script_fossil_bootstrap() has already been |
| 47 | ** called in order to initialize the window.fossil.page object. |
| 48 | */ |
| 49 | void ajax_emit_js_preview_modes(int addScriptTag){ |
| 50 | if(addScriptTag){ |
| 51 | style_emit_script_tag(0,0); |
| @@ -131,11 +131,11 @@ | |
| 131 | break; |
| 132 | default:{ |
| 133 | const char *zContent = blob_str(pContent); |
| 134 | if(AJAX_PREVIEW_LINE_NUMBERS & flags){ |
| 135 | output_text_with_line_numbers(zContent, blob_size(pContent), |
| 136 | zName, "on"); |
| 137 | }else{ |
| 138 | const char *zExt = strrchr(zName,'.'); |
| 139 | if(zExt && zExt[1]){ |
| 140 | CX("<pre><code class='language-%s'>%h</code></pre>", |
| 141 | zExt+1, zContent); |
| 142 |
| --- src/ajax.c | |
| +++ src/ajax.c | |
| @@ -41,11 +41,11 @@ | |
| 41 | ** and symbolic names for use by client-side scripts. |
| 42 | ** |
| 43 | ** If addScriptTag is true then the output is wrapped in a SCRIPT tag |
| 44 | ** with the current nonce, else no SCRIPT tag is emitted. |
| 45 | ** |
| 46 | ** Requires that builtin_emit_script_fossil_bootstrap() has already been |
| 47 | ** called in order to initialize the window.fossil.page object. |
| 48 | */ |
| 49 | void ajax_emit_js_preview_modes(int addScriptTag){ |
| 50 | if(addScriptTag){ |
| 51 | style_emit_script_tag(0,0); |
| @@ -131,11 +131,11 @@ | |
| 131 | break; |
| 132 | default:{ |
| 133 | const char *zContent = blob_str(pContent); |
| 134 | if(AJAX_PREVIEW_LINE_NUMBERS & flags){ |
| 135 | output_text_with_line_numbers(zContent, blob_size(pContent), |
| 136 | zName, "on", 0); |
| 137 | }else{ |
| 138 | const char *zExt = strrchr(zName,'.'); |
| 139 | if(zExt && zExt[1]){ |
| 140 | CX("<pre><code class='language-%s'>%h</code></pre>", |
| 141 | zExt+1, zContent); |
| 142 |
+1
-1
| --- src/attach.c | ||
| +++ src/attach.c | ||
| @@ -617,11 +617,11 @@ | ||
| 617 | 617 | const char *z; |
| 618 | 618 | content_get(ridSrc, &attach); |
| 619 | 619 | blob_to_utf8_no_bom(&attach, 0); |
| 620 | 620 | z = blob_str(&attach); |
| 621 | 621 | if( zLn ){ |
| 622 | - output_text_with_line_numbers(z, blob_size(&attach), zName, zLn); | |
| 622 | + output_text_with_line_numbers(z, blob_size(&attach), zName, zLn, 1); | |
| 623 | 623 | }else{ |
| 624 | 624 | @ <pre> |
| 625 | 625 | @ %h(z) |
| 626 | 626 | @ </pre> |
| 627 | 627 | } |
| 628 | 628 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -617,11 +617,11 @@ | |
| 617 | const char *z; |
| 618 | content_get(ridSrc, &attach); |
| 619 | blob_to_utf8_no_bom(&attach, 0); |
| 620 | z = blob_str(&attach); |
| 621 | if( zLn ){ |
| 622 | output_text_with_line_numbers(z, blob_size(&attach), zName, zLn); |
| 623 | }else{ |
| 624 | @ <pre> |
| 625 | @ %h(z) |
| 626 | @ </pre> |
| 627 | } |
| 628 |
| --- src/attach.c | |
| +++ src/attach.c | |
| @@ -617,11 +617,11 @@ | |
| 617 | const char *z; |
| 618 | content_get(ridSrc, &attach); |
| 619 | blob_to_utf8_no_bom(&attach, 0); |
| 620 | z = blob_str(&attach); |
| 621 | if( zLn ){ |
| 622 | output_text_with_line_numbers(z, blob_size(&attach), zName, zLn, 1); |
| 623 | }else{ |
| 624 | @ <pre> |
| 625 | @ %h(z) |
| 626 | @ </pre> |
| 627 | } |
| 628 |
+159
| --- src/builtin.c | ||
| +++ src/builtin.c | ||
| @@ -258,10 +258,18 @@ | ||
| 258 | 258 | }else if( !bSilent ){ |
| 259 | 259 | fossil_fatal("unknown javascript delivery mode \"%s\" - should be" |
| 260 | 260 | " one of: inline separate bundled", zMode); |
| 261 | 261 | } |
| 262 | 262 | } |
| 263 | + | |
| 264 | +/* | |
| 265 | +** Returns the current JS delivery mode: one of JS_INLINE, | |
| 266 | +** JS_SEPARATE, JS_BUNDLED. | |
| 267 | +*/ | |
| 268 | +int builtin_get_js_delivery_mode(void){ | |
| 269 | + return builtin.eDelivery; | |
| 270 | +} | |
| 263 | 271 | |
| 264 | 272 | /* |
| 265 | 273 | ** The caller wants the Javascript file named by zFilename to be |
| 266 | 274 | ** included in the generated page. Add the file to the queue of |
| 267 | 275 | ** requested javascript resources, if it is not there already. |
| @@ -559,5 +567,156 @@ | ||
| 559 | 567 | int rc = sqlite3_create_module(db, "builtin", &builtinVtabModule, 0); |
| 560 | 568 | return rc; |
| 561 | 569 | } |
| 562 | 570 | /* End of the builtin virtual table |
| 563 | 571 | ******************************************************************************/ |
| 572 | + | |
| 573 | + | |
| 574 | +/* | |
| 575 | +** The first time this is called, it emits code to install and | |
| 576 | +** bootstrap the window.fossil object, using the built-in file | |
| 577 | +** fossil.bootstrap.js (not to be confused with bootstrap.js). | |
| 578 | +** | |
| 579 | +** Subsequent calls are no-ops. | |
| 580 | +** | |
| 581 | +** It emits 2 parts: | |
| 582 | +** | |
| 583 | +** 1) window.fossil core object, some of which depends on C-level | |
| 584 | +** runtime data. That part of the script is always emitted inline. If | |
| 585 | +** addScriptTag is true then it is wrapped in its own SCRIPT tag, else | |
| 586 | +** it is assumed that the caller already opened a tag. | |
| 587 | +** | |
| 588 | +** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). | |
| 589 | +*/ | |
| 590 | +void builtin_emit_script_fossil_bootstrap(int addScriptTag){ | |
| 591 | + static int once = 0; | |
| 592 | + if(0==once++){ | |
| 593 | + char * zName; | |
| 594 | + /* Set up the generic/app-agnostic parts of window.fossil | |
| 595 | + ** which require C-level state... */ | |
| 596 | + if(addScriptTag!=0){ | |
| 597 | + style_emit_script_tag(0,0); | |
| 598 | + } | |
| 599 | + CX("(function(){\n"); | |
| 600 | + CX(/*MSIE NodeList.forEach polyfill, courtesy of Mozilla: | |
| 601 | + https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Polyfill | |
| 602 | + */ | |
| 603 | + "if(window.NodeList && !NodeList.prototype.forEach){" | |
| 604 | + "NodeList.prototype.forEach = Array.prototype.forEach;" | |
| 605 | + "}\n"); | |
| 606 | + CX("if(!window.fossil) window.fossil={};\n" | |
| 607 | + "window.fossil.version = %!j;\n" | |
| 608 | + /* fossil.rootPath is the top-most CGI/server path, | |
| 609 | + ** including a trailing slash. */ | |
| 610 | + "window.fossil.rootPath = %!j+'/';\n", | |
| 611 | + get_version(), g.zTop); | |
| 612 | + /* fossil.config = {...various config-level options...} */ | |
| 613 | + CX("window.fossil.config = {"); | |
| 614 | + zName = db_get("project-name", ""); | |
| 615 | + CX("projectName: %!j,\n", zName); | |
| 616 | + fossil_free(zName); | |
| 617 | + zName = db_get("short-project-name", ""); | |
| 618 | + CX("shortProjectName: %!j,\n", zName); | |
| 619 | + fossil_free(zName); | |
| 620 | + zName = db_get("project-code", ""); | |
| 621 | + CX("projectCode: %!j,\n", zName); | |
| 622 | + fossil_free(zName); | |
| 623 | + CX("/* Length of UUID hashes for display purposes. */"); | |
| 624 | + CX("hashDigits: %d, hashDigitsUrl: %d,\n", | |
| 625 | + hash_digits(0), hash_digits(1)); | |
| 626 | + CX("editStateMarkers: {" | |
| 627 | + "/*Symbolic markers to denote certain edit states.*/" | |
| 628 | + "isNew:'[+]', isModified:'[*]', isDeleted:'[-]'},\n"); | |
| 629 | + CX("confirmerButtonTicks: 3 " | |
| 630 | + "/*default fossil.confirmer tick count.*/\n"); | |
| 631 | + CX("};\n"/* fossil.config */); | |
| 632 | +#if 0 | |
| 633 | + /* Is it safe to emit the CSRF token here? Some pages add it | |
| 634 | + ** as a hidden form field. */ | |
| 635 | + if(g.zCsrfToken[0]!=0){ | |
| 636 | + CX("window.fossil.csrfToken = %!j;\n", | |
| 637 | + g.zCsrfToken); | |
| 638 | + } | |
| 639 | +#endif | |
| 640 | + /* | |
| 641 | + ** fossil.page holds info about the current page. This is also | |
| 642 | + ** where the current page "should" store any of its own | |
| 643 | + ** page-specific state, and it is reserved for that purpose. | |
| 644 | + */ | |
| 645 | + CX("window.fossil.page = {" | |
| 646 | + "name:\"%T\"" | |
| 647 | + "};\n", g.zPath); | |
| 648 | + CX("})();\n"); | |
| 649 | + if(addScriptTag!=0){ | |
| 650 | + style_emit_script_tag(1,0); | |
| 651 | + } | |
| 652 | + /* The remaining window.fossil bootstrap code is not dependent on | |
| 653 | + ** C-runtime state... */ | |
| 654 | + builtin_request_js("fossil.bootstrap.js"); | |
| 655 | + } | |
| 656 | +} | |
| 657 | + | |
| 658 | + | |
| 659 | +/* | |
| 660 | +** Convenience wrapper which calls builtin_request_js() for a series | |
| 661 | +** of builtin scripts named fossil.NAME.js. The first time it is | |
| 662 | +** called, it also calls builtin_emit_script_fossil_bootstrap() to | |
| 663 | +** initialize the window.fossil JS API. The first argument is the NAME | |
| 664 | +** part of the first API to emit. All subsequent arguments must be | |
| 665 | +** strings of the NAME part of additional fossil.NAME.js files, | |
| 666 | +** followed by a NULL argument to terminate the list. | |
| 667 | +** | |
| 668 | +** e.g. pass it ("fetch", "dom", "tabs", 0) to load those 3 | |
| 669 | +** APIs. Do not forget the trailing 0! | |
| 670 | +*/ | |
| 671 | +void builtin_emit_fossil_js_apis( const char * zApi, ... ) { | |
| 672 | + static int once = 0; | |
| 673 | + const char *zArg; | |
| 674 | + char * zName; | |
| 675 | + va_list vargs; | |
| 676 | + | |
| 677 | + if(0==once++){ | |
| 678 | + builtin_emit_script_fossil_bootstrap(1); | |
| 679 | + } | |
| 680 | + zName = mprintf("fossil.%s.js", zApi); | |
| 681 | + builtin_request_js(zName); | |
| 682 | + fossil_free(zName); | |
| 683 | + | |
| 684 | + va_start(vargs,zApi); | |
| 685 | + while( (zArg = va_arg (vargs, const char *))!=0 ){ | |
| 686 | + zName = mprintf("fossil.%s.js", zArg); | |
| 687 | + builtin_request_js(zName); | |
| 688 | + fossil_free(zName); | |
| 689 | + } | |
| 690 | + va_end(vargs); | |
| 691 | +} | |
| 692 | + | |
| 693 | +/* | |
| 694 | +** If builtin_get_js_delivery_mode() returns JS_BUNDLED then this | |
| 695 | +** function emits, via builtin_request_js(), all JS fossil.XYZ APIs | |
| 696 | +** which are not strictly specific to a single page, and then calls | |
| 697 | +** builtin_fulfill_js_requests(). The idea is that we can get better | |
| 698 | +** bundle caching and reduced HTTP requests by including all JS, | |
| 699 | +** rather than creating separate bundles on a per-page basis. It then | |
| 700 | +** returns true. As a special case, if this is called more than once | |
| 701 | +** in bundled mode, subsequent calls are a no-op. | |
| 702 | +** | |
| 703 | +** If the current JS delivery mode is *not* JS_BUNDLED then this | |
| 704 | +** function is a no-op and returns false. | |
| 705 | +*/ | |
| 706 | +int builtin_bundle_all_fossil_js_apis(void){ | |
| 707 | + static int bundled = 0; | |
| 708 | + if(JS_BUNDLED == builtin_get_js_delivery_mode()){ | |
| 709 | + if(!bundled){ | |
| 710 | + bundled = 1; | |
| 711 | + builtin_emit_fossil_js_apis("dom", "fetch", | |
| 712 | + "storage", "tabs", | |
| 713 | + "confirmer", "popupwidget", | |
| 714 | + "copybutton", "numbered-lines", | |
| 715 | + 0); | |
| 716 | + builtin_fulfill_js_requests(); | |
| 717 | + } | |
| 718 | + return 1; | |
| 719 | + }else{ | |
| 720 | + return 0; | |
| 721 | + } | |
| 722 | +} | |
| 564 | 723 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -258,10 +258,18 @@ | |
| 258 | }else if( !bSilent ){ |
| 259 | fossil_fatal("unknown javascript delivery mode \"%s\" - should be" |
| 260 | " one of: inline separate bundled", zMode); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | /* |
| 265 | ** The caller wants the Javascript file named by zFilename to be |
| 266 | ** included in the generated page. Add the file to the queue of |
| 267 | ** requested javascript resources, if it is not there already. |
| @@ -559,5 +567,156 @@ | |
| 559 | int rc = sqlite3_create_module(db, "builtin", &builtinVtabModule, 0); |
| 560 | return rc; |
| 561 | } |
| 562 | /* End of the builtin virtual table |
| 563 | ******************************************************************************/ |
| 564 |
| --- src/builtin.c | |
| +++ src/builtin.c | |
| @@ -258,10 +258,18 @@ | |
| 258 | }else if( !bSilent ){ |
| 259 | fossil_fatal("unknown javascript delivery mode \"%s\" - should be" |
| 260 | " one of: inline separate bundled", zMode); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | /* |
| 265 | ** Returns the current JS delivery mode: one of JS_INLINE, |
| 266 | ** JS_SEPARATE, JS_BUNDLED. |
| 267 | */ |
| 268 | int builtin_get_js_delivery_mode(void){ |
| 269 | return builtin.eDelivery; |
| 270 | } |
| 271 | |
| 272 | /* |
| 273 | ** The caller wants the Javascript file named by zFilename to be |
| 274 | ** included in the generated page. Add the file to the queue of |
| 275 | ** requested javascript resources, if it is not there already. |
| @@ -559,5 +567,156 @@ | |
| 567 | int rc = sqlite3_create_module(db, "builtin", &builtinVtabModule, 0); |
| 568 | return rc; |
| 569 | } |
| 570 | /* End of the builtin virtual table |
| 571 | ******************************************************************************/ |
| 572 | |
| 573 | |
| 574 | /* |
| 575 | ** The first time this is called, it emits code to install and |
| 576 | ** bootstrap the window.fossil object, using the built-in file |
| 577 | ** fossil.bootstrap.js (not to be confused with bootstrap.js). |
| 578 | ** |
| 579 | ** Subsequent calls are no-ops. |
| 580 | ** |
| 581 | ** It emits 2 parts: |
| 582 | ** |
| 583 | ** 1) window.fossil core object, some of which depends on C-level |
| 584 | ** runtime data. That part of the script is always emitted inline. If |
| 585 | ** addScriptTag is true then it is wrapped in its own SCRIPT tag, else |
| 586 | ** it is assumed that the caller already opened a tag. |
| 587 | ** |
| 588 | ** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). |
| 589 | */ |
| 590 | void builtin_emit_script_fossil_bootstrap(int addScriptTag){ |
| 591 | static int once = 0; |
| 592 | if(0==once++){ |
| 593 | char * zName; |
| 594 | /* Set up the generic/app-agnostic parts of window.fossil |
| 595 | ** which require C-level state... */ |
| 596 | if(addScriptTag!=0){ |
| 597 | style_emit_script_tag(0,0); |
| 598 | } |
| 599 | CX("(function(){\n"); |
| 600 | CX(/*MSIE NodeList.forEach polyfill, courtesy of Mozilla: |
| 601 | https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Polyfill |
| 602 | */ |
| 603 | "if(window.NodeList && !NodeList.prototype.forEach){" |
| 604 | "NodeList.prototype.forEach = Array.prototype.forEach;" |
| 605 | "}\n"); |
| 606 | CX("if(!window.fossil) window.fossil={};\n" |
| 607 | "window.fossil.version = %!j;\n" |
| 608 | /* fossil.rootPath is the top-most CGI/server path, |
| 609 | ** including a trailing slash. */ |
| 610 | "window.fossil.rootPath = %!j+'/';\n", |
| 611 | get_version(), g.zTop); |
| 612 | /* fossil.config = {...various config-level options...} */ |
| 613 | CX("window.fossil.config = {"); |
| 614 | zName = db_get("project-name", ""); |
| 615 | CX("projectName: %!j,\n", zName); |
| 616 | fossil_free(zName); |
| 617 | zName = db_get("short-project-name", ""); |
| 618 | CX("shortProjectName: %!j,\n", zName); |
| 619 | fossil_free(zName); |
| 620 | zName = db_get("project-code", ""); |
| 621 | CX("projectCode: %!j,\n", zName); |
| 622 | fossil_free(zName); |
| 623 | CX("/* Length of UUID hashes for display purposes. */"); |
| 624 | CX("hashDigits: %d, hashDigitsUrl: %d,\n", |
| 625 | hash_digits(0), hash_digits(1)); |
| 626 | CX("editStateMarkers: {" |
| 627 | "/*Symbolic markers to denote certain edit states.*/" |
| 628 | "isNew:'[+]', isModified:'[*]', isDeleted:'[-]'},\n"); |
| 629 | CX("confirmerButtonTicks: 3 " |
| 630 | "/*default fossil.confirmer tick count.*/\n"); |
| 631 | CX("};\n"/* fossil.config */); |
| 632 | #if 0 |
| 633 | /* Is it safe to emit the CSRF token here? Some pages add it |
| 634 | ** as a hidden form field. */ |
| 635 | if(g.zCsrfToken[0]!=0){ |
| 636 | CX("window.fossil.csrfToken = %!j;\n", |
| 637 | g.zCsrfToken); |
| 638 | } |
| 639 | #endif |
| 640 | /* |
| 641 | ** fossil.page holds info about the current page. This is also |
| 642 | ** where the current page "should" store any of its own |
| 643 | ** page-specific state, and it is reserved for that purpose. |
| 644 | */ |
| 645 | CX("window.fossil.page = {" |
| 646 | "name:\"%T\"" |
| 647 | "};\n", g.zPath); |
| 648 | CX("})();\n"); |
| 649 | if(addScriptTag!=0){ |
| 650 | style_emit_script_tag(1,0); |
| 651 | } |
| 652 | /* The remaining window.fossil bootstrap code is not dependent on |
| 653 | ** C-runtime state... */ |
| 654 | builtin_request_js("fossil.bootstrap.js"); |
| 655 | } |
| 656 | } |
| 657 | |
| 658 | |
| 659 | /* |
| 660 | ** Convenience wrapper which calls builtin_request_js() for a series |
| 661 | ** of builtin scripts named fossil.NAME.js. The first time it is |
| 662 | ** called, it also calls builtin_emit_script_fossil_bootstrap() to |
| 663 | ** initialize the window.fossil JS API. The first argument is the NAME |
| 664 | ** part of the first API to emit. All subsequent arguments must be |
| 665 | ** strings of the NAME part of additional fossil.NAME.js files, |
| 666 | ** followed by a NULL argument to terminate the list. |
| 667 | ** |
| 668 | ** e.g. pass it ("fetch", "dom", "tabs", 0) to load those 3 |
| 669 | ** APIs. Do not forget the trailing 0! |
| 670 | */ |
| 671 | void builtin_emit_fossil_js_apis( const char * zApi, ... ) { |
| 672 | static int once = 0; |
| 673 | const char *zArg; |
| 674 | char * zName; |
| 675 | va_list vargs; |
| 676 | |
| 677 | if(0==once++){ |
| 678 | builtin_emit_script_fossil_bootstrap(1); |
| 679 | } |
| 680 | zName = mprintf("fossil.%s.js", zApi); |
| 681 | builtin_request_js(zName); |
| 682 | fossil_free(zName); |
| 683 | |
| 684 | va_start(vargs,zApi); |
| 685 | while( (zArg = va_arg (vargs, const char *))!=0 ){ |
| 686 | zName = mprintf("fossil.%s.js", zArg); |
| 687 | builtin_request_js(zName); |
| 688 | fossil_free(zName); |
| 689 | } |
| 690 | va_end(vargs); |
| 691 | } |
| 692 | |
| 693 | /* |
| 694 | ** If builtin_get_js_delivery_mode() returns JS_BUNDLED then this |
| 695 | ** function emits, via builtin_request_js(), all JS fossil.XYZ APIs |
| 696 | ** which are not strictly specific to a single page, and then calls |
| 697 | ** builtin_fulfill_js_requests(). The idea is that we can get better |
| 698 | ** bundle caching and reduced HTTP requests by including all JS, |
| 699 | ** rather than creating separate bundles on a per-page basis. It then |
| 700 | ** returns true. As a special case, if this is called more than once |
| 701 | ** in bundled mode, subsequent calls are a no-op. |
| 702 | ** |
| 703 | ** If the current JS delivery mode is *not* JS_BUNDLED then this |
| 704 | ** function is a no-op and returns false. |
| 705 | */ |
| 706 | int builtin_bundle_all_fossil_js_apis(void){ |
| 707 | static int bundled = 0; |
| 708 | if(JS_BUNDLED == builtin_get_js_delivery_mode()){ |
| 709 | if(!bundled){ |
| 710 | bundled = 1; |
| 711 | builtin_emit_fossil_js_apis("dom", "fetch", |
| 712 | "storage", "tabs", |
| 713 | "confirmer", "popupwidget", |
| 714 | "copybutton", "numbered-lines", |
| 715 | 0); |
| 716 | builtin_fulfill_js_requests(); |
| 717 | } |
| 718 | return 1; |
| 719 | }else{ |
| 720 | return 0; |
| 721 | } |
| 722 | } |
| 723 |
+1
-1
| --- src/default.css | ||
| +++ src/default.css | ||
| @@ -1313,11 +1313,11 @@ | ||
| 1313 | 1313 | max-width: 1rem; |
| 1314 | 1314 | min-height: 1rem; |
| 1315 | 1315 | max-height: 1rem; |
| 1316 | 1316 | font-size: 0.9em; |
| 1317 | 1317 | border-radius: 0.5rem; |
| 1318 | - background-color: rgba(54, 54, 255,0.4); | |
| 1318 | + background-color: rgba(54, 54, 255,1); | |
| 1319 | 1319 | color: rgb(255, 255, 255); |
| 1320 | 1320 | cursor: pointer; |
| 1321 | 1321 | font-family: monspace; |
| 1322 | 1322 | text-align: center; |
| 1323 | 1323 | margin: 0 0 0 0.35em; |
| 1324 | 1324 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1313,11 +1313,11 @@ | |
| 1313 | max-width: 1rem; |
| 1314 | min-height: 1rem; |
| 1315 | max-height: 1rem; |
| 1316 | font-size: 0.9em; |
| 1317 | border-radius: 0.5rem; |
| 1318 | background-color: rgba(54, 54, 255,0.4); |
| 1319 | color: rgb(255, 255, 255); |
| 1320 | cursor: pointer; |
| 1321 | font-family: monspace; |
| 1322 | text-align: center; |
| 1323 | margin: 0 0 0 0.35em; |
| 1324 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1313,11 +1313,11 @@ | |
| 1313 | max-width: 1rem; |
| 1314 | min-height: 1rem; |
| 1315 | max-height: 1rem; |
| 1316 | font-size: 0.9em; |
| 1317 | border-radius: 0.5rem; |
| 1318 | background-color: rgba(54, 54, 255,1); |
| 1319 | color: rgb(255, 255, 255); |
| 1320 | cursor: pointer; |
| 1321 | font-family: monspace; |
| 1322 | text-align: center; |
| 1323 | margin: 0 0 0 0.35em; |
| 1324 |
+21
-19
| --- src/fileedit.c | ||
| +++ src/fileedit.c | ||
| @@ -1705,16 +1705,20 @@ | ||
| 1705 | 1705 | "data-tab-parent='fileedit-tabs' " |
| 1706 | 1706 | "data-tab-label='File Content' " |
| 1707 | 1707 | "class='hidden'" |
| 1708 | 1708 | ">"); |
| 1709 | 1709 | CX("<div class='flex-container flex-row child-gap-small'>"); |
| 1710 | - CX("<button class='fileedit-content-reload confirmer' " | |
| 1711 | - "title='Reload the file from the server, discarding " | |
| 1710 | + CX("<div class='input-with-label'>" | |
| 1711 | + "<button class='fileedit-content-reload confirmer' " | |
| 1712 | + ">Discard & Reload</button>" | |
| 1713 | + "<div class='help-buttonlet'>" | |
| 1714 | + "Reload the file from the server, discarding " | |
| 1712 | 1715 | "any local edits. To help avoid accidental loss of " |
| 1713 | 1716 | "edits, it requires confirmation (a second click) within " |
| 1714 | - "a few seconds or it will not reload.'" | |
| 1715 | - ">Discard & Reload</button>"); | |
| 1717 | + "a few seconds or it will not reload." | |
| 1718 | + "</div>" | |
| 1719 | + "</div>"); | |
| 1716 | 1720 | style_select_list_int("select-font-size", |
| 1717 | 1721 | "editor_font_size", "Editor font size", |
| 1718 | 1722 | NULL/*tooltip*/, |
| 1719 | 1723 | 100, |
| 1720 | 1724 | "100%", 100, "125%", 125, |
| @@ -1746,16 +1750,19 @@ | ||
| 1746 | 1750 | /* ^^^ fossil.page[methodName](content, callback) */ |
| 1747 | 1751 | "data-f-preview-to='#fileedit-tab-preview-wrapper' " |
| 1748 | 1752 | /* ^^^ dest elem ID */ |
| 1749 | 1753 | ">Refresh</button>"); |
| 1750 | 1754 | /* Toggle auto-update of preview when the Preview tab is selected. */ |
| 1751 | - style_labeled_checkbox("cb-preview-autoupdate", | |
| 1752 | - NULL, | |
| 1753 | - "Auto-refresh?", | |
| 1754 | - "1", 1, | |
| 1755 | - "If on, the preview will automatically " | |
| 1756 | - "refresh when this tab is selected."); | |
| 1755 | + CX("<div class='input-with-label'>" | |
| 1756 | + "<input type='checkbox' value='1' " | |
| 1757 | + "id='cb-preview-autorefresh' checked>" | |
| 1758 | + "<label for='cb-preview-autorefresh'>Auto-refresh?</label>" | |
| 1759 | + "<div class='help-buttonlet'>" | |
| 1760 | + "If on, the preview will automatically " | |
| 1761 | + "refresh (if needed) when this tab is selected." | |
| 1762 | + "</div>" | |
| 1763 | + "</div>"); | |
| 1757 | 1764 | |
| 1758 | 1765 | /* Default preview rendering mode selection... */ |
| 1759 | 1766 | previewRenderMode = zFileMime |
| 1760 | 1767 | ? ajax_render_mode_for_mimetype(zFileMime) |
| 1761 | 1768 | : AJAX_RENDER_GUESS; |
| @@ -1980,19 +1987,14 @@ | ||
| 1980 | 1987 | CX("</ul>"); |
| 1981 | 1988 | } |
| 1982 | 1989 | CX("</div>"/*#fileedit-tab-help*/); |
| 1983 | 1990 | |
| 1984 | 1991 | builtin_request_js("sbsdiff.js"); |
| 1985 | -#if 0 | |
| 1986 | - style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", | |
| 1987 | - "storage", 0); | |
| 1988 | -#else | |
| 1989 | - style_emit_all_fossil_js_apis(); | |
| 1990 | - builtin_fulfill_js_requests(); | |
| 1991 | - builtin_request_js("fossil.page.fileedit.js"); | |
| 1992 | -#endif | |
| 1993 | - builtin_fulfill_js_requests(); | |
| 1992 | + if(!builtin_bundle_all_fossil_js_apis()){ | |
| 1993 | + builtin_emit_fossil_js_apis("fetch", "dom", "tabs", "confirmer", | |
| 1994 | + "storage", 0); | |
| 1995 | + } | |
| 1994 | 1996 | /* |
| 1995 | 1997 | ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is |
| 1996 | 1998 | ** used for dynamically toggling certain UI components on and off. |
| 1997 | 1999 | ** Must come after window.fossil has been intialized and before |
| 1998 | 2000 | ** fossil.page.fileedit.js. Potential TODO: move this into the |
| 1999 | 2001 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1705,16 +1705,20 @@ | |
| 1705 | "data-tab-parent='fileedit-tabs' " |
| 1706 | "data-tab-label='File Content' " |
| 1707 | "class='hidden'" |
| 1708 | ">"); |
| 1709 | CX("<div class='flex-container flex-row child-gap-small'>"); |
| 1710 | CX("<button class='fileedit-content-reload confirmer' " |
| 1711 | "title='Reload the file from the server, discarding " |
| 1712 | "any local edits. To help avoid accidental loss of " |
| 1713 | "edits, it requires confirmation (a second click) within " |
| 1714 | "a few seconds or it will not reload.'" |
| 1715 | ">Discard & Reload</button>"); |
| 1716 | style_select_list_int("select-font-size", |
| 1717 | "editor_font_size", "Editor font size", |
| 1718 | NULL/*tooltip*/, |
| 1719 | 100, |
| 1720 | "100%", 100, "125%", 125, |
| @@ -1746,16 +1750,19 @@ | |
| 1746 | /* ^^^ fossil.page[methodName](content, callback) */ |
| 1747 | "data-f-preview-to='#fileedit-tab-preview-wrapper' " |
| 1748 | /* ^^^ dest elem ID */ |
| 1749 | ">Refresh</button>"); |
| 1750 | /* Toggle auto-update of preview when the Preview tab is selected. */ |
| 1751 | style_labeled_checkbox("cb-preview-autoupdate", |
| 1752 | NULL, |
| 1753 | "Auto-refresh?", |
| 1754 | "1", 1, |
| 1755 | "If on, the preview will automatically " |
| 1756 | "refresh when this tab is selected."); |
| 1757 | |
| 1758 | /* Default preview rendering mode selection... */ |
| 1759 | previewRenderMode = zFileMime |
| 1760 | ? ajax_render_mode_for_mimetype(zFileMime) |
| 1761 | : AJAX_RENDER_GUESS; |
| @@ -1980,19 +1987,14 @@ | |
| 1980 | CX("</ul>"); |
| 1981 | } |
| 1982 | CX("</div>"/*#fileedit-tab-help*/); |
| 1983 | |
| 1984 | builtin_request_js("sbsdiff.js"); |
| 1985 | #if 0 |
| 1986 | style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", |
| 1987 | "storage", 0); |
| 1988 | #else |
| 1989 | style_emit_all_fossil_js_apis(); |
| 1990 | builtin_fulfill_js_requests(); |
| 1991 | builtin_request_js("fossil.page.fileedit.js"); |
| 1992 | #endif |
| 1993 | builtin_fulfill_js_requests(); |
| 1994 | /* |
| 1995 | ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is |
| 1996 | ** used for dynamically toggling certain UI components on and off. |
| 1997 | ** Must come after window.fossil has been intialized and before |
| 1998 | ** fossil.page.fileedit.js. Potential TODO: move this into the |
| 1999 |
| --- src/fileedit.c | |
| +++ src/fileedit.c | |
| @@ -1705,16 +1705,20 @@ | |
| 1705 | "data-tab-parent='fileedit-tabs' " |
| 1706 | "data-tab-label='File Content' " |
| 1707 | "class='hidden'" |
| 1708 | ">"); |
| 1709 | CX("<div class='flex-container flex-row child-gap-small'>"); |
| 1710 | CX("<div class='input-with-label'>" |
| 1711 | "<button class='fileedit-content-reload confirmer' " |
| 1712 | ">Discard & Reload</button>" |
| 1713 | "<div class='help-buttonlet'>" |
| 1714 | "Reload the file from the server, discarding " |
| 1715 | "any local edits. To help avoid accidental loss of " |
| 1716 | "edits, it requires confirmation (a second click) within " |
| 1717 | "a few seconds or it will not reload." |
| 1718 | "</div>" |
| 1719 | "</div>"); |
| 1720 | style_select_list_int("select-font-size", |
| 1721 | "editor_font_size", "Editor font size", |
| 1722 | NULL/*tooltip*/, |
| 1723 | 100, |
| 1724 | "100%", 100, "125%", 125, |
| @@ -1746,16 +1750,19 @@ | |
| 1750 | /* ^^^ fossil.page[methodName](content, callback) */ |
| 1751 | "data-f-preview-to='#fileedit-tab-preview-wrapper' " |
| 1752 | /* ^^^ dest elem ID */ |
| 1753 | ">Refresh</button>"); |
| 1754 | /* Toggle auto-update of preview when the Preview tab is selected. */ |
| 1755 | CX("<div class='input-with-label'>" |
| 1756 | "<input type='checkbox' value='1' " |
| 1757 | "id='cb-preview-autorefresh' checked>" |
| 1758 | "<label for='cb-preview-autorefresh'>Auto-refresh?</label>" |
| 1759 | "<div class='help-buttonlet'>" |
| 1760 | "If on, the preview will automatically " |
| 1761 | "refresh (if needed) when this tab is selected." |
| 1762 | "</div>" |
| 1763 | "</div>"); |
| 1764 | |
| 1765 | /* Default preview rendering mode selection... */ |
| 1766 | previewRenderMode = zFileMime |
| 1767 | ? ajax_render_mode_for_mimetype(zFileMime) |
| 1768 | : AJAX_RENDER_GUESS; |
| @@ -1980,19 +1987,14 @@ | |
| 1987 | CX("</ul>"); |
| 1988 | } |
| 1989 | CX("</div>"/*#fileedit-tab-help*/); |
| 1990 | |
| 1991 | builtin_request_js("sbsdiff.js"); |
| 1992 | if(!builtin_bundle_all_fossil_js_apis()){ |
| 1993 | builtin_emit_fossil_js_apis("fetch", "dom", "tabs", "confirmer", |
| 1994 | "storage", 0); |
| 1995 | } |
| 1996 | /* |
| 1997 | ** Set up a JS-side mapping of the AJAX_RENDER_xyz values. This is |
| 1998 | ** used for dynamically toggling certain UI components on and off. |
| 1999 | ** Must come after window.fossil has been intialized and before |
| 2000 | ** fossil.page.fileedit.js. Potential TODO: move this into the |
| 2001 |
+1
-1
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -804,11 +804,11 @@ | ||
| 804 | 804 | |
| 805 | 805 | /* Display the thread. */ |
| 806 | 806 | forum_display_thread(froot, fpid, mode, bUnf, bHist); |
| 807 | 807 | |
| 808 | 808 | /* Emit Forum Javascript. */ |
| 809 | - style_emit_script_fossil_bootstrap(1); | |
| 809 | + builtin_emit_script_fossil_bootstrap(1); | |
| 810 | 810 | builtin_request_js("forum.js"); |
| 811 | 811 | builtin_request_js("fossil.dom.js"); |
| 812 | 812 | builtin_request_js("fossil.page.forumpost.js"); |
| 813 | 813 | |
| 814 | 814 | /* Emit the page style. */ |
| 815 | 815 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -804,11 +804,11 @@ | |
| 804 | |
| 805 | /* Display the thread. */ |
| 806 | forum_display_thread(froot, fpid, mode, bUnf, bHist); |
| 807 | |
| 808 | /* Emit Forum Javascript. */ |
| 809 | style_emit_script_fossil_bootstrap(1); |
| 810 | builtin_request_js("forum.js"); |
| 811 | builtin_request_js("fossil.dom.js"); |
| 812 | builtin_request_js("fossil.page.forumpost.js"); |
| 813 | |
| 814 | /* Emit the page style. */ |
| 815 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -804,11 +804,11 @@ | |
| 804 | |
| 805 | /* Display the thread. */ |
| 806 | forum_display_thread(froot, fpid, mode, bUnf, bHist); |
| 807 | |
| 808 | /* Emit Forum Javascript. */ |
| 809 | builtin_emit_script_fossil_bootstrap(1); |
| 810 | builtin_request_js("forum.js"); |
| 811 | builtin_request_js("fossil.dom.js"); |
| 812 | builtin_request_js("fossil.page.forumpost.js"); |
| 813 | |
| 814 | /* Emit the page style. */ |
| 815 |
+4
-4
| --- src/fossil.bootstrap.js | ||
| +++ src/fossil.bootstrap.js | ||
| @@ -5,18 +5,18 @@ | ||
| 5 | 5 | */ |
| 6 | 6 | if(typeof window.CustomEvent === "function") return false; |
| 7 | 7 | window.CustomEvent = function(event, params) { |
| 8 | 8 | if(!params) params = {bubbles: false, cancelable: false, detail: null}; |
| 9 | 9 | const evt = document.createEvent('CustomEvent'); |
| 10 | - evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); | |
| 10 | + evt.initCustomEvent( event, !!params.bubbles, !!params.cancelable, params.detail ); | |
| 11 | 11 | return evt; |
| 12 | 12 | }; |
| 13 | 13 | })(); |
| 14 | 14 | (function(global){ |
| 15 | - /* Bootstrapping bits for the global.fossil object. Must be | |
| 16 | - loaded after style.c:style_emit_script_tag() has initialized | |
| 17 | - that object. | |
| 15 | + /* Bootstrapping bits for the global.fossil object. Must be loaded | |
| 16 | + after style.c:builtin_emit_script_fossil_bootstrap() has | |
| 17 | + initialized that object. | |
| 18 | 18 | */ |
| 19 | 19 | |
| 20 | 20 | const F = global.fossil; |
| 21 | 21 | |
| 22 | 22 | /** |
| 23 | 23 |
| --- src/fossil.bootstrap.js | |
| +++ src/fossil.bootstrap.js | |
| @@ -5,18 +5,18 @@ | |
| 5 | */ |
| 6 | if(typeof window.CustomEvent === "function") return false; |
| 7 | window.CustomEvent = function(event, params) { |
| 8 | if(!params) params = {bubbles: false, cancelable: false, detail: null}; |
| 9 | const evt = document.createEvent('CustomEvent'); |
| 10 | evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); |
| 11 | return evt; |
| 12 | }; |
| 13 | })(); |
| 14 | (function(global){ |
| 15 | /* Bootstrapping bits for the global.fossil object. Must be |
| 16 | loaded after style.c:style_emit_script_tag() has initialized |
| 17 | that object. |
| 18 | */ |
| 19 | |
| 20 | const F = global.fossil; |
| 21 | |
| 22 | /** |
| 23 |
| --- src/fossil.bootstrap.js | |
| +++ src/fossil.bootstrap.js | |
| @@ -5,18 +5,18 @@ | |
| 5 | */ |
| 6 | if(typeof window.CustomEvent === "function") return false; |
| 7 | window.CustomEvent = function(event, params) { |
| 8 | if(!params) params = {bubbles: false, cancelable: false, detail: null}; |
| 9 | const evt = document.createEvent('CustomEvent'); |
| 10 | evt.initCustomEvent( event, !!params.bubbles, !!params.cancelable, params.detail ); |
| 11 | return evt; |
| 12 | }; |
| 13 | })(); |
| 14 | (function(global){ |
| 15 | /* Bootstrapping bits for the global.fossil object. Must be loaded |
| 16 | after style.c:builtin_emit_script_fossil_bootstrap() has |
| 17 | initialized that object. |
| 18 | */ |
| 19 | |
| 20 | const F = global.fossil; |
| 21 | |
| 22 | /** |
| 23 |
+13
-10
| --- src/fossil.page.fileedit.js | ||
| +++ src/fossil.page.fileedit.js | ||
| @@ -464,23 +464,26 @@ | ||
| 464 | 464 | const wrapper = D.addClass( |
| 465 | 465 | D.attr(D.div(),'id','fileedit-stash-selector'), |
| 466 | 466 | 'input-with-label' |
| 467 | 467 | ); |
| 468 | 468 | const sel = this.e.select = D.select(); |
| 469 | - const btnClear = this.e.btnClear | |
| 470 | - = D.button("Discard Edits"); | |
| 469 | + const btnClear = this.e.btnClear = D.button("Discard Edits"), | |
| 470 | + btnHelp = D.append( | |
| 471 | + D.addClass(D.div(), "help-buttonlet"), | |
| 472 | + 'Locally-edited files. Timestamps are the last local edit time. ', | |
| 473 | + 'Only the ',P.config.defaultMaxStashSize,' most recent files ', | |
| 474 | + 'are retained. Saving or reloading a file removes it from this list. ', | |
| 475 | + D.append(D.code(),'localStorage'),' uses browser-local persistent storage. ', | |
| 476 | + D.append(D.code(),'sessionStorage'),' uses storage local to this browser tab.' | |
| 477 | + ); | |
| 478 | + | |
| 471 | 479 | D.append(wrapper, "Local edits (", |
| 472 | 480 | D.append(D.code(), |
| 473 | 481 | F.storage.storageImplName()), |
| 474 | 482 | "):", |
| 475 | - sel, btnClear); | |
| 476 | - D.attr(wrapper, "title", [ | |
| 477 | - 'Locally-edited files. Timestamps are the last local edit time.', | |
| 478 | - 'Only the',P.config.defaultMaxStashSize,'most recent checkin/file', | |
| 479 | - 'combinations are retained.', | |
| 480 | - 'Committing or reloading a file removes it from this list.' | |
| 481 | - ].join(' ')); | |
| 483 | + btnHelp, sel, btnClear); | |
| 484 | + F.helpButtonlets.setup(btnHelp); | |
| 482 | 485 | D.option(D.disable(sel), "(empty)"); |
| 483 | 486 | F.page.addEventListener('fileedit-stash-updated',(e)=>this.updateList(e.detail)); |
| 484 | 487 | F.page.addEventListener('fileedit-file-loaded',(e)=>this.updateList($stash, e.detail)); |
| 485 | 488 | sel.addEventListener('change',function(e){ |
| 486 | 489 | const opt = this.selectedOptions[0]; |
| @@ -656,11 +659,11 @@ | ||
| 656 | 659 | selectEolWrap: E('#select-eol-style'), |
| 657 | 660 | selectEol: E('#select-eol-style select[name=eol]'), |
| 658 | 661 | selectFontSizeWrap: E('#select-font-size'), |
| 659 | 662 | selectDiffWS: E('select[name=diff_ws]'), |
| 660 | 663 | cbLineNumbersWrap: E('#cb-line-numbers'), |
| 661 | - cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'), | |
| 664 | + cbAutoPreview: E('#cb-preview-autorefresh'), | |
| 662 | 665 | previewTarget: E('#fileedit-tab-preview-wrapper'), |
| 663 | 666 | manifestTarget: E('#fileedit-manifest'), |
| 664 | 667 | diffTarget: E('#fileedit-tab-diff-wrapper'), |
| 665 | 668 | cbIsExe: E('input[type=checkbox][name=exec_bit]'), |
| 666 | 669 | cbManifest: E('input[type=checkbox][name=include_manifest]'), |
| 667 | 670 |
| --- src/fossil.page.fileedit.js | |
| +++ src/fossil.page.fileedit.js | |
| @@ -464,23 +464,26 @@ | |
| 464 | const wrapper = D.addClass( |
| 465 | D.attr(D.div(),'id','fileedit-stash-selector'), |
| 466 | 'input-with-label' |
| 467 | ); |
| 468 | const sel = this.e.select = D.select(); |
| 469 | const btnClear = this.e.btnClear |
| 470 | = D.button("Discard Edits"); |
| 471 | D.append(wrapper, "Local edits (", |
| 472 | D.append(D.code(), |
| 473 | F.storage.storageImplName()), |
| 474 | "):", |
| 475 | sel, btnClear); |
| 476 | D.attr(wrapper, "title", [ |
| 477 | 'Locally-edited files. Timestamps are the last local edit time.', |
| 478 | 'Only the',P.config.defaultMaxStashSize,'most recent checkin/file', |
| 479 | 'combinations are retained.', |
| 480 | 'Committing or reloading a file removes it from this list.' |
| 481 | ].join(' ')); |
| 482 | D.option(D.disable(sel), "(empty)"); |
| 483 | F.page.addEventListener('fileedit-stash-updated',(e)=>this.updateList(e.detail)); |
| 484 | F.page.addEventListener('fileedit-file-loaded',(e)=>this.updateList($stash, e.detail)); |
| 485 | sel.addEventListener('change',function(e){ |
| 486 | const opt = this.selectedOptions[0]; |
| @@ -656,11 +659,11 @@ | |
| 656 | selectEolWrap: E('#select-eol-style'), |
| 657 | selectEol: E('#select-eol-style select[name=eol]'), |
| 658 | selectFontSizeWrap: E('#select-font-size'), |
| 659 | selectDiffWS: E('select[name=diff_ws]'), |
| 660 | cbLineNumbersWrap: E('#cb-line-numbers'), |
| 661 | cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'), |
| 662 | previewTarget: E('#fileedit-tab-preview-wrapper'), |
| 663 | manifestTarget: E('#fileedit-manifest'), |
| 664 | diffTarget: E('#fileedit-tab-diff-wrapper'), |
| 665 | cbIsExe: E('input[type=checkbox][name=exec_bit]'), |
| 666 | cbManifest: E('input[type=checkbox][name=include_manifest]'), |
| 667 |
| --- src/fossil.page.fileedit.js | |
| +++ src/fossil.page.fileedit.js | |
| @@ -464,23 +464,26 @@ | |
| 464 | const wrapper = D.addClass( |
| 465 | D.attr(D.div(),'id','fileedit-stash-selector'), |
| 466 | 'input-with-label' |
| 467 | ); |
| 468 | const sel = this.e.select = D.select(); |
| 469 | const btnClear = this.e.btnClear = D.button("Discard Edits"), |
| 470 | btnHelp = D.append( |
| 471 | D.addClass(D.div(), "help-buttonlet"), |
| 472 | 'Locally-edited files. Timestamps are the last local edit time. ', |
| 473 | 'Only the ',P.config.defaultMaxStashSize,' most recent files ', |
| 474 | 'are retained. Saving or reloading a file removes it from this list. ', |
| 475 | D.append(D.code(),'localStorage'),' uses browser-local persistent storage. ', |
| 476 | D.append(D.code(),'sessionStorage'),' uses storage local to this browser tab.' |
| 477 | ); |
| 478 | |
| 479 | D.append(wrapper, "Local edits (", |
| 480 | D.append(D.code(), |
| 481 | F.storage.storageImplName()), |
| 482 | "):", |
| 483 | btnHelp, sel, btnClear); |
| 484 | F.helpButtonlets.setup(btnHelp); |
| 485 | D.option(D.disable(sel), "(empty)"); |
| 486 | F.page.addEventListener('fileedit-stash-updated',(e)=>this.updateList(e.detail)); |
| 487 | F.page.addEventListener('fileedit-file-loaded',(e)=>this.updateList($stash, e.detail)); |
| 488 | sel.addEventListener('change',function(e){ |
| 489 | const opt = this.selectedOptions[0]; |
| @@ -656,11 +659,11 @@ | |
| 659 | selectEolWrap: E('#select-eol-style'), |
| 660 | selectEol: E('#select-eol-style select[name=eol]'), |
| 661 | selectFontSizeWrap: E('#select-font-size'), |
| 662 | selectDiffWS: E('select[name=diff_ws]'), |
| 663 | cbLineNumbersWrap: E('#cb-line-numbers'), |
| 664 | cbAutoPreview: E('#cb-preview-autorefresh'), |
| 665 | previewTarget: E('#fileedit-tab-preview-wrapper'), |
| 666 | manifestTarget: E('#fileedit-manifest'), |
| 667 | diffTarget: E('#fileedit-tab-diff-wrapper'), |
| 668 | cbIsExe: E('input[type=checkbox][name=exec_bit]'), |
| 669 | cbManifest: E('input[type=checkbox][name=include_manifest]'), |
| 670 |
+1
-1
| --- src/fossil.page.wikiedit.js | ||
| +++ src/fossil.page.wikiedit.js | ||
| @@ -848,11 +848,11 @@ | ||
| 848 | 848 | btnSave: E("button.wikiedit-save"), |
| 849 | 849 | btnSaveClose: E("button.wikiedit-save-close"), |
| 850 | 850 | selectMimetype: E('select[name=mimetype]'), |
| 851 | 851 | selectFontSizeWrap: E('#select-font-size'), |
| 852 | 852 | // selectDiffWS: E('select[name=diff_ws]'), |
| 853 | - cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'), | |
| 853 | + cbAutoPreview: E('#cb-preview-autorefresh'), | |
| 854 | 854 | previewTarget: E('#wikiedit-tab-preview-wrapper'), |
| 855 | 855 | diffTarget: E('#wikiedit-tab-diff-wrapper'), |
| 856 | 856 | editStatus: E('#wikiedit-edit-status'), |
| 857 | 857 | tabContainer: E('#wikiedit-tabs'), |
| 858 | 858 | tabs:{ |
| 859 | 859 |
| --- src/fossil.page.wikiedit.js | |
| +++ src/fossil.page.wikiedit.js | |
| @@ -848,11 +848,11 @@ | |
| 848 | btnSave: E("button.wikiedit-save"), |
| 849 | btnSaveClose: E("button.wikiedit-save-close"), |
| 850 | selectMimetype: E('select[name=mimetype]'), |
| 851 | selectFontSizeWrap: E('#select-font-size'), |
| 852 | // selectDiffWS: E('select[name=diff_ws]'), |
| 853 | cbAutoPreview: E('#cb-preview-autoupdate > input[type=checkbox]'), |
| 854 | previewTarget: E('#wikiedit-tab-preview-wrapper'), |
| 855 | diffTarget: E('#wikiedit-tab-diff-wrapper'), |
| 856 | editStatus: E('#wikiedit-edit-status'), |
| 857 | tabContainer: E('#wikiedit-tabs'), |
| 858 | tabs:{ |
| 859 |
| --- src/fossil.page.wikiedit.js | |
| +++ src/fossil.page.wikiedit.js | |
| @@ -848,11 +848,11 @@ | |
| 848 | btnSave: E("button.wikiedit-save"), |
| 849 | btnSaveClose: E("button.wikiedit-save-close"), |
| 850 | selectMimetype: E('select[name=mimetype]'), |
| 851 | selectFontSizeWrap: E('#select-font-size'), |
| 852 | // selectDiffWS: E('select[name=diff_ws]'), |
| 853 | cbAutoPreview: E('#cb-preview-autorefresh'), |
| 854 | previewTarget: E('#wikiedit-tab-preview-wrapper'), |
| 855 | diffTarget: E('#wikiedit-tab-diff-wrapper'), |
| 856 | editStatus: E('#wikiedit-edit-status'), |
| 857 | tabContainer: E('#wikiedit-tabs'), |
| 858 | tabs:{ |
| 859 |
+22
-12
| --- src/info.c | ||
| +++ src/info.c | ||
| @@ -2024,24 +2024,33 @@ | ||
| 2024 | 2024 | ** zLn is the ?ln= parameter for the HTTP query. If there is an argument, |
| 2025 | 2025 | ** then highlight that line number and scroll to it once the page loads. |
| 2026 | 2026 | ** If there are two line numbers, highlight the range of lines. |
| 2027 | 2027 | ** Multiple ranges can be highlighed by adding additional line numbers |
| 2028 | 2028 | ** separated by a non-digit character (also not one of [-,.]). |
| 2029 | +** | |
| 2030 | +** If includeJS is true then the JS code associated with line | |
| 2031 | +** numbering is also emitted, else it is not. If this routine is | |
| 2032 | +** called multiple times in a single app run, the JS is emitted only | |
| 2033 | +** once. Note that when using this routine to emit Ajax responses, the | |
| 2034 | +** JS should be not be included, as it will not get imported properly | |
| 2035 | +** into the response's rendering. | |
| 2029 | 2036 | */ |
| 2030 | 2037 | void output_text_with_line_numbers( |
| 2031 | 2038 | const char *z, |
| 2032 | 2039 | int nZ, |
| 2033 | 2040 | const char *zName, |
| 2034 | - const char *zLn | |
| 2041 | + const char *zLn, | |
| 2042 | + int includeJS | |
| 2035 | 2043 | ){ |
| 2036 | 2044 | int iStart, iEnd; /* Start and end of region to highlight */ |
| 2037 | 2045 | int n = 0; /* Current line number */ |
| 2038 | 2046 | int i = 0; /* Loop index */ |
| 2039 | 2047 | int iTop = 0; /* Scroll so that this line is on top of screen. */ |
| 2040 | 2048 | int nLine = 0; /* content line count */ |
| 2041 | 2049 | int nSpans = 0; /* number of distinct zLn spans */ |
| 2042 | 2050 | const char *zExt = file_extension(zName); |
| 2051 | + static int emittedJS = 0; /* emitted shared JS yet? */ | |
| 2043 | 2052 | Stmt q; |
| 2044 | 2053 | |
| 2045 | 2054 | iStart = iEnd = atoi(zLn); |
| 2046 | 2055 | db_multi_exec( |
| 2047 | 2056 | "CREATE TEMP TABLE lnos(iStart INTEGER PRIMARY KEY, iEnd INTEGER)"); |
| @@ -2115,19 +2124,20 @@ | ||
| 2115 | 2124 | }else{ |
| 2116 | 2125 | cgi_append_content("<code>", -1); |
| 2117 | 2126 | } |
| 2118 | 2127 | cgi_printf("%z", htmlize(z, nZ)); |
| 2119 | 2128 | CX("</code></pre></td></tr></tbody></table>\n"); |
| 2120 | - if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){ | |
| 2121 | - builtin_request_js("scroll.js"); | |
| 2122 | - } | |
| 2123 | -#if 0 | |
| 2124 | - style_emit_fossil_js_apis(0, "dom", "copybutton", "popupwidget", | |
| 2125 | - "numbered-lines", 0); | |
| 2126 | -#else | |
| 2127 | - style_emit_all_fossil_js_apis(); | |
| 2128 | -#endif | |
| 2129 | + if(includeJS && !emittedJS){ | |
| 2130 | + emittedJS = 1; | |
| 2131 | + if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){ | |
| 2132 | + builtin_request_js("scroll.js"); | |
| 2133 | + } | |
| 2134 | + if(!builtin_bundle_all_fossil_js_apis()){ | |
| 2135 | + builtin_emit_fossil_js_apis("dom", "copybutton", "popupwidget", | |
| 2136 | + "numbered-lines", 0); | |
| 2137 | + } | |
| 2138 | + } | |
| 2129 | 2139 | } |
| 2130 | 2140 | |
| 2131 | 2141 | /* |
| 2132 | 2142 | ** COMMAND: test-line-numbers |
| 2133 | 2143 | ** |
| @@ -2148,11 +2158,11 @@ | ||
| 2148 | 2158 | zFilename = g.argv[2]; |
| 2149 | 2159 | fossil_print("%s %s\n", zFilename, zLn); |
| 2150 | 2160 | |
| 2151 | 2161 | blob_read_from_file(&content, zFilename, ExtFILE); |
| 2152 | 2162 | output_text_with_line_numbers(blob_str(&content), blob_size(&content), |
| 2153 | - zFilename, zLn); | |
| 2163 | + zFilename, zLn, 0); | |
| 2154 | 2164 | blob_reset(&content); |
| 2155 | 2165 | fossil_print("%b\n", cgi_output_blob()); |
| 2156 | 2166 | } |
| 2157 | 2167 | |
| 2158 | 2168 | /* |
| @@ -2460,11 +2470,11 @@ | ||
| 2460 | 2470 | " AND mlink.fid=%d", |
| 2461 | 2471 | rid); |
| 2462 | 2472 | zExt = zFileName ? file_extension(zFileName) : 0; |
| 2463 | 2473 | if( zLn ){ |
| 2464 | 2474 | output_text_with_line_numbers(z, blob_size(&content), |
| 2465 | - zFileName, zLn); | |
| 2475 | + zFileName, zLn, 1); | |
| 2466 | 2476 | }else if( zExt && zExt[1] ){ |
| 2467 | 2477 | @ <pre> |
| 2468 | 2478 | @ <code class="language-%s(zExt)">%h(z)</code> |
| 2469 | 2479 | @ </pre> |
| 2470 | 2480 | }else{ |
| 2471 | 2481 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -2024,24 +2024,33 @@ | |
| 2024 | ** zLn is the ?ln= parameter for the HTTP query. If there is an argument, |
| 2025 | ** then highlight that line number and scroll to it once the page loads. |
| 2026 | ** If there are two line numbers, highlight the range of lines. |
| 2027 | ** Multiple ranges can be highlighed by adding additional line numbers |
| 2028 | ** separated by a non-digit character (also not one of [-,.]). |
| 2029 | */ |
| 2030 | void output_text_with_line_numbers( |
| 2031 | const char *z, |
| 2032 | int nZ, |
| 2033 | const char *zName, |
| 2034 | const char *zLn |
| 2035 | ){ |
| 2036 | int iStart, iEnd; /* Start and end of region to highlight */ |
| 2037 | int n = 0; /* Current line number */ |
| 2038 | int i = 0; /* Loop index */ |
| 2039 | int iTop = 0; /* Scroll so that this line is on top of screen. */ |
| 2040 | int nLine = 0; /* content line count */ |
| 2041 | int nSpans = 0; /* number of distinct zLn spans */ |
| 2042 | const char *zExt = file_extension(zName); |
| 2043 | Stmt q; |
| 2044 | |
| 2045 | iStart = iEnd = atoi(zLn); |
| 2046 | db_multi_exec( |
| 2047 | "CREATE TEMP TABLE lnos(iStart INTEGER PRIMARY KEY, iEnd INTEGER)"); |
| @@ -2115,19 +2124,20 @@ | |
| 2115 | }else{ |
| 2116 | cgi_append_content("<code>", -1); |
| 2117 | } |
| 2118 | cgi_printf("%z", htmlize(z, nZ)); |
| 2119 | CX("</code></pre></td></tr></tbody></table>\n"); |
| 2120 | if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){ |
| 2121 | builtin_request_js("scroll.js"); |
| 2122 | } |
| 2123 | #if 0 |
| 2124 | style_emit_fossil_js_apis(0, "dom", "copybutton", "popupwidget", |
| 2125 | "numbered-lines", 0); |
| 2126 | #else |
| 2127 | style_emit_all_fossil_js_apis(); |
| 2128 | #endif |
| 2129 | } |
| 2130 | |
| 2131 | /* |
| 2132 | ** COMMAND: test-line-numbers |
| 2133 | ** |
| @@ -2148,11 +2158,11 @@ | |
| 2148 | zFilename = g.argv[2]; |
| 2149 | fossil_print("%s %s\n", zFilename, zLn); |
| 2150 | |
| 2151 | blob_read_from_file(&content, zFilename, ExtFILE); |
| 2152 | output_text_with_line_numbers(blob_str(&content), blob_size(&content), |
| 2153 | zFilename, zLn); |
| 2154 | blob_reset(&content); |
| 2155 | fossil_print("%b\n", cgi_output_blob()); |
| 2156 | } |
| 2157 | |
| 2158 | /* |
| @@ -2460,11 +2470,11 @@ | |
| 2460 | " AND mlink.fid=%d", |
| 2461 | rid); |
| 2462 | zExt = zFileName ? file_extension(zFileName) : 0; |
| 2463 | if( zLn ){ |
| 2464 | output_text_with_line_numbers(z, blob_size(&content), |
| 2465 | zFileName, zLn); |
| 2466 | }else if( zExt && zExt[1] ){ |
| 2467 | @ <pre> |
| 2468 | @ <code class="language-%s(zExt)">%h(z)</code> |
| 2469 | @ </pre> |
| 2470 | }else{ |
| 2471 |
| --- src/info.c | |
| +++ src/info.c | |
| @@ -2024,24 +2024,33 @@ | |
| 2024 | ** zLn is the ?ln= parameter for the HTTP query. If there is an argument, |
| 2025 | ** then highlight that line number and scroll to it once the page loads. |
| 2026 | ** If there are two line numbers, highlight the range of lines. |
| 2027 | ** Multiple ranges can be highlighed by adding additional line numbers |
| 2028 | ** separated by a non-digit character (also not one of [-,.]). |
| 2029 | ** |
| 2030 | ** If includeJS is true then the JS code associated with line |
| 2031 | ** numbering is also emitted, else it is not. If this routine is |
| 2032 | ** called multiple times in a single app run, the JS is emitted only |
| 2033 | ** once. Note that when using this routine to emit Ajax responses, the |
| 2034 | ** JS should be not be included, as it will not get imported properly |
| 2035 | ** into the response's rendering. |
| 2036 | */ |
| 2037 | void output_text_with_line_numbers( |
| 2038 | const char *z, |
| 2039 | int nZ, |
| 2040 | const char *zName, |
| 2041 | const char *zLn, |
| 2042 | int includeJS |
| 2043 | ){ |
| 2044 | int iStart, iEnd; /* Start and end of region to highlight */ |
| 2045 | int n = 0; /* Current line number */ |
| 2046 | int i = 0; /* Loop index */ |
| 2047 | int iTop = 0; /* Scroll so that this line is on top of screen. */ |
| 2048 | int nLine = 0; /* content line count */ |
| 2049 | int nSpans = 0; /* number of distinct zLn spans */ |
| 2050 | const char *zExt = file_extension(zName); |
| 2051 | static int emittedJS = 0; /* emitted shared JS yet? */ |
| 2052 | Stmt q; |
| 2053 | |
| 2054 | iStart = iEnd = atoi(zLn); |
| 2055 | db_multi_exec( |
| 2056 | "CREATE TEMP TABLE lnos(iStart INTEGER PRIMARY KEY, iEnd INTEGER)"); |
| @@ -2115,19 +2124,20 @@ | |
| 2124 | }else{ |
| 2125 | cgi_append_content("<code>", -1); |
| 2126 | } |
| 2127 | cgi_printf("%z", htmlize(z, nZ)); |
| 2128 | CX("</code></pre></td></tr></tbody></table>\n"); |
| 2129 | if(includeJS && !emittedJS){ |
| 2130 | emittedJS = 1; |
| 2131 | if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){ |
| 2132 | builtin_request_js("scroll.js"); |
| 2133 | } |
| 2134 | if(!builtin_bundle_all_fossil_js_apis()){ |
| 2135 | builtin_emit_fossil_js_apis("dom", "copybutton", "popupwidget", |
| 2136 | "numbered-lines", 0); |
| 2137 | } |
| 2138 | } |
| 2139 | } |
| 2140 | |
| 2141 | /* |
| 2142 | ** COMMAND: test-line-numbers |
| 2143 | ** |
| @@ -2148,11 +2158,11 @@ | |
| 2158 | zFilename = g.argv[2]; |
| 2159 | fossil_print("%s %s\n", zFilename, zLn); |
| 2160 | |
| 2161 | blob_read_from_file(&content, zFilename, ExtFILE); |
| 2162 | output_text_with_line_numbers(blob_str(&content), blob_size(&content), |
| 2163 | zFilename, zLn, 0); |
| 2164 | blob_reset(&content); |
| 2165 | fossil_print("%b\n", cgi_output_blob()); |
| 2166 | } |
| 2167 | |
| 2168 | /* |
| @@ -2460,11 +2470,11 @@ | |
| 2470 | " AND mlink.fid=%d", |
| 2471 | rid); |
| 2472 | zExt = zFileName ? file_extension(zFileName) : 0; |
| 2473 | if( zLn ){ |
| 2474 | output_text_with_line_numbers(z, blob_size(&content), |
| 2475 | zFileName, zLn, 1); |
| 2476 | }else if( zExt && zExt[1] ){ |
| 2477 | @ <pre> |
| 2478 | @ <code class="language-%s(zExt)">%h(z)</code> |
| 2479 | @ </pre> |
| 2480 | }else{ |
| 2481 |
-130
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -1416,95 +1416,10 @@ | ||
| 1416 | 1416 | CX("</div>\n"); |
| 1417 | 1417 | va_end(vargs); |
| 1418 | 1418 | fossil_free(zLabelID); |
| 1419 | 1419 | } |
| 1420 | 1420 | |
| 1421 | - | |
| 1422 | -/* | |
| 1423 | -** The first time this is called, it emits code to install and | |
| 1424 | -** bootstrap the window.fossil object, using the built-in file | |
| 1425 | -** fossil.bootstrap.js (not to be confused with bootstrap.js). | |
| 1426 | -** | |
| 1427 | -** Subsequent calls are no-ops. | |
| 1428 | -** | |
| 1429 | -** It emits 2 parts: | |
| 1430 | -** | |
| 1431 | -** 1) window.fossil core object, some of which depends on C-level | |
| 1432 | -** runtime data. That part of the script is always emitted inline. If | |
| 1433 | -** addScriptTag is true then it is wrapped in its own SCRIPT tag, else | |
| 1434 | -** it is assumed that the caller already opened a tag. | |
| 1435 | -** | |
| 1436 | -** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). | |
| 1437 | -*/ | |
| 1438 | -void style_emit_script_fossil_bootstrap(int addScriptTag){ | |
| 1439 | - static int once = 0; | |
| 1440 | - if(0==once++){ | |
| 1441 | - char * zName; | |
| 1442 | - /* Set up the generic/app-agnostic parts of window.fossil | |
| 1443 | - ** which require C-level state... */ | |
| 1444 | - if(addScriptTag!=0){ | |
| 1445 | - style_emit_script_tag(0,0); | |
| 1446 | - } | |
| 1447 | - CX("(function(){\n"); | |
| 1448 | - CX(/*MSIE NodeList.forEach polyfill, courtesy of Mozilla: | |
| 1449 | - https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Polyfill | |
| 1450 | - */ | |
| 1451 | - "if(window.NodeList && !NodeList.prototype.forEach){" | |
| 1452 | - "NodeList.prototype.forEach = Array.prototype.forEach;" | |
| 1453 | - "}\n"); | |
| 1454 | - CX("if(!window.fossil) window.fossil={};\n" | |
| 1455 | - "window.fossil.version = %!j;\n" | |
| 1456 | - /* fossil.rootPath is the top-most CGI/server path, | |
| 1457 | - ** including a trailing slash. */ | |
| 1458 | - "window.fossil.rootPath = %!j+'/';\n", | |
| 1459 | - get_version(), g.zTop); | |
| 1460 | - /* fossil.config = {...various config-level options...} */ | |
| 1461 | - CX("window.fossil.config = {"); | |
| 1462 | - zName = db_get("project-name", ""); | |
| 1463 | - CX("projectName: %!j,\n", zName); | |
| 1464 | - fossil_free(zName); | |
| 1465 | - zName = db_get("short-project-name", ""); | |
| 1466 | - CX("shortProjectName: %!j,\n", zName); | |
| 1467 | - fossil_free(zName); | |
| 1468 | - zName = db_get("project-code", ""); | |
| 1469 | - CX("projectCode: %!j,\n", zName); | |
| 1470 | - fossil_free(zName); | |
| 1471 | - CX("/* Length of UUID hashes for display purposes. */"); | |
| 1472 | - CX("hashDigits: %d, hashDigitsUrl: %d,\n", | |
| 1473 | - hash_digits(0), hash_digits(1)); | |
| 1474 | - CX("editStateMarkers: {" | |
| 1475 | - "/*Symbolic markers to denote certain edit states.*/" | |
| 1476 | - "isNew:'[+]', isModified:'[*]', isDeleted:'[-]'},\n"); | |
| 1477 | - CX("confirmerButtonTicks: 3 " | |
| 1478 | - "/*default fossil.confirmer tick count.*/\n"); | |
| 1479 | - CX("};\n"/* fossil.config */); | |
| 1480 | -#if 0 | |
| 1481 | - /* Is it safe to emit the CSRF token here? Some pages add it | |
| 1482 | - ** as a hidden form field. */ | |
| 1483 | - if(g.zCsrfToken[0]!=0){ | |
| 1484 | - CX("window.fossil.csrfToken = %!j;\n", | |
| 1485 | - g.zCsrfToken); | |
| 1486 | - } | |
| 1487 | -#endif | |
| 1488 | - /* | |
| 1489 | - ** fossil.page holds info about the current page. This is also | |
| 1490 | - ** where the current page "should" store any of its own | |
| 1491 | - ** page-specific state, and it is reserved for that purpose. | |
| 1492 | - */ | |
| 1493 | - CX("window.fossil.page = {" | |
| 1494 | - "name:\"%T\"" | |
| 1495 | - "};\n", g.zPath); | |
| 1496 | - CX("})();\n"); | |
| 1497 | - if(addScriptTag!=0){ | |
| 1498 | - style_emit_script_tag(1,0); | |
| 1499 | - } | |
| 1500 | - /* The remaining window.fossil bootstrap code is not dependent on | |
| 1501 | - ** C-runtime state... */ | |
| 1502 | - builtin_request_js("fossil.bootstrap.js"); | |
| 1503 | - } | |
| 1504 | -} | |
| 1505 | - | |
| 1506 | 1421 | /* |
| 1507 | 1422 | ** If passed 0 as its first argument, it emits a script opener tag |
| 1508 | 1423 | ** with this request's nonce. If passed non-0 it emits a script |
| 1509 | 1424 | ** closing tag. Mnemonic for remembering the order in which to pass 0 |
| 1510 | 1425 | ** or 1 as the first argument to this function: 0 comes before 1. |
| @@ -1530,50 +1445,5 @@ | ||
| 1530 | 1445 | } |
| 1531 | 1446 | }else{ |
| 1532 | 1447 | CX("</script>\n"); |
| 1533 | 1448 | } |
| 1534 | 1449 | } |
| 1535 | - | |
| 1536 | -/* | |
| 1537 | -** Convenience wrapper which calls builtin_request_js() for a series | |
| 1538 | -** of builtin scripts named fossil.NAME.js. The first time it is | |
| 1539 | -** called, it also calls style_emit_script_fossil_bootstrap() to | |
| 1540 | -** initialize the window.fossil JS API. The first argument is a | |
| 1541 | -** no-meaning dummy required by the va_start() interface. All | |
| 1542 | -** subsequent arguments must be strings of the NAME part of | |
| 1543 | -** fossil.NAME.js, followed by a NULL argument to terminate the list. | |
| 1544 | -** | |
| 1545 | -** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3 | |
| 1546 | -** APIs. Do not forget the trailing 0! | |
| 1547 | -*/ | |
| 1548 | -void style_emit_fossil_js_apis( int dummy, ... ) { | |
| 1549 | - static int once = 0; | |
| 1550 | - const char *zArg; | |
| 1551 | - char * zName; | |
| 1552 | - va_list vargs; | |
| 1553 | - | |
| 1554 | - if(0==once++){ | |
| 1555 | - style_emit_script_fossil_bootstrap(1); | |
| 1556 | - } | |
| 1557 | - va_start(vargs,dummy); | |
| 1558 | - while( (zArg = va_arg (vargs, const char *))!=0 ){ | |
| 1559 | - zName = mprintf("fossil.%s.js", zArg); | |
| 1560 | - builtin_request_js(zName); | |
| 1561 | - fossil_free(zName); | |
| 1562 | - } | |
| 1563 | - va_end(vargs); | |
| 1564 | -} | |
| 1565 | - | |
| 1566 | -/* | |
| 1567 | -** Emits, via builtin_request_js(), all JS fossil.XYZ APIs which are | |
| 1568 | -** not strictly specific to a single page. The idea is that we can get | |
| 1569 | -** better bundle caching and reduced HTTP requests by including all | |
| 1570 | -** JS, rather than creating separate bundles on a per-page basis. | |
| 1571 | -*/ | |
| 1572 | -void style_emit_all_fossil_js_apis(void){ | |
| 1573 | - style_emit_fossil_js_apis(0, | |
| 1574 | - "dom", "fetch", | |
| 1575 | - "storage", "tabs", | |
| 1576 | - "confirmer", "popupwidget", | |
| 1577 | - "copybutton", "numbered-lines", | |
| 1578 | - 0); | |
| 1579 | -} | |
| 1580 | 1450 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -1416,95 +1416,10 @@ | |
| 1416 | CX("</div>\n"); |
| 1417 | va_end(vargs); |
| 1418 | fossil_free(zLabelID); |
| 1419 | } |
| 1420 | |
| 1421 | |
| 1422 | /* |
| 1423 | ** The first time this is called, it emits code to install and |
| 1424 | ** bootstrap the window.fossil object, using the built-in file |
| 1425 | ** fossil.bootstrap.js (not to be confused with bootstrap.js). |
| 1426 | ** |
| 1427 | ** Subsequent calls are no-ops. |
| 1428 | ** |
| 1429 | ** It emits 2 parts: |
| 1430 | ** |
| 1431 | ** 1) window.fossil core object, some of which depends on C-level |
| 1432 | ** runtime data. That part of the script is always emitted inline. If |
| 1433 | ** addScriptTag is true then it is wrapped in its own SCRIPT tag, else |
| 1434 | ** it is assumed that the caller already opened a tag. |
| 1435 | ** |
| 1436 | ** 2) Emits the static fossil.bootstrap.js using builtin_request_js(). |
| 1437 | */ |
| 1438 | void style_emit_script_fossil_bootstrap(int addScriptTag){ |
| 1439 | static int once = 0; |
| 1440 | if(0==once++){ |
| 1441 | char * zName; |
| 1442 | /* Set up the generic/app-agnostic parts of window.fossil |
| 1443 | ** which require C-level state... */ |
| 1444 | if(addScriptTag!=0){ |
| 1445 | style_emit_script_tag(0,0); |
| 1446 | } |
| 1447 | CX("(function(){\n"); |
| 1448 | CX(/*MSIE NodeList.forEach polyfill, courtesy of Mozilla: |
| 1449 | https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach#Polyfill |
| 1450 | */ |
| 1451 | "if(window.NodeList && !NodeList.prototype.forEach){" |
| 1452 | "NodeList.prototype.forEach = Array.prototype.forEach;" |
| 1453 | "}\n"); |
| 1454 | CX("if(!window.fossil) window.fossil={};\n" |
| 1455 | "window.fossil.version = %!j;\n" |
| 1456 | /* fossil.rootPath is the top-most CGI/server path, |
| 1457 | ** including a trailing slash. */ |
| 1458 | "window.fossil.rootPath = %!j+'/';\n", |
| 1459 | get_version(), g.zTop); |
| 1460 | /* fossil.config = {...various config-level options...} */ |
| 1461 | CX("window.fossil.config = {"); |
| 1462 | zName = db_get("project-name", ""); |
| 1463 | CX("projectName: %!j,\n", zName); |
| 1464 | fossil_free(zName); |
| 1465 | zName = db_get("short-project-name", ""); |
| 1466 | CX("shortProjectName: %!j,\n", zName); |
| 1467 | fossil_free(zName); |
| 1468 | zName = db_get("project-code", ""); |
| 1469 | CX("projectCode: %!j,\n", zName); |
| 1470 | fossil_free(zName); |
| 1471 | CX("/* Length of UUID hashes for display purposes. */"); |
| 1472 | CX("hashDigits: %d, hashDigitsUrl: %d,\n", |
| 1473 | hash_digits(0), hash_digits(1)); |
| 1474 | CX("editStateMarkers: {" |
| 1475 | "/*Symbolic markers to denote certain edit states.*/" |
| 1476 | "isNew:'[+]', isModified:'[*]', isDeleted:'[-]'},\n"); |
| 1477 | CX("confirmerButtonTicks: 3 " |
| 1478 | "/*default fossil.confirmer tick count.*/\n"); |
| 1479 | CX("};\n"/* fossil.config */); |
| 1480 | #if 0 |
| 1481 | /* Is it safe to emit the CSRF token here? Some pages add it |
| 1482 | ** as a hidden form field. */ |
| 1483 | if(g.zCsrfToken[0]!=0){ |
| 1484 | CX("window.fossil.csrfToken = %!j;\n", |
| 1485 | g.zCsrfToken); |
| 1486 | } |
| 1487 | #endif |
| 1488 | /* |
| 1489 | ** fossil.page holds info about the current page. This is also |
| 1490 | ** where the current page "should" store any of its own |
| 1491 | ** page-specific state, and it is reserved for that purpose. |
| 1492 | */ |
| 1493 | CX("window.fossil.page = {" |
| 1494 | "name:\"%T\"" |
| 1495 | "};\n", g.zPath); |
| 1496 | CX("})();\n"); |
| 1497 | if(addScriptTag!=0){ |
| 1498 | style_emit_script_tag(1,0); |
| 1499 | } |
| 1500 | /* The remaining window.fossil bootstrap code is not dependent on |
| 1501 | ** C-runtime state... */ |
| 1502 | builtin_request_js("fossil.bootstrap.js"); |
| 1503 | } |
| 1504 | } |
| 1505 | |
| 1506 | /* |
| 1507 | ** If passed 0 as its first argument, it emits a script opener tag |
| 1508 | ** with this request's nonce. If passed non-0 it emits a script |
| 1509 | ** closing tag. Mnemonic for remembering the order in which to pass 0 |
| 1510 | ** or 1 as the first argument to this function: 0 comes before 1. |
| @@ -1530,50 +1445,5 @@ | |
| 1530 | } |
| 1531 | }else{ |
| 1532 | CX("</script>\n"); |
| 1533 | } |
| 1534 | } |
| 1535 | |
| 1536 | /* |
| 1537 | ** Convenience wrapper which calls builtin_request_js() for a series |
| 1538 | ** of builtin scripts named fossil.NAME.js. The first time it is |
| 1539 | ** called, it also calls style_emit_script_fossil_bootstrap() to |
| 1540 | ** initialize the window.fossil JS API. The first argument is a |
| 1541 | ** no-meaning dummy required by the va_start() interface. All |
| 1542 | ** subsequent arguments must be strings of the NAME part of |
| 1543 | ** fossil.NAME.js, followed by a NULL argument to terminate the list. |
| 1544 | ** |
| 1545 | ** e.g. pass it (0, "fetch", "dom", "tabs", 0) to load those 3 |
| 1546 | ** APIs. Do not forget the trailing 0! |
| 1547 | */ |
| 1548 | void style_emit_fossil_js_apis( int dummy, ... ) { |
| 1549 | static int once = 0; |
| 1550 | const char *zArg; |
| 1551 | char * zName; |
| 1552 | va_list vargs; |
| 1553 | |
| 1554 | if(0==once++){ |
| 1555 | style_emit_script_fossil_bootstrap(1); |
| 1556 | } |
| 1557 | va_start(vargs,dummy); |
| 1558 | while( (zArg = va_arg (vargs, const char *))!=0 ){ |
| 1559 | zName = mprintf("fossil.%s.js", zArg); |
| 1560 | builtin_request_js(zName); |
| 1561 | fossil_free(zName); |
| 1562 | } |
| 1563 | va_end(vargs); |
| 1564 | } |
| 1565 | |
| 1566 | /* |
| 1567 | ** Emits, via builtin_request_js(), all JS fossil.XYZ APIs which are |
| 1568 | ** not strictly specific to a single page. The idea is that we can get |
| 1569 | ** better bundle caching and reduced HTTP requests by including all |
| 1570 | ** JS, rather than creating separate bundles on a per-page basis. |
| 1571 | */ |
| 1572 | void style_emit_all_fossil_js_apis(void){ |
| 1573 | style_emit_fossil_js_apis(0, |
| 1574 | "dom", "fetch", |
| 1575 | "storage", "tabs", |
| 1576 | "confirmer", "popupwidget", |
| 1577 | "copybutton", "numbered-lines", |
| 1578 | 0); |
| 1579 | } |
| 1580 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -1416,95 +1416,10 @@ | |
| 1416 | CX("</div>\n"); |
| 1417 | va_end(vargs); |
| 1418 | fossil_free(zLabelID); |
| 1419 | } |
| 1420 | |
| 1421 | /* |
| 1422 | ** If passed 0 as its first argument, it emits a script opener tag |
| 1423 | ** with this request's nonce. If passed non-0 it emits a script |
| 1424 | ** closing tag. Mnemonic for remembering the order in which to pass 0 |
| 1425 | ** or 1 as the first argument to this function: 0 comes before 1. |
| @@ -1530,50 +1445,5 @@ | |
| 1445 | } |
| 1446 | }else{ |
| 1447 | CX("</script>\n"); |
| 1448 | } |
| 1449 | } |
| 1450 |
| --- src/style.fileedit.css | ||
| +++ src/style.fileedit.css | ||
| @@ -220,6 +220,15 @@ | ||
| 220 | 220 | body.fileedit #fileedit-edit-status span.links > *::before { |
| 221 | 221 | content: "["; |
| 222 | 222 | } |
| 223 | 223 | body.fileedit #fileedit-edit-status span.links > *::after { |
| 224 | 224 | content: "]"; |
| 225 | +} | |
| 226 | +/* JS selection of line numbers cannot work in preview mode, | |
| 227 | + so disable the UI indications which imply that it does | |
| 228 | + something... */ | |
| 229 | +body.fileedit table.numbered-lines td.line-numbers > span { | |
| 230 | + cursor: unset; | |
| 231 | +} | |
| 232 | +body.fileedit table.numbered-lines td.line-numbers > span:hover { | |
| 233 | + background-color: inherit; | |
| 225 | 234 | } |
| 226 | 235 |
| --- src/style.fileedit.css | |
| +++ src/style.fileedit.css | |
| @@ -220,6 +220,15 @@ | |
| 220 | body.fileedit #fileedit-edit-status span.links > *::before { |
| 221 | content: "["; |
| 222 | } |
| 223 | body.fileedit #fileedit-edit-status span.links > *::after { |
| 224 | content: "]"; |
| 225 | } |
| 226 |
| --- src/style.fileedit.css | |
| +++ src/style.fileedit.css | |
| @@ -220,6 +220,15 @@ | |
| 220 | body.fileedit #fileedit-edit-status span.links > *::before { |
| 221 | content: "["; |
| 222 | } |
| 223 | body.fileedit #fileedit-edit-status span.links > *::after { |
| 224 | content: "]"; |
| 225 | } |
| 226 | /* JS selection of line numbers cannot work in preview mode, |
| 227 | so disable the UI indications which imply that it does |
| 228 | something... */ |
| 229 | body.fileedit table.numbered-lines td.line-numbers > span { |
| 230 | cursor: unset; |
| 231 | } |
| 232 | body.fileedit table.numbered-lines td.line-numbers > span:hover { |
| 233 | background-color: inherit; |
| 234 | } |
| 235 |
| --- src/style.wikiedit.css | ||
| +++ src/style.wikiedit.css | ||
| @@ -189,12 +189,10 @@ | ||
| 189 | 189 | margin: 0 1em 0 0.5em; |
| 190 | 190 | height: initial; |
| 191 | 191 | font-family: monospace; |
| 192 | 192 | flex: 10 1 auto; |
| 193 | 193 | } |
| 194 | - | |
| 195 | - | |
| 196 | 194 | body.wikiedit fieldset.page-types-list > div > span { |
| 197 | 195 | display: flex; |
| 198 | 196 | flex-direction: row; |
| 199 | 197 | flex-wrap: nowrap; |
| 200 | 198 | align-items: center; |
| 201 | 199 |
| --- src/style.wikiedit.css | |
| +++ src/style.wikiedit.css | |
| @@ -189,12 +189,10 @@ | |
| 189 | margin: 0 1em 0 0.5em; |
| 190 | height: initial; |
| 191 | font-family: monospace; |
| 192 | flex: 10 1 auto; |
| 193 | } |
| 194 | |
| 195 | |
| 196 | body.wikiedit fieldset.page-types-list > div > span { |
| 197 | display: flex; |
| 198 | flex-direction: row; |
| 199 | flex-wrap: nowrap; |
| 200 | align-items: center; |
| 201 |
| --- src/style.wikiedit.css | |
| +++ src/style.wikiedit.css | |
| @@ -189,12 +189,10 @@ | |
| 189 | margin: 0 1em 0 0.5em; |
| 190 | height: initial; |
| 191 | font-family: monospace; |
| 192 | flex: 10 1 auto; |
| 193 | } |
| 194 | body.wikiedit fieldset.page-types-list > div > span { |
| 195 | display: flex; |
| 196 | flex-direction: row; |
| 197 | flex-wrap: nowrap; |
| 198 | align-items: center; |
| 199 |
+7
-11
| --- src/wiki.c | ||
| +++ src/wiki.c | ||
| @@ -1181,11 +1181,11 @@ | ||
| 1181 | 1181 | "</div>" /*will get moved around dynamically*/); |
| 1182 | 1182 | CX("<div class='input-with-label'>" |
| 1183 | 1183 | "<button class='wikiedit-save-close'>" |
| 1184 | 1184 | "Save & Close</button>" |
| 1185 | 1185 | "<div class='help-buttonlet'>" |
| 1186 | - "Saves edits to this page and returns to the wiki page viewer." | |
| 1186 | + "Save edits to this page and returns to the wiki page viewer." | |
| 1187 | 1187 | "</div>" |
| 1188 | 1188 | "</div>" /*will get moved around dynamically*/); |
| 1189 | 1189 | CX("<span class='save-button-slot'></span>"); |
| 1190 | 1190 | |
| 1191 | 1191 | CX("<div class='input-with-label'>" |
| @@ -1227,15 +1227,15 @@ | ||
| 1227 | 1227 | /* ^^^ dest elem ID */ |
| 1228 | 1228 | ">Refresh</button>"); |
| 1229 | 1229 | /* Toggle auto-update of preview when the Preview tab is selected. */ |
| 1230 | 1230 | CX("<div class='input-with-label'>" |
| 1231 | 1231 | "<input type='checkbox' value='1' " |
| 1232 | - "id='cb-preview-autorefresh' checked=''>" | |
| 1232 | + "id='cb-preview-autorefresh' checked>" | |
| 1233 | 1233 | "<label for='cb-preview-autorefresh'>Auto-refresh?</label>" |
| 1234 | 1234 | "<div class='help-buttonlet'>" |
| 1235 | 1235 | "If on, the preview will automatically " |
| 1236 | - "refresh when this tab is selected." | |
| 1236 | + "refresh (if needed) when this tab is selected." | |
| 1237 | 1237 | "</div>" |
| 1238 | 1238 | "</div>"); |
| 1239 | 1239 | CX("<span class='save-button-slot'></span>"); |
| 1240 | 1240 | CX("</div>"/*.wikiedit-options*/); |
| 1241 | 1241 | CX("<div id='wikiedit-tab-preview-wrapper'></div>"); |
| @@ -1286,19 +1286,15 @@ | ||
| 1286 | 1286 | well_formed_wiki_name_rules(); |
| 1287 | 1287 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1288 | 1288 | } |
| 1289 | 1289 | |
| 1290 | 1290 | builtin_request_js("sbsdiff.js"); |
| 1291 | -#if 0 | |
| 1292 | - style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", | |
| 1293 | - "storage", "page.wikiedit", 0); | |
| 1294 | -#else | |
| 1295 | - style_emit_all_fossil_js_apis(); | |
| 1296 | - builtin_fulfill_js_requests(); | |
| 1291 | + if(!builtin_bundle_all_fossil_js_apis()){ | |
| 1292 | + builtin_emit_fossil_js_apis("fetch", "dom", "tabs", "confirmer", | |
| 1293 | + "storage", "page.wikiedit", 0); | |
| 1294 | + } | |
| 1297 | 1295 | builtin_request_js("fossil.page.wikiedit.js"); |
| 1298 | -#endif | |
| 1299 | - builtin_fulfill_js_requests(); | |
| 1300 | 1296 | /* Dynamically populate the editor... */ |
| 1301 | 1297 | style_emit_script_tag(0,0); |
| 1302 | 1298 | { |
| 1303 | 1299 | /* Render the current page list to save us an XHR request |
| 1304 | 1300 | during page initialization. This must be OUTSIDE of |
| 1305 | 1301 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1181,11 +1181,11 @@ | |
| 1181 | "</div>" /*will get moved around dynamically*/); |
| 1182 | CX("<div class='input-with-label'>" |
| 1183 | "<button class='wikiedit-save-close'>" |
| 1184 | "Save & Close</button>" |
| 1185 | "<div class='help-buttonlet'>" |
| 1186 | "Saves edits to this page and returns to the wiki page viewer." |
| 1187 | "</div>" |
| 1188 | "</div>" /*will get moved around dynamically*/); |
| 1189 | CX("<span class='save-button-slot'></span>"); |
| 1190 | |
| 1191 | CX("<div class='input-with-label'>" |
| @@ -1227,15 +1227,15 @@ | |
| 1227 | /* ^^^ dest elem ID */ |
| 1228 | ">Refresh</button>"); |
| 1229 | /* Toggle auto-update of preview when the Preview tab is selected. */ |
| 1230 | CX("<div class='input-with-label'>" |
| 1231 | "<input type='checkbox' value='1' " |
| 1232 | "id='cb-preview-autorefresh' checked=''>" |
| 1233 | "<label for='cb-preview-autorefresh'>Auto-refresh?</label>" |
| 1234 | "<div class='help-buttonlet'>" |
| 1235 | "If on, the preview will automatically " |
| 1236 | "refresh when this tab is selected." |
| 1237 | "</div>" |
| 1238 | "</div>"); |
| 1239 | CX("<span class='save-button-slot'></span>"); |
| 1240 | CX("</div>"/*.wikiedit-options*/); |
| 1241 | CX("<div id='wikiedit-tab-preview-wrapper'></div>"); |
| @@ -1286,19 +1286,15 @@ | |
| 1286 | well_formed_wiki_name_rules(); |
| 1287 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1288 | } |
| 1289 | |
| 1290 | builtin_request_js("sbsdiff.js"); |
| 1291 | #if 0 |
| 1292 | style_emit_fossil_js_apis(0, "fetch", "dom", "tabs", "confirmer", |
| 1293 | "storage", "page.wikiedit", 0); |
| 1294 | #else |
| 1295 | style_emit_all_fossil_js_apis(); |
| 1296 | builtin_fulfill_js_requests(); |
| 1297 | builtin_request_js("fossil.page.wikiedit.js"); |
| 1298 | #endif |
| 1299 | builtin_fulfill_js_requests(); |
| 1300 | /* Dynamically populate the editor... */ |
| 1301 | style_emit_script_tag(0,0); |
| 1302 | { |
| 1303 | /* Render the current page list to save us an XHR request |
| 1304 | during page initialization. This must be OUTSIDE of |
| 1305 |
| --- src/wiki.c | |
| +++ src/wiki.c | |
| @@ -1181,11 +1181,11 @@ | |
| 1181 | "</div>" /*will get moved around dynamically*/); |
| 1182 | CX("<div class='input-with-label'>" |
| 1183 | "<button class='wikiedit-save-close'>" |
| 1184 | "Save & Close</button>" |
| 1185 | "<div class='help-buttonlet'>" |
| 1186 | "Save edits to this page and returns to the wiki page viewer." |
| 1187 | "</div>" |
| 1188 | "</div>" /*will get moved around dynamically*/); |
| 1189 | CX("<span class='save-button-slot'></span>"); |
| 1190 | |
| 1191 | CX("<div class='input-with-label'>" |
| @@ -1227,15 +1227,15 @@ | |
| 1227 | /* ^^^ dest elem ID */ |
| 1228 | ">Refresh</button>"); |
| 1229 | /* Toggle auto-update of preview when the Preview tab is selected. */ |
| 1230 | CX("<div class='input-with-label'>" |
| 1231 | "<input type='checkbox' value='1' " |
| 1232 | "id='cb-preview-autorefresh' checked>" |
| 1233 | "<label for='cb-preview-autorefresh'>Auto-refresh?</label>" |
| 1234 | "<div class='help-buttonlet'>" |
| 1235 | "If on, the preview will automatically " |
| 1236 | "refresh (if needed) when this tab is selected." |
| 1237 | "</div>" |
| 1238 | "</div>"); |
| 1239 | CX("<span class='save-button-slot'></span>"); |
| 1240 | CX("</div>"/*.wikiedit-options*/); |
| 1241 | CX("<div id='wikiedit-tab-preview-wrapper'></div>"); |
| @@ -1286,19 +1286,15 @@ | |
| 1286 | well_formed_wiki_name_rules(); |
| 1287 | CX("</div>"/*#wikiedit-tab-save*/); |
| 1288 | } |
| 1289 | |
| 1290 | builtin_request_js("sbsdiff.js"); |
| 1291 | if(!builtin_bundle_all_fossil_js_apis()){ |
| 1292 | builtin_emit_fossil_js_apis("fetch", "dom", "tabs", "confirmer", |
| 1293 | "storage", "page.wikiedit", 0); |
| 1294 | } |
| 1295 | builtin_request_js("fossil.page.wikiedit.js"); |
| 1296 | /* Dynamically populate the editor... */ |
| 1297 | style_emit_script_tag(0,0); |
| 1298 | { |
| 1299 | /* Render the current page list to save us an XHR request |
| 1300 | during page initialization. This must be OUTSIDE of |
| 1301 |