Fossil SCM

More pikchrshow cleanups. Corrected the body text for the markdown/wiki render modes (was using the SVG instead of pikchr code). Center the pikchr when not in auto-fit mode.

stephan 2022-06-07 12:07 pikchrshow-wasm
Commit e23286a60b03a9b43af8bb0a784ba50773f315f4399c7d3b20c499ac81d816db
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -59,11 +59,12 @@
5959
previewCopyButton: E('#preview-copy-button'),
6060
previewModeLabel: E('label[for=preview-copy-button]'),
6161
zoneOutputButtons: E('.zone-wrapper.output > legend > .button-bar'),
6262
outText: E('#pikchr-output-text'),
6363
pikOutWrapper: E('#pikchr-output-wrapper'),
64
- pikOut: E('#pikchr-output')
64
+ pikOut: E('#pikchr-output'),
65
+ btnRender: E('#btn-render')
6566
},
6667
renderModes: ['svg'/*SVG must be at index 0*/,'markdown', 'wiki', 'text'],
6768
renderModeLabels: {
6869
svg: 'SVG', markdown: 'Markdown', wiki: 'Fossil Wiki', text: 'Text'
6970
},
@@ -189,26 +190,24 @@
189190
const taInput = E('#input');
190191
const btnClearIn = E('#btn-clear');
191192
btnClearIn.addEventListener('click',function(){
192193
taInput.value = '';
193194
},false);
194
- const taOutput = E('#output');
195
- const btnRender = E('#btn-render');
196195
const getCurrentText = function(){
197196
let text;
198197
if(taInput.selectionStart<taInput.selectionEnd){
199198
text = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim();
200199
}else{
201200
text = taInput.value.trim();
202201
}
203202
return text;;
204
- }
203
+ };
205204
const renderCurrentText = function(){
206205
const text = getCurrentText();
207206
if(text) PS.render(text);
208207
};
209
- btnRender.addEventListener('click',function(ev){
208
+ PS.e.btnRender.addEventListener('click',function(ev){
210209
ev.preventDefault();
211210
renderCurrentText();
212211
},false);
213212
214213
0 && (function(){
@@ -278,17 +277,16 @@
278277
*/
279278
const preStartWork = function f(){
280279
if(!f._){
281280
const title = E('title');
282281
f._ = {
283
- btnLabel: btnRender.innerText,
284282
pageTitle: title,
285283
pageTitleOrig: title.innerText
286284
};
287285
}
288286
//f._.pageTitle.innerText = "[working...] "+f._.pageTitleOrig;
289
- btnRender.setAttribute('disabled','disabled');
287
+ PS.e.btnRender.setAttribute('disabled','disabled');
290288
};
291289
292290
/**
293291
Submits the current input text to pikchr and renders the
294292
result. */
@@ -298,72 +296,76 @@
298296
pikchr: txt,
299297
darkMode: !!window.fossil.config.skin.isDark
300298
});
301299
};
302300
301
+ /**
302
+ Event handler for 'pikchr' messages from the Worker thread.
303
+ */
303304
PS.addMsgHandler('pikchr', function(ev){
304305
const m = ev.data;
305
- PS.e.pikOut.classList[m.isError ? 'add' : 'remove']('error');
306
- PS.e.pikOut.dataset.pikchr = m.pikchr;
307
- const mode = PS.renderModes[PS.renderModes.selectedIndex];
306
+ this.e.pikOut.classList[m.isError ? 'add' : 'remove']('error');
307
+ this.e.pikOut.dataset.pikchr = m.pikchr;
308
+ const mode = this.renderModes[this.renderModes.selectedIndex];
308309
switch(mode){
309
- case 'text':
310
- case 'markdown':
311
- case 'wiki': {
312
- const body = [m.result];
313
- if('markdown'===mode){
314
- body.unshift('```pikchr');
315
- body.push('```');
316
- }else if('wiki'===mode){
317
- body.unshift('<verbatim type="pikchr">');
318
- body.push('</verbatim>');
319
- }
320
- PS.e.outText.value = body.join('\n');
321
- PS.e.outText.classList.remove('hidden');
322
- PS.e.pikOut.classList.add('hidden');
323
- PS.e.pikOutWrapper.classList.add('text');
310
+ case 'text': case 'markdown': case 'wiki': {
311
+ let body;
312
+ switch(mode){
313
+ case 'markdown':
314
+ body = ['```pikchr', m.pikchr, '```'].join('\n');
315
+ break;
316
+ case 'wiki':
317
+ body = ['<verbatim type="pikchr">', m.pikchr, '</verbatim>'].join('');
318
+ break;
319
+ default:
320
+ body = m.result;
321
+ }
322
+ this.e.outText.value = body;
323
+ this.e.outText.classList.remove('hidden');
324
+ this.e.pikOut.classList.add('hidden');
325
+ this.e.pikOutWrapper.classList.add('text');
324326
break;
325327
}
326328
case 'svg':
327
- PS.e.outText.classList.add('hidden');
328
- PS.e.pikOut.classList.remove('hidden');
329
- PS.e.pikOutWrapper.classList.remove('text');
330
- PS.e.pikOut.innerHTML = m.result;
331
- PS.e.outText.value = m.result/*for clipboard copy*/;
329
+ this.e.outText.classList.add('hidden');
330
+ this.e.pikOut.classList.remove('hidden');
331
+ this.e.pikOutWrapper.classList.remove('text');
332
+ this.e.pikOut.innerHTML = m.result;
333
+ this.e.outText.value = m.result/*for clipboard copy*/;
332334
break;
333335
default: throw new Error("Unhandled render mode: "+mode);
334336
}
335337
let vw = null, vh = null;
336
- if('svg'===mode && !PS.config.renderAutofit && !m.isError){
338
+ if('svg'===mode && !this.config.renderAutofit && !m.isError){
337339
vw = m.width; vh = m.height;
338340
}
339
- PS.e.pikOut.style.width = vw ? vw+'px' : null;
340
- PS.e.pikOut.style.height = vh ? vh+'px' : null;
341
- })/*'pikchr' msg handler*/;
341
+ this.e.pikOut.style.width = vw ? vw+'px' : null;
342
+ this.e.pikOut.style.height = vh ? vh+'px' : null;
343
+ }.bind(PS))/*'pikchr' msg handler*/;
342344
343345
E('#btn-render-mode').addEventListener('click',function(){
344
- const modes = PS.renderModes;
346
+ const modes = this.renderModes;
345347
modes.selectedIndex = (modes.selectedIndex + 1) % modes.length;
346
- PS.e.previewModeLabel.innerText = PS.renderModeLabels[modes[modes.selectedIndex]];
347
- if(PS.e.pikOut.dataset.pikchr){
348
- PS.render(PS.e.pikOut.dataset.pikchr);
348
+ this.e.previewModeLabel.innerText = this.renderModeLabels[modes[modes.selectedIndex]];
349
+ if(this.e.pikOut.dataset.pikchr){
350
+ this.render(this.e.pikOut.dataset.pikchr);
349351
}
350
- });
352
+ }.bind(PS));
351353
F.copyButton(PS.e.previewCopyButton, {copyFromElement: PS.e.outText});
352354
PS.e.previewModeLabel.addEventListener('click', ()=>PS.e.previewCopyButton.click(), false);
353355
354356
PS.addMsgHandler('working',function f(ev){
355357
switch(ev.data){
356358
case 'start': /* See notes in preStartWork(). */; return;
357359
case 'end':
358360
//preStartWork._.pageTitle.innerText = preStartWork._.pageTitleOrig;
359
- btnRender.innerText = preStartWork._.btnLabel;
360
- btnRender.removeAttribute('disabled');
361
+ this.e.btnRender.removeAttribute('disabled');
362
+ this.e.pikOutWrapper.classList[this.config.renderAutofit ? 'add' : 'remove']('autofit');
361363
return;
362364
}
363365
console.warn("Unhandled 'working' event:",ev.data);
364
- });
366
+ }.bind(PS));
365367
366368
/* For each checkbox with data-csstgt, set up a handler which
367369
toggles the given CSS class on the element matching
368370
E(data-csstgt). */
369371
EAll('input[type=checkbox][data-csstgt]')
@@ -443,11 +445,11 @@
443445
fs.classList.toggle('collapsed');
444446
content.forEach((d)=>d.classList.toggle('hidden'));
445447
}, false);
446448
});
447449
448
- btnRender.click();
450
+ PS.e.btnRender.click();
449451
450452
/** Debounce handler for auto-rendering while typing. */
451453
const debounceAutoRender = F.debounce(function f(){
452454
if(!PS._isDirty) return;
453455
const text = getCurrentText();
454456
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -59,11 +59,12 @@
59 previewCopyButton: E('#preview-copy-button'),
60 previewModeLabel: E('label[for=preview-copy-button]'),
61 zoneOutputButtons: E('.zone-wrapper.output > legend > .button-bar'),
62 outText: E('#pikchr-output-text'),
63 pikOutWrapper: E('#pikchr-output-wrapper'),
64 pikOut: E('#pikchr-output')
 
65 },
66 renderModes: ['svg'/*SVG must be at index 0*/,'markdown', 'wiki', 'text'],
67 renderModeLabels: {
68 svg: 'SVG', markdown: 'Markdown', wiki: 'Fossil Wiki', text: 'Text'
69 },
@@ -189,26 +190,24 @@
189 const taInput = E('#input');
190 const btnClearIn = E('#btn-clear');
191 btnClearIn.addEventListener('click',function(){
192 taInput.value = '';
193 },false);
194 const taOutput = E('#output');
195 const btnRender = E('#btn-render');
196 const getCurrentText = function(){
197 let text;
198 if(taInput.selectionStart<taInput.selectionEnd){
199 text = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim();
200 }else{
201 text = taInput.value.trim();
202 }
203 return text;;
204 }
205 const renderCurrentText = function(){
206 const text = getCurrentText();
207 if(text) PS.render(text);
208 };
209 btnRender.addEventListener('click',function(ev){
210 ev.preventDefault();
211 renderCurrentText();
212 },false);
213
214 0 && (function(){
@@ -278,17 +277,16 @@
278 */
279 const preStartWork = function f(){
280 if(!f._){
281 const title = E('title');
282 f._ = {
283 btnLabel: btnRender.innerText,
284 pageTitle: title,
285 pageTitleOrig: title.innerText
286 };
287 }
288 //f._.pageTitle.innerText = "[working...] "+f._.pageTitleOrig;
289 btnRender.setAttribute('disabled','disabled');
290 };
291
292 /**
293 Submits the current input text to pikchr and renders the
294 result. */
@@ -298,72 +296,76 @@
298 pikchr: txt,
299 darkMode: !!window.fossil.config.skin.isDark
300 });
301 };
302
 
 
 
303 PS.addMsgHandler('pikchr', function(ev){
304 const m = ev.data;
305 PS.e.pikOut.classList[m.isError ? 'add' : 'remove']('error');
306 PS.e.pikOut.dataset.pikchr = m.pikchr;
307 const mode = PS.renderModes[PS.renderModes.selectedIndex];
308 switch(mode){
309 case 'text':
310 case 'markdown':
311 case 'wiki': {
312 const body = [m.result];
313 if('markdown'===mode){
314 body.unshift('```pikchr');
315 body.push('```');
316 }else if('wiki'===mode){
317 body.unshift('<verbatim type="pikchr">');
318 body.push('</verbatim>');
319 }
320 PS.e.outText.value = body.join('\n');
321 PS.e.outText.classList.remove('hidden');
322 PS.e.pikOut.classList.add('hidden');
323 PS.e.pikOutWrapper.classList.add('text');
 
324 break;
325 }
326 case 'svg':
327 PS.e.outText.classList.add('hidden');
328 PS.e.pikOut.classList.remove('hidden');
329 PS.e.pikOutWrapper.classList.remove('text');
330 PS.e.pikOut.innerHTML = m.result;
331 PS.e.outText.value = m.result/*for clipboard copy*/;
332 break;
333 default: throw new Error("Unhandled render mode: "+mode);
334 }
335 let vw = null, vh = null;
336 if('svg'===mode && !PS.config.renderAutofit && !m.isError){
337 vw = m.width; vh = m.height;
338 }
339 PS.e.pikOut.style.width = vw ? vw+'px' : null;
340 PS.e.pikOut.style.height = vh ? vh+'px' : null;
341 })/*'pikchr' msg handler*/;
342
343 E('#btn-render-mode').addEventListener('click',function(){
344 const modes = PS.renderModes;
345 modes.selectedIndex = (modes.selectedIndex + 1) % modes.length;
346 PS.e.previewModeLabel.innerText = PS.renderModeLabels[modes[modes.selectedIndex]];
347 if(PS.e.pikOut.dataset.pikchr){
348 PS.render(PS.e.pikOut.dataset.pikchr);
349 }
350 });
351 F.copyButton(PS.e.previewCopyButton, {copyFromElement: PS.e.outText});
352 PS.e.previewModeLabel.addEventListener('click', ()=>PS.e.previewCopyButton.click(), false);
353
354 PS.addMsgHandler('working',function f(ev){
355 switch(ev.data){
356 case 'start': /* See notes in preStartWork(). */; return;
357 case 'end':
358 //preStartWork._.pageTitle.innerText = preStartWork._.pageTitleOrig;
359 btnRender.innerText = preStartWork._.btnLabel;
360 btnRender.removeAttribute('disabled');
361 return;
362 }
363 console.warn("Unhandled 'working' event:",ev.data);
364 });
365
366 /* For each checkbox with data-csstgt, set up a handler which
367 toggles the given CSS class on the element matching
368 E(data-csstgt). */
369 EAll('input[type=checkbox][data-csstgt]')
@@ -443,11 +445,11 @@
443 fs.classList.toggle('collapsed');
444 content.forEach((d)=>d.classList.toggle('hidden'));
445 }, false);
446 });
447
448 btnRender.click();
449
450 /** Debounce handler for auto-rendering while typing. */
451 const debounceAutoRender = F.debounce(function f(){
452 if(!PS._isDirty) return;
453 const text = getCurrentText();
454
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -59,11 +59,12 @@
59 previewCopyButton: E('#preview-copy-button'),
60 previewModeLabel: E('label[for=preview-copy-button]'),
61 zoneOutputButtons: E('.zone-wrapper.output > legend > .button-bar'),
62 outText: E('#pikchr-output-text'),
63 pikOutWrapper: E('#pikchr-output-wrapper'),
64 pikOut: E('#pikchr-output'),
65 btnRender: E('#btn-render')
66 },
67 renderModes: ['svg'/*SVG must be at index 0*/,'markdown', 'wiki', 'text'],
68 renderModeLabels: {
69 svg: 'SVG', markdown: 'Markdown', wiki: 'Fossil Wiki', text: 'Text'
70 },
@@ -189,26 +190,24 @@
190 const taInput = E('#input');
191 const btnClearIn = E('#btn-clear');
192 btnClearIn.addEventListener('click',function(){
193 taInput.value = '';
194 },false);
 
 
195 const getCurrentText = function(){
196 let text;
197 if(taInput.selectionStart<taInput.selectionEnd){
198 text = taInput.value.substring(taInput.selectionStart,taInput.selectionEnd).trim();
199 }else{
200 text = taInput.value.trim();
201 }
202 return text;;
203 };
204 const renderCurrentText = function(){
205 const text = getCurrentText();
206 if(text) PS.render(text);
207 };
208 PS.e.btnRender.addEventListener('click',function(ev){
209 ev.preventDefault();
210 renderCurrentText();
211 },false);
212
213 0 && (function(){
@@ -278,17 +277,16 @@
277 */
278 const preStartWork = function f(){
279 if(!f._){
280 const title = E('title');
281 f._ = {
 
282 pageTitle: title,
283 pageTitleOrig: title.innerText
284 };
285 }
286 //f._.pageTitle.innerText = "[working...] "+f._.pageTitleOrig;
287 PS.e.btnRender.setAttribute('disabled','disabled');
288 };
289
290 /**
291 Submits the current input text to pikchr and renders the
292 result. */
@@ -298,72 +296,76 @@
296 pikchr: txt,
297 darkMode: !!window.fossil.config.skin.isDark
298 });
299 };
300
301 /**
302 Event handler for 'pikchr' messages from the Worker thread.
303 */
304 PS.addMsgHandler('pikchr', function(ev){
305 const m = ev.data;
306 this.e.pikOut.classList[m.isError ? 'add' : 'remove']('error');
307 this.e.pikOut.dataset.pikchr = m.pikchr;
308 const mode = this.renderModes[this.renderModes.selectedIndex];
309 switch(mode){
310 case 'text': case 'markdown': case 'wiki': {
311 let body;
312 switch(mode){
313 case 'markdown':
314 body = ['```pikchr', m.pikchr, '```'].join('\n');
315 break;
316 case 'wiki':
317 body = ['<verbatim type="pikchr">', m.pikchr, '</verbatim>'].join('');
318 break;
319 default:
320 body = m.result;
321 }
322 this.e.outText.value = body;
323 this.e.outText.classList.remove('hidden');
324 this.e.pikOut.classList.add('hidden');
325 this.e.pikOutWrapper.classList.add('text');
326 break;
327 }
328 case 'svg':
329 this.e.outText.classList.add('hidden');
330 this.e.pikOut.classList.remove('hidden');
331 this.e.pikOutWrapper.classList.remove('text');
332 this.e.pikOut.innerHTML = m.result;
333 this.e.outText.value = m.result/*for clipboard copy*/;
334 break;
335 default: throw new Error("Unhandled render mode: "+mode);
336 }
337 let vw = null, vh = null;
338 if('svg'===mode && !this.config.renderAutofit && !m.isError){
339 vw = m.width; vh = m.height;
340 }
341 this.e.pikOut.style.width = vw ? vw+'px' : null;
342 this.e.pikOut.style.height = vh ? vh+'px' : null;
343 }.bind(PS))/*'pikchr' msg handler*/;
344
345 E('#btn-render-mode').addEventListener('click',function(){
346 const modes = this.renderModes;
347 modes.selectedIndex = (modes.selectedIndex + 1) % modes.length;
348 this.e.previewModeLabel.innerText = this.renderModeLabels[modes[modes.selectedIndex]];
349 if(this.e.pikOut.dataset.pikchr){
350 this.render(this.e.pikOut.dataset.pikchr);
351 }
352 }.bind(PS));
353 F.copyButton(PS.e.previewCopyButton, {copyFromElement: PS.e.outText});
354 PS.e.previewModeLabel.addEventListener('click', ()=>PS.e.previewCopyButton.click(), false);
355
356 PS.addMsgHandler('working',function f(ev){
357 switch(ev.data){
358 case 'start': /* See notes in preStartWork(). */; return;
359 case 'end':
360 //preStartWork._.pageTitle.innerText = preStartWork._.pageTitleOrig;
361 this.e.btnRender.removeAttribute('disabled');
362 this.e.pikOutWrapper.classList[this.config.renderAutofit ? 'add' : 'remove']('autofit');
363 return;
364 }
365 console.warn("Unhandled 'working' event:",ev.data);
366 }.bind(PS));
367
368 /* For each checkbox with data-csstgt, set up a handler which
369 toggles the given CSS class on the element matching
370 E(data-csstgt). */
371 EAll('input[type=checkbox][data-csstgt]')
@@ -443,11 +445,11 @@
445 fs.classList.toggle('collapsed');
446 content.forEach((d)=>d.classList.toggle('hidden'));
447 }, false);
448 });
449
450 PS.e.btnRender.click();
451
452 /** Debounce handler for auto-rendering while typing. */
453 const debounceAutoRender = F.debounce(function f(){
454 if(!PS._isDirty) return;
455 const text = getCurrentText();
456
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -457,11 +457,15 @@
457457
CX("<label for='opt-cb-swapio'>Swap in/out</label>");
458458
CX("</span>");
459459
CX("<span class='labeled-input'>");
460460
CX("<input type='checkbox' id='opt-cb-autofit' ");
461461
CX("data-config='renderAutofit'>");
462
- CX("<label for='opt-cb-autofit'>Auto-fit SVG</label>");
462
+ CX("<label for='opt-cb-autofit' "
463
+ "title='Attempt to scale SVG to fit viewport. "
464
+ "Whether it will work depends in part on the size "
465
+ "and shape of the image and the viewport.'"
466
+ ">Auto-fit SVG</label>");
463467
CX("</span>");
464468
CX("<span class='labeled-input'>");
465469
CX("<input type='checkbox' id='opt-cb-autorender' ");
466470
CX("data-csstgt='#main-wrapper' ");
467471
CX("data-cssclass='auto-render' ");
468472
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -457,11 +457,15 @@
457 CX("<label for='opt-cb-swapio'>Swap in/out</label>");
458 CX("</span>");
459 CX("<span class='labeled-input'>");
460 CX("<input type='checkbox' id='opt-cb-autofit' ");
461 CX("data-config='renderAutofit'>");
462 CX("<label for='opt-cb-autofit'>Auto-fit SVG</label>");
 
 
 
 
463 CX("</span>");
464 CX("<span class='labeled-input'>");
465 CX("<input type='checkbox' id='opt-cb-autorender' ");
466 CX("data-csstgt='#main-wrapper' ");
467 CX("data-cssclass='auto-render' ");
468
--- src/pikchrshow.c
+++ src/pikchrshow.c
@@ -457,11 +457,15 @@
457 CX("<label for='opt-cb-swapio'>Swap in/out</label>");
458 CX("</span>");
459 CX("<span class='labeled-input'>");
460 CX("<input type='checkbox' id='opt-cb-autofit' ");
461 CX("data-config='renderAutofit'>");
462 CX("<label for='opt-cb-autofit' "
463 "title='Attempt to scale SVG to fit viewport. "
464 "Whether it will work depends in part on the size "
465 "and shape of the image and the viewport.'"
466 ">Auto-fit SVG</label>");
467 CX("</span>");
468 CX("<span class='labeled-input'>");
469 CX("<input type='checkbox' id='opt-cb-autorender' ");
470 CX("data-csstgt='#main-wrapper' ");
471 CX("data-cssclass='auto-render' ");
472
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -91,10 +91,13 @@
9191
margin: 0;
9292
}
9393
#pikchr-output-wrapper {
9494
flex: 1 1 auto;
9595
overflow: auto;
96
+}
97
+#pikchr-output-wrapper:not(.autofit) {
98
+ align-items: center;
9699
}
97100
#pikchr-output-wrapper.text {
98101
display: flex;
99102
align-items: stretch;
100103
}
101104
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -91,10 +91,13 @@
91 margin: 0;
92 }
93 #pikchr-output-wrapper {
94 flex: 1 1 auto;
95 overflow: auto;
 
 
 
96 }
97 #pikchr-output-wrapper.text {
98 display: flex;
99 align-items: stretch;
100 }
101
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -91,10 +91,13 @@
91 margin: 0;
92 }
93 #pikchr-output-wrapper {
94 flex: 1 1 auto;
95 overflow: auto;
96 }
97 #pikchr-output-wrapper:not(.autofit) {
98 align-items: center;
99 }
100 #pikchr-output-wrapper.text {
101 display: flex;
102 align-items: stretch;
103 }
104

Keyboard Shortcuts

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