Index: src/default.css ================================================================== --- src/default.css +++ src/default.css @@ -1388,9 +1388,7 @@ padding: 1em; font-size: 150%; } .pikchr-src { /* source code view for a pikchr (see fossil.pikchr.js) */ box-sizing: border-box/*reduces UI shift*/; - border-width: 1px; - border-style: dotted; overflow: auto; } Index: src/fossil.dom.js ================================================================== --- src/fossil.dom.js +++ src/fossil.dom.js @@ -713,12 +713,12 @@ /** Parses a string as HTML. Usages: - (htmlString) - (DOMElement target, htmlString) + Array (htmlString) + DOMElement (DOMElement target, htmlString) The first form parses the string as HTML and returns an Array of all elements parsed from it. If string is falsy then it returns an empty array. Index: src/fossil.page.pikchrshow.js ================================================================== --- src/fossil.page.pikchrshow.js +++ src/fossil.page.pikchrshow.js @@ -322,13 +322,14 @@ switch(this.previewMode){ case 0: label = "SVG"; f.showMarkupAlignment(false); D.parseHtml(D.clearElement(preTgt), P.response.raw); - svg = f.getSvgNode(this.response.raw); + svg = preTgt.querySelector('svg.pikchr'); if(svg){ /*for copy button*/ this.e.taPreviewText.value = svg.outerHTML; + F.pikchr.addSrcView(svg); } break; case 1: label = "Markdown"; f.showMarkupAlignment(true); Index: src/fossil.pikchr.js ================================================================== --- src/fossil.pikchr.js +++ src/fossil.pikchr.js @@ -1,240 +1,87 @@ (function(F/*window.fossil object*/){ "use strict"; - - const D = F.dom; - - const P = F.pikchr = { - }; - - //////////////////////////////////////////////////////////////////////// - // Install an app-specific stylesheet, just for development, after which - // it will be moved into default.css - (function(){ - const head = document.head || document.querySelector('head'), - styleTag = document.createElement('style'), - wh = '1cm' /* fixed width/height of buttons */, - styleCSS = ` -.pikchr-button-bar { - position: absolute; - position: absolute; - top: 0; - left: 0; - display: inline-flex; - flex-direction: column; -} -.pikchr-src-button { - min-height: ${wh}; max-height: ${wh}; - min-width: ${wh}; max-width: ${wh}; - font-size: ${wh}; - border: 1px solid black; - background-color: rgba(255,255,0,0.7); - border-radius: 0.25cm; - z-index: 50; - cursor: pointer; - text-align: center; - display: inline-flex; - align-items: center; - justify-content: center; - transform-origin: center; - transition: transform 250ms linear; - padding: 0; margin: 0; -/* MIT-licensed SVG from: https://github.com/leungwensen/svg-icon/blob/master/dist/svg/ant/code.svg */ - background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg viewBox='0 0 1195 1195' \ -xmlns='http:/\x2fwww.w3.org/2000/svg'%3e%3cpath d='M321.333 440q-9-10-22.5-10t-22.5 \ -10l-182 181q-9 9-9 22.5t9 22.5l182 182q9 10 22.5 10t22.5-10q10-9 10-22.5t-10-22.5l-159-159 \ -159-159q10-10 10-23t-10-22zm552 0q9-10 22.5-10t22.5 10l182 181q9 9 9 22.5t-9 \ -22.5l-182 182q-9 10-22.5 10t-22.5-10q-10-9-10-22.5t10-22.5l159-159-159-159q-10-10-10-23t10-22zm-97-180q12 \ -6 16 19t-2 24l-371 704q-7 12-19.5 16t-24.5-2q-11-7-15-19.5t2-24.5l371-703q6-12 \ -18.5-16t24.5 2z'/%3e%3c/svg%3e"); - background-size: contain; -} -.pikchr-src-button.src-active { - transform: scaleX(-1); -/* MIT-licensed SVG from: https://github.com/leungwensen/svg-icon/blob/master/dist/svg/ant/picture.svg */ - background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg viewBox='0 0 1195 1195' \ -xmlns='http:/\x2fwww.w3.org/2000/svg'%3e%3cpath d='M1045.333 192h-896q-26 0-45 \ -19t-19 45v768q0 26 19 45t45 19h896q26 0 45-19t19-45V256q0-26-19-45t-45-19zm-896 \ -64h896v714l-236-348q-7-12-21-14t-25 7l-154 125-174-243q-10-14-28-13t-26 17l-232 \ -448V256zm855 768h-822l231-447 184 255 179-145zm-182-642q13 0 22.5 9.5t9.5 22.5-9.5 \ -22.5-22.5 9.5-22.5-9.5-9.5-22.5 9.5-22.5 22.5-9.5zm0-64q-40 0-68 28t-28 68 28 68 68 \ -28 68-28 28-68-28-68-68-28z'/%3e%3c/svg%3e"); -} -textarea.pikchr-src-text { - box-sizing: border-box/*reduces UI shift*/; -} -.pikchr-copy-button { - min-width: ${wh}; max-width: ${wh}; - min-height: ${wh}; max-height: ${wh}; - display: inline-block; -} -.pikchr-button-bar > .pikchr-src-button, -.pikchr-button-bar > .pikchr-copy-button { - margin-bottom: 0.3em; -} -`; - head.appendChild(styleTag); - /* Adapted from https://stackoverflow.com/a/524721 */ - styleTag.type = 'text/css'; - D.append(styleTag, styleCSS); - })(); + const D = F.dom, P = F.pikchr = {}; /** - Sets up a "view source" button on one or more pikchr-created SVG - image elements. + Initializes pikchr-rendered elements with the ability to + toggle between their SVG and source code. The first argument may be any of: - - A single SVG element. + - A single SVG.pikchr element. - A collection (with a forEach method) of such elements. - A CSS selector string for one or more such elements. - An array of such strings. Passing no value is equivalent to passing 'svg.pikchr'. - For each SVG in the resulting set, this function does the - following: - - - It sets the "position" value of the element's *parent* node to - "relative", as that is necessary for what follows. - - - It creates a small pseudo-button, adding it to the SVG - element's parent node, styled to hover in one of the element's - corners. - - - That button, when tapped, toggles the SVG on and off - while revealing or hiding a readonly textarea element - which contains the source code for that pikchr SVG - (which pikchr has helpfully embedded in the SVG's - metadata). + For each SVG in the resulting set, this function sets up event + handlers which allow the user to toggle the SVG between image and + source code modes. The image will switch modes in response to + cltr-click and, if its *parent* element has the "toggle" CSS + class, it will also switch modes in response to single-click. + + If the parent element has the "source" CSS class, the image + starts off with its source code visible and the image hidden, + instead of the default of the other way around. Returns this object. - The 2nd argument is intended to be a plain options object, but it - is currently unused, as it's not yet clear what we can/should - make configurable. - Each element will only be processed once by this routine, even if 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: + +
"
- "%s
\n", zIn);
- blob_appendf(ob, "\n");
- blob_appendf(ob,
- "\n",
- style_nonce(), nSvg, zClickOk);
- blob_appendf(ob, "%s\n", zSafeNonce);
- }else{
- blob_appendf(ob, "\n%s\n\n", zOut); - } - fossil_free(zIn); - free(zOut); -} - - + int pikFlags = PIKCHR_PROCESS_NONCE + | PIKCHR_PROCESS_DIV + | PIKCHR_PROCESS_SRC_HIDDEN; + Blob bSrc = empty_blob; + + while( nArg>0 ){ + int i; + for(i=0; i
" + "%h\n", (PIKCHR_PROCESS_SRC_HIDDEN & pikFlags) ? " hidden" : "", blob_str(&bIn)); } if(PIKCHR_PROCESS_DIV & pikFlags){ @@ -357,11 +388,11 @@ ** ** -div-left Like -div but floats the div left. ** ** -div-right Like -div but floats the div right. ** -** -svg-src Stores the input pikchr's source code in the output as +** -src Stores the input pikchr's source code in the output as ** a separate element adjacent to the SVG one. The ** source element initially has the "hidden" CSS class. ** ** -th Process the input using TH1 before passing it to pikchr. ** @@ -399,11 +430,11 @@ 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("svg-src",0,0)!=0 + int pikFlags = find_option("src",0,0)!=0 ? PIKCHR_PROCESS_SRC_HIDDEN : 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*/; @@ -417,10 +448,16 @@ }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; + } verify_all_options(); if(g.argc>4){ usage("?INFILE? ?OUTFILE?"); }