Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Reimplemented pikchr show/hide entirely in CSS, so it's now controlled by toggling the 'source' class on the outermost DIV element. Less JS and easier to implement in 3rd-party pikchr clients. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
947c0390735ef1e39c71e926dbadca31 |
| User & Date: | stephan 2020-09-18 19:06:30.542 |
References
|
2025-11-23
| ||
| 02:06 | Reduced the space around floated left/right Pikchr elements in the default CSS, applied as part of [947c039073]. It was giving each 4em all the way around, but it now gives 2em to the sides and 1em top and bottom, which seems plenty in all conceivable contexts. ... (check-in: 97c9cae468 user: wyoung tags: trunk) | |
Context
|
2020-09-18
| ||
| 20:01 | Added pikchr block 'source-inline' modifier for the 'source' flag which tells the latter that the sources should be rendered inline (same position as the graphic), rather than left-aligned. ... (check-in: 3f2c0af278 user: stephan tags: trunk) | |
| 19:06 | Reimplemented pikchr show/hide entirely in CSS, so it's now controlled by toggling the 'source' class on the outermost DIV element. Less JS and easier to implement in 3rd-party pikchr clients. ... (check-in: 947c039073 user: stephan tags: trunk) | |
| 17:43 | CSS workaround for centering pikchrs in Chrome. ... (check-in: d825fcc11a user: stephan tags: trunk) | |
Changes
Changes to src/default.css.
| ︙ | ︙ | |||
1384 1385 1386 1387 1388 1389 1390 1391 |
}
noscript > .error {
/* Part of the style_emit_noscript_for_js_page() interface. */
padding: 1em;
font-size: 150%;
}
div.pikchr-wrapper {/*outer wrapper elem for a pikchr construct*/}
| > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 |
}
noscript > .error {
/* Part of the style_emit_noscript_for_js_page() interface. */
padding: 1em;
font-size: 150%;
}
/************************************************************
pikchr...
DOM structure:
<DIV.pikchr-wrapper>
<DIV.pikchr-svg>
<SVG.pikchr>...</SVG>
</DIV.pikchr-svg>
<PRE.pikchr-src>...</PRE>
</DIV.pikchr-wrapper>
************************************************************/
div.pikchr-wrapper {/*outer wrapper elem for a pikchr construct*/}
div.pikchr-svg {/*wrapper for SVG.pikchr element*/}
svg.pikchr {/*pikchr SVG*/}
pre.pikchr-src {/*source code view for a pikchr (see fossil.pikchr.js)*/
box-sizing: border-box;
overflow: auto;
text-align: left;
}
div.pikchr-wrapper.center {
text-align: center;
}
div.pikchr-wrapper.center > div.pikchr-svg {
width: 100%/*necessary for Chrome!*/;
}
div.pikchr-wrapper.center > pre.pikchr-src,
div.pikchr-wrapper.center > div.pikchr-svg{
display:inline-block/*allows text-align to do the alignment*/;
}
div.pikchr-wrapper.indent {
margin-left: 4em;
}
div.pikchr-wrapper.float-left {
float: left;
padding: 4em;
}
div.pikchr-wrapper.float-right {
float: right;
padding: 4em;
}
div.pikchr-wrapper.source > pre.pikchr-src {
}
/* For non-source view, pre.pikchr-src and reveal svg.pikchr... */
div.pikchr-wrapper:not(.source) > pre.pikchr-src {
position: absolute !important;
opacity: 0 !important;
pointer-events: none !important;
display: none !important;
}
div.pikchr-wrapper.source > div.pikchr-svg {
position: absolute !important;
opacity: 0 !important;
pointer-events: none !important;
display: none !important;
}
|
Changes to src/fossil.pikchr.js.
| ︙ | ︙ | |||
34 35 36 37 38 39 40 |
it is passed to this function multiple times. Each processed
element gets a "data" attribute set to it to indicate that it was
already dealt with.
This code expects the following structure around the SVGs, and
will not process any which don't match this:
| | | | > > | | < < < < < < < < < | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
it is passed to this function multiple times. Each processed
element gets a "data" attribute set to it to indicate that it was
already dealt with.
This code expects the following structure around the SVGs, and
will not process any which don't match this:
<DIV.pikchr-wrapper>
<DIV.pikchr-svg><SVG.pikchr></SVG></DIV>
<PRE.pikchr-src></PRE>
</DIV>
*/
P.addSrcView = function f(svg){
if(!f.hasOwnProperty('parentClick')){
f.parentClick = function(ev){
if(ev.altKey || ev.metaKey || ev.ctrlKey
/* Every combination of special key (alt, shift, ctrl,
meta) is handled differently everywhere. Shift is used
by the browser, Ctrl doesn't work on an iMac, and Alt is
intercepted by most Linux window managers to control
window movement! So... we just listen for *any* of them
(except Shift) and the user will need to find one which
works on on their environment. */
|| this.classList.contains('toggle')){
this.classList.toggle('source');
ev.stopPropagation();
ev.preventDefault();
}
};
};
if(!svg) svg = 'svg.pikchr';
if('string' === typeof svg){
document.querySelectorAll(svg).forEach((e)=>f.call(this, e));
return this;
}else if(svg.forEach){
svg.forEach((e)=>f.call(this, e));
return this;
}
if(svg.dataset.pikchrProcessed){
return this;
}
svg.dataset.pikchrProcessed = 1;
const parent = svg.parentNode.parentNode /* outermost div.pikchr-wrapper */;
const srcView = parent ? svg.parentNode.nextElementSibling : undefined;
if(!srcView || !srcView.classList.contains('pikchr-src')){
/* Without this element, there's nothing for us to do here. */
return this;
}
parent.addEventListener('click', f.parentClick, false);
};
})(window.fossil);
|
Changes to src/markdown_html.c.
| ︙ | ︙ | |||
342 343 344 345 346 347 348 |
void pikchr_to_html(
Blob *ob, /* Write the generated SVG here */
const char *zSrc, int nSrc, /* The Pikchr source text */
const char *zArg, int nArg /* Addition arguments */
){
int pikFlags = PIKCHR_PROCESS_NONCE
| PIKCHR_PROCESS_DIV
| | | 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
void pikchr_to_html(
Blob *ob, /* Write the generated SVG here */
const char *zSrc, int nSrc, /* The Pikchr source text */
const char *zArg, int nArg /* Addition arguments */
){
int pikFlags = PIKCHR_PROCESS_NONCE
| PIKCHR_PROCESS_DIV
| PIKCHR_PROCESS_SRC;
Blob bSrc = empty_blob;
while( nArg>0 ){
int i;
for(i=0; i<nArg && !fossil_isspace(zArg[i]); i++){}
if( i==6 && strncmp(zArg, "center", 6)==0 ){
pikFlags |= PIKCHR_PROCESS_DIV_CENTER;
|
| ︙ | ︙ |
Changes to src/pikchrshow.c.
| ︙ | ︙ | |||
25 26 27 28 29 30 31 | #if INTERFACE /* These are described in pikchr_process()'s docs. */ #define PIKCHR_PROCESS_TH1 0x01 #define PIKCHR_PROCESS_TH1_NOSVG 0x02 #define PIKCHR_PROCESS_NONCE 0x04 #define PIKCHR_PROCESS_ERR_PRE 0x08 #define PIKCHR_PROCESS_SRC 0x10 | < | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #if INTERFACE /* These are described in pikchr_process()'s docs. */ #define PIKCHR_PROCESS_TH1 0x01 #define PIKCHR_PROCESS_TH1_NOSVG 0x02 #define PIKCHR_PROCESS_NONCE 0x04 #define PIKCHR_PROCESS_ERR_PRE 0x08 #define PIKCHR_PROCESS_SRC 0x10 #define PIKCHR_PROCESS_DIV 0x20 #define PIKCHR_PROCESS_DIV_INDENT 0x0100 #define PIKCHR_PROCESS_DIV_CENTER 0x0200 #define PIKCHR_PROCESS_DIV_FLOAT_LEFT 0x0400 #define PIKCHR_PROCESS_DIV_FLOAT_RIGHT 0x0800 #define PIKCHR_PROCESS_DIV_TOGGLE 0x1000 #define PIKCHR_PROCESS_DIV_SOURCE 0x2000 #endif |
| ︙ | ︙ | |||
95 96 97 98 99 100 101 | ** which prevents the wiki/markdown processors from re-processing this ** output. This is necessary when calling this routine in the context ** of wiki/embedded doc processing, but not (e.g.) when fetching ** an image for /pikchrpage. ** ** - PIKCHR_PROCESS_SRC: if set, a new PRE.pikchr-src element is ** injected adjacent to the SVG element which contains the | | < | < < < | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
** which prevents the wiki/markdown processors from re-processing this
** output. This is necessary when calling this routine in the context
** of wiki/embedded doc processing, but not (e.g.) when fetching
** an image for /pikchrpage.
**
** - PIKCHR_PROCESS_SRC: if set, a new PRE.pikchr-src element is
** injected adjacent to the SVG element which contains the
** HTML-escaped content of the input script. If
** PIKCHR_PROCESS_DIV_SOURCE is set, this flag is automatically
** implied.
**
** - PIKCHR_PROCESS_ERR_PRE: if set and pikchr() fails, the resulting
** error report is wrapped in a PRE element, else it is retained
** as-is (intended only for console output).
*/
int pikchr_process(const char * zIn, int pikFlags, int thFlags,
Blob * pOut){
|
| ︙ | ︙ | |||
160 161 162 163 164 165 166 |
const char * zWrapperClass = "";
const char *zNonce = (PIKCHR_PROCESS_NONCE & pikFlags)
? safe_html_nonce(1) : 0;
if(zNonce){
blob_appendf(pOut, "%s\n", zNonce);
}
if(PIKCHR_PROCESS_DIV & pikFlags){
| < < | | | > | | | | < | < | < < < | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
const char * zWrapperClass = "";
const char *zNonce = (PIKCHR_PROCESS_NONCE & pikFlags)
? safe_html_nonce(1) : 0;
if(zNonce){
blob_appendf(pOut, "%s\n", zNonce);
}
if(PIKCHR_PROCESS_DIV & pikFlags){
if(PIKCHR_PROCESS_DIV_CENTER & pikFlags){
/*blob_append(&css, "display:block;margin:auto;", -1);*/
zWrapperClass = " center";
}else if(PIKCHR_PROCESS_DIV_INDENT & pikFlags){
zWrapperClass = " indent";
}else if(PIKCHR_PROCESS_DIV_FLOAT_LEFT & pikFlags){
zWrapperClass = " float-left";
}else if(PIKCHR_PROCESS_DIV_FLOAT_RIGHT & pikFlags){
zWrapperClass = " float-right";
}
if(PIKCHR_PROCESS_DIV_TOGGLE & pikFlags){
zClassToggle = " toggle";
}
if(PIKCHR_PROCESS_DIV_SOURCE & pikFlags){
zClassSource = " source";
pikFlags |= PIKCHR_PROCESS_SRC;
}
blob_appendf(pOut,"<div class='pikchr-wrapper%s%s%s'>"
"<div class=\"pikchr-svg\" "
"style=\"max-width:%dpx\">\n",
zWrapperClass/*safe-for-%s*/,
zClassToggle/*safe-for-%s*/,
zClassSource/*safe-for-%s*/, w);
}
blob_append(pOut, zOut, -1);
if(PIKCHR_PROCESS_DIV & pikFlags){
blob_append(pOut, "</div>\n", 7);
}
if(PIKCHR_PROCESS_SRC & pikFlags){
blob_appendf(pOut, "<pre class='pikchr-src'>%h</pre>\n",
blob_str(&bIn));
}
if(PIKCHR_PROCESS_DIV & pikFlags){
blob_append(pOut, "</div>\n", 7);
}
if(zNonce){
blob_append(pOut, zNonce, -1);
|
| ︙ | ︙ | |||
235 236 237 238 239 240 241 |
** It optionally accepts a p=pikchr-script-code URL parameter or POST
** value to pre-populate the editor with that code.
*/
void pikchrshow_page(void){
const char *zContent = 0;
int isDark; /* true if the current skin is "dark" */
int pikFlags = PIKCHR_PROCESS_DIV
| | | 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
** It optionally accepts a p=pikchr-script-code URL parameter or POST
** value to pre-populate the editor with that code.
*/
void pikchrshow_page(void){
const char *zContent = 0;
int isDark; /* true if the current skin is "dark" */
int pikFlags = PIKCHR_PROCESS_DIV
| PIKCHR_PROCESS_SRC
| PIKCHR_PROCESS_ERR_PRE;
login_check_credentials();
if( !g.perm.RdWiki && !g.perm.Read && !g.perm.RdForum ){
cgi_redirectf("%s/login?g=%s/pikchrshow", g.zTop, g.zTop);
}
zContent = PD("content",P("p"));
|
| ︙ | ︙ | |||
390 391 392 393 394 395 396 | ** ** -div-center Like -div but centers the div. ** ** -div-left Like -div but floats the div left. ** ** -div-right Like -div but floats the div right. ** | | | | | | > | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 | ** ** -div-center Like -div but centers the div. ** ** -div-left Like -div but floats the div left. ** ** -div-right Like -div but floats the div right. ** ** -div-toggle Sets the 'toggle' CSS class on the div (used by the ** JavaScript-side post-processor). ** ** -div-source Sets the 'source' CSS class on the div, which tells ** CSS to hide the SVG and reveal the source by default. ** ** -src Stores the input pikchr's source code in the output as ** a separate element adjacent to the SVG one. Implied ** by -div-source. ** ** ** -th Process the input using TH1 before passing it to pikchr. ** ** -th-novar Disable $var and $<var> TH1 processing. Use this if the ** pikchr script uses '$' for its own purposes and that ** causes issues. This only affects parsing of '$' outside ** of TH1 script blocks. Code in such blocks is unaffected. |
| ︙ | ︙ | |||
442 443 444 445 446 447 448 |
Blob bOut = empty_blob;
const char * zInfile = "-";
const char * zOutfile = "-";
const int fTh1 = find_option("th",0,0)!=0;
const int fNosvg = find_option("th-nosvg",0,0)!=0;
int isErr = 0;
int pikFlags = find_option("src",0,0)!=0
| | | | 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 |
Blob bOut = empty_blob;
const char * zInfile = "-";
const char * zOutfile = "-";
const int fTh1 = find_option("th",0,0)!=0;
const int fNosvg = find_option("th-nosvg",0,0)!=0;
int isErr = 0;
int pikFlags = find_option("src",0,0)!=0
? PIKCHR_PROCESS_SRC : 0;
u32 fThFlags = TH_INIT_NO_ENCODE
| (find_option("th-novar",0,0)!=0 ? TH_R2B_NO_VARS : 0);
Th_InitTraceLog()/*processes -th-trace flag*/;
if(find_option("div",0,0)!=0){
pikFlags |= PIKCHR_PROCESS_DIV;
}else if(find_option("div-indent",0,0)!=0){
pikFlags |= PIKCHR_PROCESS_DIV_INDENT;
}else if(find_option("div-center",0,0)!=0){
pikFlags |= PIKCHR_PROCESS_DIV_CENTER;
}else if(find_option("div-float-left",0,0)!=0){
pikFlags |= PIKCHR_PROCESS_DIV_FLOAT_LEFT;
}else if(find_option("div-float-right",0,0)!=0){
pikFlags |= PIKCHR_PROCESS_DIV_FLOAT_RIGHT;
}
if(find_option("div-toggle",0,0)!=0){
pikFlags |= PIKCHR_PROCESS_DIV_TOGGLE;
}
if(find_option("div-source",0,0)!=0){
pikFlags |= PIKCHR_PROCESS_DIV_SOURCE | PIKCHR_PROCESS_SRC;
}
verify_all_options();
if(g.argc>4){
usage("?INFILE? ?OUTFILE?");
}
if(g.argc>2){
|
| ︙ | ︙ |