Fossil SCM

pikchrshow now squirrels away a copy of the raw response SVG, instead of fishing it out the DOM on demand, because in the latter case the browser converts u00a0 characters to nbsp elements, resulting in illegal SVG.

stephan 2020-09-25 03:04 trunk
Commit f45cd279190cc9bb86f21d4b5ed28e091827e6036223808fdce8a537aaca69ea
1 file changed +29 -5
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -13,12 +13,30 @@
1313
P.previewMode = 0 /*0==rendered SVG, 1==pikchr text markdown,
1414
2==pikchr text fossil, 3==raw SVG. */
1515
P.response = {/*stashed state for the server's preview response*/
1616
isError: false,
1717
inputText: undefined /* value of the editor field at render-time */,
18
- raw: undefined /* raw response text/HTML from server */
18
+ raw: undefined /* raw response text/HTML from server */,
19
+ rawSvg: undefined /* plain-text SVG part of responses. Required
20
+ because the browser will convert \u00a0 to
21
+   if we extract the SVG from the DOM,
22
+ resulting in illegal SVG. */
23
+ };
24
+
25
+ /**
26
+ If string r contains an SVG element, this returns that section
27
+ of the string, else it returns falsy.
28
+ */
29
+ const getResponseSvg = function(r){
30
+ const i0 = r.indexOf("<svg");
31
+ if(i0>=0){
32
+ const i1 = r.indexOf("</svg");
33
+ return r.substring(i0,i1+6);
34
+ }
35
+ return '';
1936
};
37
+
2038
F.onPageLoad(function() {
2139
document.body.classList.add('pikchrshow');
2240
P.e = { /* various DOM elements we work with... */
2341
previewTarget: E('#pikchrshow-output'),
2442
previewLegend: E('#pikchrshow-output-wrapper > legend'),
@@ -275,10 +293,14 @@
275293
}
276294
if(P.e.taContent.value){
277295
/* Fill our "response" state so that renderPreview() can work */
278296
P.response.inputText = P.e.taContent.value;
279297
P.response.raw = P.e.previewTarget.innerHTML;
298
+ P.response.rawSvg = getResponseSvg(
299
+ P.response.raw /*note that this is already in the DOM,
300
+ which means that the browser has already mangled
301
+ \u00a0 to &nbsp;, so...*/.split('&nbsp;').join('\u00a0'));
280302
if(needsPreview) P.preview();
281303
else{
282304
/*If it's from the server, it's already rendered, but this
283305
gets all labels/headers in sync.*/
284306
P.renderPreview();
@@ -323,12 +345,12 @@
323345
case 0:
324346
label = "SVG";
325347
f.showMarkupAlignment(false);
326348
D.parseHtml(D.clearElement(preTgt), P.response.raw);
327349
svg = preTgt.querySelector('svg.pikchr');
328
- if(svg){ /*for copy button*/
329
- this.e.taPreviewText.value = svg.outerHTML;
350
+ if(svg && P.response.rawSvg){ /*for copy button*/
351
+ this.e.taPreviewText.value = P.response.rawSvg;
330352
F.pikchr.addSrcView(svg);
331353
}
332354
break;
333355
case 1:
334356
label = "Markdown";
@@ -352,11 +374,12 @@
352374
case 3:
353375
label = "Raw SVG";
354376
f.showMarkupAlignment(false);
355377
svg = f.getSvgNode(this.response.raw);
356378
if(svg){
357
- this.e.taPreviewText.value = svg.outerHTML;
379
+ this.e.taPreviewText.value =
380
+ P.response.rawSvg || "Error extracting SVG element.";
358381
}else{
359382
this.e.taPreviewText.value = "ERROR parsing response HTML:\n"+
360383
this.response.raw;
361384
console.error("svg parsed HTML nodes:",childs);
362385
}
@@ -382,20 +405,21 @@
382405
];
383406
fp.target = this.e.previewTarget;
384407
fp.updateView = function(c,isError){
385408
P.previewMode = 0;
386409
P.response.raw = c;
410
+ P.response.rawSvg = getResponseSvg(c);
387411
P.response.isError = isError;
388412
D.enable(fp.toDisable);
389413
P.renderPreview();
390414
};
391415
}
392416
D.disable(fp.toDisable, this.e.previewModeToggle, this.e.markupAlignRadios);
393417
D.addClass(this.e.markupAlignWrapper, 'hidden');
394418
D.addClass(this.e.previewCopyButton, 'disabled');
395419
const content = this.e.taContent.value.trim();
396
- this.response.raw = undefined;
420
+ this.response.raw = this.response.rawSvg = undefined;
397421
this.response.inputText = content;
398422
const sampleScript = fp.$_sampleScript;
399423
delete fp.$_sampleScript;
400424
if(sampleScript && sampleScript.cached){
401425
fp.updateView(sampleScript.cached, false);
402426
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -13,12 +13,30 @@
13 P.previewMode = 0 /*0==rendered SVG, 1==pikchr text markdown,
14 2==pikchr text fossil, 3==raw SVG. */
15 P.response = {/*stashed state for the server's preview response*/
16 isError: false,
17 inputText: undefined /* value of the editor field at render-time */,
18 raw: undefined /* raw response text/HTML from server */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19 };
 
20 F.onPageLoad(function() {
21 document.body.classList.add('pikchrshow');
22 P.e = { /* various DOM elements we work with... */
23 previewTarget: E('#pikchrshow-output'),
24 previewLegend: E('#pikchrshow-output-wrapper > legend'),
@@ -275,10 +293,14 @@
275 }
276 if(P.e.taContent.value){
277 /* Fill our "response" state so that renderPreview() can work */
278 P.response.inputText = P.e.taContent.value;
279 P.response.raw = P.e.previewTarget.innerHTML;
 
 
 
 
280 if(needsPreview) P.preview();
281 else{
282 /*If it's from the server, it's already rendered, but this
283 gets all labels/headers in sync.*/
284 P.renderPreview();
@@ -323,12 +345,12 @@
323 case 0:
324 label = "SVG";
325 f.showMarkupAlignment(false);
326 D.parseHtml(D.clearElement(preTgt), P.response.raw);
327 svg = preTgt.querySelector('svg.pikchr');
328 if(svg){ /*for copy button*/
329 this.e.taPreviewText.value = svg.outerHTML;
330 F.pikchr.addSrcView(svg);
331 }
332 break;
333 case 1:
334 label = "Markdown";
@@ -352,11 +374,12 @@
352 case 3:
353 label = "Raw SVG";
354 f.showMarkupAlignment(false);
355 svg = f.getSvgNode(this.response.raw);
356 if(svg){
357 this.e.taPreviewText.value = svg.outerHTML;
 
358 }else{
359 this.e.taPreviewText.value = "ERROR parsing response HTML:\n"+
360 this.response.raw;
361 console.error("svg parsed HTML nodes:",childs);
362 }
@@ -382,20 +405,21 @@
382 ];
383 fp.target = this.e.previewTarget;
384 fp.updateView = function(c,isError){
385 P.previewMode = 0;
386 P.response.raw = c;
 
387 P.response.isError = isError;
388 D.enable(fp.toDisable);
389 P.renderPreview();
390 };
391 }
392 D.disable(fp.toDisable, this.e.previewModeToggle, this.e.markupAlignRadios);
393 D.addClass(this.e.markupAlignWrapper, 'hidden');
394 D.addClass(this.e.previewCopyButton, 'disabled');
395 const content = this.e.taContent.value.trim();
396 this.response.raw = undefined;
397 this.response.inputText = content;
398 const sampleScript = fp.$_sampleScript;
399 delete fp.$_sampleScript;
400 if(sampleScript && sampleScript.cached){
401 fp.updateView(sampleScript.cached, false);
402
--- src/fossil.page.pikchrshow.js
+++ src/fossil.page.pikchrshow.js
@@ -13,12 +13,30 @@
13 P.previewMode = 0 /*0==rendered SVG, 1==pikchr text markdown,
14 2==pikchr text fossil, 3==raw SVG. */
15 P.response = {/*stashed state for the server's preview response*/
16 isError: false,
17 inputText: undefined /* value of the editor field at render-time */,
18 raw: undefined /* raw response text/HTML from server */,
19 rawSvg: undefined /* plain-text SVG part of responses. Required
20 because the browser will convert \u00a0 to
21 &nbsp; if we extract the SVG from the DOM,
22 resulting in illegal SVG. */
23 };
24
25 /**
26 If string r contains an SVG element, this returns that section
27 of the string, else it returns falsy.
28 */
29 const getResponseSvg = function(r){
30 const i0 = r.indexOf("<svg");
31 if(i0>=0){
32 const i1 = r.indexOf("</svg");
33 return r.substring(i0,i1+6);
34 }
35 return '';
36 };
37
38 F.onPageLoad(function() {
39 document.body.classList.add('pikchrshow');
40 P.e = { /* various DOM elements we work with... */
41 previewTarget: E('#pikchrshow-output'),
42 previewLegend: E('#pikchrshow-output-wrapper > legend'),
@@ -275,10 +293,14 @@
293 }
294 if(P.e.taContent.value){
295 /* Fill our "response" state so that renderPreview() can work */
296 P.response.inputText = P.e.taContent.value;
297 P.response.raw = P.e.previewTarget.innerHTML;
298 P.response.rawSvg = getResponseSvg(
299 P.response.raw /*note that this is already in the DOM,
300 which means that the browser has already mangled
301 \u00a0 to &nbsp;, so...*/.split('&nbsp;').join('\u00a0'));
302 if(needsPreview) P.preview();
303 else{
304 /*If it's from the server, it's already rendered, but this
305 gets all labels/headers in sync.*/
306 P.renderPreview();
@@ -323,12 +345,12 @@
345 case 0:
346 label = "SVG";
347 f.showMarkupAlignment(false);
348 D.parseHtml(D.clearElement(preTgt), P.response.raw);
349 svg = preTgt.querySelector('svg.pikchr');
350 if(svg && P.response.rawSvg){ /*for copy button*/
351 this.e.taPreviewText.value = P.response.rawSvg;
352 F.pikchr.addSrcView(svg);
353 }
354 break;
355 case 1:
356 label = "Markdown";
@@ -352,11 +374,12 @@
374 case 3:
375 label = "Raw SVG";
376 f.showMarkupAlignment(false);
377 svg = f.getSvgNode(this.response.raw);
378 if(svg){
379 this.e.taPreviewText.value =
380 P.response.rawSvg || "Error extracting SVG element.";
381 }else{
382 this.e.taPreviewText.value = "ERROR parsing response HTML:\n"+
383 this.response.raw;
384 console.error("svg parsed HTML nodes:",childs);
385 }
@@ -382,20 +405,21 @@
405 ];
406 fp.target = this.e.previewTarget;
407 fp.updateView = function(c,isError){
408 P.previewMode = 0;
409 P.response.raw = c;
410 P.response.rawSvg = getResponseSvg(c);
411 P.response.isError = isError;
412 D.enable(fp.toDisable);
413 P.renderPreview();
414 };
415 }
416 D.disable(fp.toDisable, this.e.previewModeToggle, this.e.markupAlignRadios);
417 D.addClass(this.e.markupAlignWrapper, 'hidden');
418 D.addClass(this.e.previewCopyButton, 'disabled');
419 const content = this.e.taContent.value.trim();
420 this.response.raw = this.response.rawSvg = undefined;
421 this.response.inputText = content;
422 const sampleScript = fp.$_sampleScript;
423 delete fp.$_sampleScript;
424 if(sampleScript && sampleScript.cached){
425 fp.updateView(sampleScript.cached, false);
426

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button