diff options
-rw-r--r-- | README.rst | 1 | ||||
-rw-r--r-- | generator/postrenderer.js | 76 | ||||
-rw-r--r-- | generator/scanner.js | 10 | ||||
-rw-r--r-- | generator/util.js | 19 |
4 files changed, 80 insertions, 26 deletions
@@ -17,6 +17,7 @@ Dependencies: - jsdom - aes-js - scrypt-js + - Imagemagick >7.x (for thumbnail generation) Usage: diff --git a/generator/postrenderer.js b/generator/postrenderer.js index e387691..f3cf46b 100644 --- a/generator/postrenderer.js +++ b/generator/postrenderer.js @@ -12,6 +12,11 @@ const scrypt=require('scrypt-js'); const btoa=require('btoa'); const sha256=require('./sha256').sha256; const spawn=require('child_process').spawn; +const util=require('./util'); + +const THUMB_IMAGE_URL='//filestorage.chrisoft.org/blog/img/'; +const THUMB_LOCAL_DIR='../content/img/'; + let template_file=''; let tmplcont=''; let tocid; @@ -43,26 +48,58 @@ function _dfs(doc,el,le,p) } function footnoter(doc) { - var footnotes=doc.body.getElementsByTagName("footnote"); - let starting=doc.getElementById("notediv").children.length; + var footnotes=doc.body.getElementsByTagName('footnote'); + let starting=doc.getElementById('notediv').children.length; for(var i=0;i<footnotes.length;++i) { var s=footnotes[i].innerHTML; - footnotes[i].innerHTML=""; - var a=doc.createElement("a"); - a.setAttribute("id","n"+(starting+i+1)); - a.setAttribute("href","#note"+(starting+i+1)); - a.setAttribute("class","note"); - a.innerHTML="["+(starting+i+1)+"]"; + footnotes[i].innerHTML=''; + var a=doc.createElement('a'); + a.setAttribute('id',`n${(starting+i+1)}`); + a.setAttribute('href',`#note${(starting+i+1)}`); + a.setAttribute('class','note'); + a.innerHTML=`[${(starting+i+1)}]`; footnotes[i].parentNode.insertBefore(a,footnotes[i]); - var span=doc.createElement("span"); - span.setAttribute("class","TText"); - span.innerHTML="<a id=\"note"+(starting+i+1)+"\" href=\"#n"+(starting+i+1)+"\">["+(starting+i+1)+"]</a>: "+s+"<br>"; - doc.getElementById("notediv").appendChild(span); + var span=doc.createElement('span'); + span.setAttribute('class','TText'); + span.innerHTML=`<a id="note${(starting+i+1)}" href="#n${(starting+i+1)}">[${(starting+i+1)}]</a>: ${s}<br>`; + doc.getElementById('notediv').appendChild(span); } starting+=footnotes.length; while(footnotes.length)footnotes[0].remove(); } +function gen_thumb(doc,el) +{ + const a=doc.createElement('a'); + const im=doc.createElement('img'); + const srcfn=el.innerHTML; + let w=el.hasAttribute('width')?Number(el.getAttribute('width')):-1; + let h=el.hasAttribute('height')?Number(el.getAttribute('height')):-1; + let p=el.hasAttribute('scale')?Number(el.getAttribute('scale')):-1; + if(el.hasAttribute('iw')) + im.style.width=el.getAttribute('iw'); + if(el.hasAttribute('ih')) + im.style.height=el.getAttribute('ih'); + if(p>0)w=h=-1; + if(w>0||h>0) + { + if(w<=0)w=h; + else if(h<=0)h=w; + } + const dstfn=`ssbsthumb_${p>0?'s'+p.toFixed(2):w+'x'+h}_${srcfn}` + const srcf=path.join(THUMB_LOCAL_DIR,srcfn); + const dstf=path.join(THUMB_LOCAL_DIR,dstfn); + if(!util.mtime_cmp(srcf,dstf)) + { + const m=spawn('magick',[srcf,'-resize',p>0?(p*100).toFixed()+'%':w+'x'+h,dstf]); + m.stdout.on('data',(d)=>{console.log(`IMout:${d}`);}); + m.stderr.on('data',(d)=>{console.log(`IMerr:${d}`);}); + } + a.setAttribute('href',THUMB_IMAGE_URL+srcfn); + im.src=THUMB_IMAGE_URL+dstfn; + a.appendChild(im); + el.parentNode.replaceChild(a,el); +} async function encrypt(doc) { let enid=0; @@ -128,6 +165,14 @@ async function _render(inf,outf,np,pp) } else trd.getElementById('article').innerHTML=contsplit.join('\n'); + + //async images + trd.getElementById('article').querySelectorAll('img').forEach( + (i)=>{if(!i.getAttribute('decoding'))i.setAttribute('decoding','async');} + ); + + //thumbnails generation + trd.getElementById('article').querySelectorAll('thumb').forEach((el)=>{gen_thumb(trd,el);}); //Encryption await encrypt(trd); @@ -144,13 +189,6 @@ async function _render(inf,outf,np,pp) //Footnotes footnoter(trd); - - //async images - //TODO: Actually compress the images using imagemagick - //(by introducing a new tag e.g. <thumb> ?) - trd.getElementById('article').querySelectorAll('img').forEach( - (i)=>{if(!i.getAttribute('decoding'))i.setAttribute('decoding','async');} - ); //Tag list const tgs=meta[2].split(','); diff --git a/generator/scanner.js b/generator/scanner.js index 87b3f2f..52744a4 100644 --- a/generator/scanner.js +++ b/generator/scanner.js @@ -6,6 +6,7 @@ module.exports={ }; const fs=require('fs'); const path=require('path'); +const util=require('./util'); const list=[]; const tags=[]; function _scan(s,dst) @@ -22,11 +23,6 @@ function _scan(s,dst) if(i.endsWith('.txt')) { const cont=fs.readFileSync(path.join(s,i),'utf8'); - const smodt=fs.statSync(path.join(s,i)).mtimeMs; - let dmodt=0; - try{ - dmodt=fs.statSync(path.join(pdst,i.substring(0,i.length-4)+'.html')).mtimeMs; - }catch(e){}; contsplit=cont.split('\n'); if(contsplit.length<4)continue; if(contsplit[1].indexOf('WIP')!=-1)continue; @@ -35,8 +31,8 @@ function _scan(s,dst) title:contsplit[0].trim(), date:contsplit[1].trim(), tags:contsplit[2].trim(), - mdate:smodt, - needsupdate:dmodt<smodt + mdate:fs.statSync(path.join(s,i)).mtimeMs, + needsupdate:!util.mtime_cmp(path.join(s,i),path.join(pdst,i.substring(0,i.length-4)+'.html')) }); } diff --git a/generator/util.js b/generator/util.js new file mode 100644 index 0000000..e9b5c78 --- /dev/null +++ b/generator/util.js @@ -0,0 +1,19 @@ +//Copyright Chris Xiong 2019 +//License: Expat (MIT) +module.exports={ + mtime_cmp:function(a,b){return _mtime_cmp(a,b);} +}; +const fs=require('fs'); + +/*Returns true when file b exists and has a mtime no earlier than file a, + *false otherwise. + */ +function _mtime_cmp(a,b) +{ + const mtimea=fs.statSync(a).mtimeMs; + let mtimeb=0; + try{ + mtimeb=fs.statSync(b).mtimeMs; + }catch(e){return false}; + return mtimeb>=mtimea; +} |