#!/usr/bin/node
//Copyright Chris Xiong 2024
//License: Expat (MIT)
const content_dir='../content';
const image_dir='../content/img';
const process = require('node:process');
const path = require('node:path');
const util = require('node:util');
const fs = require('node:fs');
const jsdom = require('jsdom');
const spawn = require('child_process').spawn;
const image_size = require('image-size');
function promote_header(doc)
{
for (let i = 2; i <= 6; ++i)
{
const list = doc.querySelectorAll(`h${i}`);
for (let j = list.length - 1; j >= 0; --j)
{
const e = list[j];
const newe = doc.createElement(`h${i-1}`);
newe.innerHTML = e.innerHTML;
e.parentNode.replaceChild(newe, e);
}
}
}
function image_unsquash(doc, wd)
{
for (let im of doc.querySelectorAll('img'))
{
const d = image_size(path.join(wd, im.src));
if (d.width > d.height)
im.removeAttribute('width');
else if (d.width < d.height)
im.removeAttribute('height');
}
}
function image_relocate(doc, wd, imd)
{
for (let im of doc.querySelectorAll('img'))
{
fs.copyFileSync(path.join(wd, im.src), path.join(imd, im.src));
im.src = `//filestorage.chrisoft.org/blog/img/${im.src}`;
}
}
function css_embed(doc, cssc)
{
const style = doc.createElement('style');
style.textContent = cssc.replaceAll('font-family', 'not-font-family');
const body = doc.querySelector('body');
body.insertBefore(style, body.childNodes[0]);
}
async function main()
{
process.stdin.setEncoding('utf8');
const input = await new Promise((resolv, rej) => {
let d = '';
process.stdin.on('readable', () => { const r = process.stdin.read(); if (r) d += r; });
process.stdin.on('end',() => { resolv(d.trim()); });
});
const wd = path.resolve(path.join(content_dir, path.dirname(input)));
const fn = path.basename(input);
const fnb = path.basename(input, '.tex');
const make4htp = spawn('make4ht', ['-f', 'html5', fn, '"fn-in"'], {
cwd: wd,
shell: true,
stdio: ['ignore', 'pipe', 'pipe']
});
make4htp.stdout.setEncoding('utf8');
make4htp.stderr.setEncoding('utf8');
make4htp.stdout.on('data', (d) => { console.error(d); });
make4htp.stderr.on('data', (d) => { console.error(d); });
try {
await new Promise((resolv, rej) => {
make4htp.on('close', (r) => r ? rej(r) : resolv())
});
} catch (e) {
console.error(`make4ht failed with exitcode ${e}`);
return;
}
const htmlc = fs.readFileSync(path.join(wd, `${fnb}.html`), 'utf8');
const cssc = fs.readFileSync(path.join(wd, `${fnb}.css`), 'utf8');
const domrt = new jsdom.JSDOM(htmlc);
promote_header(domrt.window.document);
image_unsquash(domrt.window.document, wd);
image_relocate(domrt.window.document, wd, path.resolve(image_dir));
css_embed(domrt.window.document, cssc);
process.stdout.setEncoding('utf8');
process.stdout.write(domrt.window.document.querySelector('body').innerHTML);
}
main()