aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.rst1
-rw-r--r--generator/postrenderer.js76
-rw-r--r--generator/scanner.js10
-rw-r--r--generator/util.js19
4 files changed, 80 insertions, 26 deletions
diff --git a/README.rst b/README.rst
index 9a165cb..feee8fc 100644
--- a/README.rst
+++ b/README.rst
@@ -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;
+}