| | @@ -28,16 +28,36 @@ |
| 28 | 28 | ** |
| 29 | 29 | ** A basic pikchr code editor and renderer, allowing users with write- |
| 30 | 30 | ** or wiki-write permissions to experiment with pikchr code. |
| 31 | 31 | */ |
| 32 | 32 | void pikchrshow_cmd(void){ |
| 33 | | - const char *zContent = P("content"); |
| 33 | + const char *zContent = 0; |
| 34 | 34 | int isDark, flipColors; |
| 35 | 35 | |
| 36 | 36 | login_check_credentials(); |
| 37 | | - if( !g.perm.WrWiki && !g.perm.Write ){ |
| 37 | + if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){ |
| 38 | 38 | cgi_redirectf("%s/login?g=%s/pikchrshow", g.zTop, g.zTop); |
| 39 | + } |
| 40 | + zContent = P("content"); |
| 41 | + if(P("ajax")!=0){ |
| 42 | + /* Called from the JS-side preview updater. */ |
| 43 | + cgi_set_content_type("text/html"); |
| 44 | + if(zContent && *zContent){ |
| 45 | + int w = 0, h = 0; |
| 46 | + char *zOut = pikchr(zContent, "pikchr", 0, &w, &h); |
| 47 | + if( w>0 && h>0 ){ |
| 48 | + const char *zNonce = safe_html_nonce(1); |
| 49 | + CX("%s\n%s%s", zNonce, zOut, zNonce); |
| 50 | + }else{ |
| 51 | + cgi_printf_header("x-pikchrshow-is-error: 1\r\n"); |
| 52 | + CX("<pre>\n%s\n</pre>\n", zOut); |
| 53 | + } |
| 54 | + fossil_free(zOut); |
| 55 | + }else{ |
| 56 | + CX("<pre>No content! Nothing to render</pre>"); |
| 57 | + } |
| 58 | + return; |
| 39 | 59 | } |
| 40 | 60 | isDark = skin_detail_boolean("white-foreground"); |
| 41 | 61 | flipColors = zContent ? P("flipcolors")!=0 : isDark; |
| 42 | 62 | if(!zContent){ |
| 43 | 63 | zContent = "arrow right 200% \"Markdown\" \"Source\"\n" |
| | @@ -54,38 +74,44 @@ |
| 54 | 74 | CX("#sbs-wrapper > * {margin: 0 0 1em 0}"); |
| 55 | 75 | CX("#pikchrshow-output, #pikchrshow-form" |
| 56 | 76 | "{display: flex; flex-direction: column}"); |
| 57 | 77 | CX("#pikchrshow-form {flex: 2 1 auto}"); |
| 58 | 78 | CX("#pikchrshow-form > * {margin: 0.25em 0}"); |
| 59 | | - CX("#pikchrshow-output {flex: 1 1 auto}"); |
| 79 | + CX("#pikchrshow-output {" |
| 80 | + "flex: 1 1 auto; border-width: 1px; border-style: solid;" |
| 81 | + "border-radius: 0.25em; padding: 0.5em;" |
| 82 | + "}"); |
| 83 | + CX("#pikchrshow-output > pre, " |
| 84 | + "#pikchrshow-output > pre > div, " |
| 85 | + "#pikchrshow-output > pre > div > pre " |
| 86 | + "{margin: 0; padding: 0}"); |
| 60 | 87 | CX("#pikchrshow-controls {" |
| 61 | 88 | "display: flex; flex-direction: row; align-items: center;" |
| 62 | 89 | "}"); |
| 63 | 90 | CX("#pikchrshow-controls > * {" |
| 64 | 91 | "display: inline; margin-left: 0.5em;" |
| 65 | 92 | "}"); |
| 66 | 93 | CX("#pikchrshow-controls > .input-with-label > * {" |
| 67 | 94 | "cursor: pointer;" |
| 68 | 95 | "}"); |
| 96 | + CX("#pikchrshow-output.dark-mode > svg {" |
| 97 | + /* Flip the colors to approximate a dark theme look */ |
| 98 | + "filter: invert(1) hue-rotate(180deg);" |
| 99 | + "}"); |
| 69 | 100 | CX("</style>"); |
| 70 | | - if( flipColors ){ |
| 71 | | - /* Flip the colors to approximate a dark theme look */ |
| 72 | | - CX("<style>#pikchrshow-output > svg {" |
| 73 | | - "filter: invert(1) hue-rotate(180deg);" |
| 74 | | - "}</style>"); |
| 75 | | - } |
| 76 | | - CX("<div>Input pikchr code and tap SUBMIT to render it:</div>"); |
| 101 | + CX("<div>Input pikchr code and tap Preview to render it:</div>"); |
| 77 | 102 | CX("<div id='sbs-wrapper'>"); |
| 78 | | - CX("<form method='POST' id='pikchrshow-form' action=''>"); |
| 79 | | - CX("<textarea name='content' rows='15'>%s</textarea>", |
| 103 | + CX("<div id='pikchrshow-form'>"); |
| 104 | + CX("<textarea id='content' name='content' rows='15'>%s</textarea>", |
| 80 | 105 | zContent/*safe-for-%s*/); |
| 81 | 106 | CX("<div id='pikchrshow-controls'>"); |
| 82 | | - CX("<input type='submit' value='Submit'></input>"); |
| 83 | | - style_labeled_checkbox(0, "flipcolors", "Simulate dark color theme?", |
| 107 | + CX("<button id='pikchr-submit-preview'>Preview</button>"); |
| 108 | + style_labeled_checkbox("flipcolors-wrapper", "flipcolors", |
| 109 | + "Simulate dark color theme?", |
| 84 | 110 | "1", flipColors, 0); |
| 85 | 111 | CX("</div>"/*#pikchrshow-controls*/); |
| 86 | | - CX("</form>"/*#pikchrshow-form*/); |
| 112 | + CX("</div>"/*#pikchrshow-form*/); |
| 87 | 113 | CX("<div id='pikchrshow-output'>"); |
| 88 | 114 | if(*zContent){ |
| 89 | 115 | int w = 0, h = 0; |
| 90 | 116 | char *zOut = pikchr(zContent, "pikchr", 0, &w, &h); |
| 91 | 117 | if( w>0 && h>0 ){ |
| | @@ -96,8 +122,13 @@ |
| 96 | 122 | } |
| 97 | 123 | fossil_free(zOut); |
| 98 | 124 | } |
| 99 | 125 | CX("</div>"/*#pikchrshow-output*/); |
| 100 | 126 | CX("</div>"/*sbs-wrapper*/); |
| 127 | + if(!builtin_bundle_all_fossil_js_apis()){ |
| 128 | + builtin_emit_fossil_js_apis("dom", "fetch", 0); |
| 129 | + } |
| 130 | + builtin_emit_fossil_js_apis("page.pikchrshow", 0); |
| 131 | + builtin_fulfill_js_requests(); |
| 101 | 132 | style_footer(); |
| 102 | 133 | } |
| 103 | 134 | |
| 104 | 135 | |