Files
js-scripts/scripts/markdownconvert.js
2025-06-20 22:13:06 +08:00

109 lines
4.8 KiB
JavaScript

#! /usr/bin/env runjs
requireJAR('markdown4j-2.2.jar');
var argsjs = require('component-args.js');
var counterjs = require('component-counter.js');
var File = java.io.File;
var FileUtil = Packages.me.hatter.tools.commons.file.FileUtil;
var Markdown4jProcessor = Packages.org.markdown4j.Markdown4jProcessor;
var BOOTSTRAP = 'https://play.hatter.me/css/bootstrap.css';
var BOOTSTRAP_THEME = 'https://play.hatter.me/css/bootstrap-theme.css';
var main = () => {
var args = argsjs.parseDefARGs();
if (args.length < 1) {
xprintln('[ERROR] Need arguments.');
xprintln();
xprintln('markdownconvert.js <file.md> [output.htm|output.pdf]');
xprintln();
xprintln(' -t, --title [PDF] Title');
//xprintln(' --author [PDF] Author')
return;
}
var mdFile = $$.file(args[0]);
if (!mdFile.exists()) {
xprintln('[ERROR] File not exists: ' + mdFile);
return;
}
xprintln('[INFO] Make tmp dir: .tmp')
var tmpDir = $$.file('.tmp');
tmpDir.mkdirs();
if (!$$.file(tmpDir, 'bootstrap.css').exists()) {
print('[INFO] Download file: bootstrap.css');
var fos = new java.io.FileOutputStream($$.file(tmpDir, 'bootstrap.css'));
$$.httpRequest().skipCertCheck().url(BOOTSTRAP).get(fos, counterjs.getCounter());
fos.close();
println();
}
if (!$$.file(tmpDir, 'bootstrap-theme.css').exists()) {
print('[INFO] Download file: bootstrap-theme.css');
var fos = new java.io.FileOutputStream($$.file(tmpDir, 'bootstrap-theme.css'));
$$.httpRequest().skipCertCheck().url(BOOTSTRAP_THEME).get(fos, counterjs.getCounter());
fos.close();
println();
}
var isPDF = false;
var targetFile = (args.length > 1) ? $$.file(args[1]) : $$.file(mdFile.getAbsoluteFile().getParentFile(), mdFile.getName() + '.pdf');
if (targetFile.getName().toLowerCase().endsWith('.pdf')) {
isPDF = true;
}
var htmlFile = (isPDF) ? $$.file('.tmp.htm') : targetFile;
xprintln('[INFO] Render markdown file to html file: ' + htmlFile.getName());
var md = $$.rFile(mdFile).string();
var html = new Markdown4jProcessor().process(md);
html = '<html>\n'
+ '<head>\n'
+ '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n'
+ '<link href=".tmp/bootstrap.css" rel="stylesheet">\n'
+ '<link href=".tmp/bootstrap-theme.css" rel="stylesheet">\n'
+ '</head>\n'
+ '<body>\n\n\n' + html + '\n\n\n</body>\n'
+ '</html>\n';
$$.rFile(htmlFile).write(html);
if (isPDF) {
xprintln('[INFO] Render html file to pdf file: ' + targetFile.getName());
var title = (args.val('t', 'title') || targetFile.getName()).replace('"', '\\"');
// https://manual.calibre-ebook.com/conversion.html
$$.shell().commands('sh', '-c',
'ebook-convert '
+ htmlFile.getAbsolutePath()
+ ' ' + targetFile.getAbsolutePath()
+ ' --title="' + title + '" --comments="" --language="en"'
//+ '--authors="' + (args.val('author') || $$.env('USER')) + '"'
+ ' --book-producer="markdownconvert.js" --publisher="markdownconvert.js"'
//+ ' --chapter="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter \')]"'
// DEFAULT: //*[((name()='h1' or name()='h2') and re:test(., 'chapter|book|section|part\s+', 'i')) or @class = 'chapter']
+ ' --chapter="//*[(name()=\'h2\') or @class = \'chapter\']"'
+ ' --chapter-mark="pagebreak" --page-breaks-before="/"'
+ ' --level1-toc="//*[(name()=\'h3\') or @class = \'section\']"'
//+ ' --level1-toc="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter-1 \')]"'
//+ ' --level2-toc="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter-2 \')]"'
//+ ' --level3-toc="descendant-or-self::*[contains(concat(\' \', normalize-space(@class), \' \'), \' book-chapter-3 \')]"'
//+ ' --no-chapters-in-toc'
//+ ' --pdf-add-toc'
+ ' --max-levels="1" --breadth-first'
+ ' --margin-left="62" --margin-right="62" --margin-top="56" --margin-bottom="56"'
+ ' --pdf-default-font-size="12" --pdf-mono-font-size="12"'
+ ' --paper-size="a4"'
+ ' --pdf-header-template="<p class=\'header\'><span style=\'color:gray;\'>_TITLE_</span></p>"'
+ ' --pdf-footer-template="<p class=\'footer\'><span>_SECTION_</span> <span style=\'float:right;\'>_PAGENUM_</span></p>"')
.run();
xprintln('[INFO] Clean up tmp files.');
htmlFile.delete();
FileUtil.deleteDirectory(tmpDir);
}
};
main();