#! /usr/bin/env runjs var ByteArrayOutputStream = java.io.ByteArrayOutputStream; var Bytes = Packages.me.hatter.tools.commons.bytes.Bytes; var FileUtil = Packages.me.hatter.tools.commons.file.FileUtil; var argsjs = require('component-args.js'); var CALIBRE_HOME = '/Applications/calibre.app/Contents/MacOS'; var DOT = 'dot'; var NPM = 'npm'; var GITBOOK = 'gitbook'; var CALIBRE_EBOOK_CONVERT = 'ebook-convert'; var NODE_INSTALL_URL = 'https://nodejs.org/en/download/'; var CALIBRE_INSTALL_URL = 'https://calibre-ebook.com/download'; var DOT_INSTALL = 'brew install graphviz'; var GITBOOK_INSTALL = 'npm install -g gitbook-cli'; var DEFAULT_PROCESSOR_VIZ = null; var DEFAULT_PROCESSOR = { 'plantuml': (lns, tmpDir) => { $ONCE('gitbook.js-defaultprocessor-plantuml-requirejar-plantuml').run(() => { requireJAR('plantuml-8059.jar'); }); var FileFormat = Packages.net.sourceforge.plantuml.FileFormat; var FileFormatOption = Packages.net.sourceforge.plantuml.FileFormatOption; var SourceStringReader = Packages.net.sourceforge.plantuml.SourceStringReader; var puml = $ARR(lns).join('\n'); var dgst = Bytes.from(puml).digest($$.digests().sha256()).asHex(); var baos = new ByteArrayOutputStream(); var reader = new SourceStringReader(puml); reader.generateImage(baos, new FileFormatOption(FileFormat.PNG, false)); $$.rFile(tmpDir, dgst + '.png').write(baos.toByteArray()); return ''; }, 'graphviz': (lns, tmpDir) => { var viz = $ARR(lns).join('\n'); var vizB64 = Bytes.from(viz).asBase64(); var dgst = Bytes.from(viz).digest($$.digests().sha256()).asHex(); var vizToPngRes = $$.shell().commands('sh', '-c', 'echo ' + vizB64 + ' | base64 -D | dot -Tpng').start(); $$.rFile(tmpDir, dgst + '.png').write(vizToPngRes[0].bytes()); return ''; } }; // return null or string var dealWithMarkdown = (f, tmpDir, mdList, plugins) => { var list = []; var codeTag = null; var codeList = []; var inCode = false; $ARR(mdList).forEach((ln) => { if (inCode) { if ($STR(ln.trim()) == '```') { // CODE ENDED inCode = false; var plugInFunc = null; plugins.forEach((p) => { if (plugInFunc == null) { plugInFunc = p[codeTag || 'default']; } }); if (plugInFunc == null) { // plugin not found list.push('```' + codeTag); codeList.forEach((ln) => { list.push(ln) } ); list.push('```'); } else { list.push(plugInFunc(codeList, tmpDir)); } } else { codeList.push(ln); } } else if (ln.trim().startsWith('```')) { // CODE STARTED inCode = true; codeList = []; codeTag = ln.trim().substring(3).trim(); } else { list.push(ln); } }); if (inCode) { xprintln('[ERROR] Markdown content error: ' + f); return null; } return list.join('\n'); }; // gitbook-cli OR https://github.com/GitbookIO/gitbook-pdf ? var main = () => { var args = argsjs.parseDefARGs(['default-processor', 'skip-delete-tmp']); if (args.length < 1) { xprintln('[ERROR] Need arguments.'); xprintln(); xprintln('gitbook.js [args] '); xprintln(' --default-processor enable default processor'); xprintln(' --skip-delete-tmp skip delete tmp dir'); xprintln(' -p, --processor with file processor'); xprintln(' -t, --type <"pdf"> default pdf'); xprintln(' -d, --dir default "."'); return; } var whichRes = $$.shell().commands('which', NPM).start(); if ($STR(whichRes[0].toString().trim()) == '') { xprintln('[ERROR] Node is not installed.'); xprintln('[INFO] Install node URL: ' + NODE_INSTALL_URL); return; } xprintln('[OK] Check node installed: ' + $$.shell().commands('node', '-v').start()[0].toString().trim()); var gitbookRes = $$.shell().commands('which', GITBOOK).start(); if ($STR(gitbookRes[0].toString().trim()) == '') { xprintln('[ERROR] Gitbook is not installed.'); xprintln('[INFO] Install gitbook command: ' + GITBOOK_INSTALL); return; } xprintln('[OK] Check gitbook installed: ' + $$.shell().commands('gitbook', '-V').start()[0].toString().trim().replace('\n', '; ')); var dotRes = $$.shell().commands('which', DOT).start(); if ($STR(dotRes[0].toString().trim()) == '') { xprintln('[ERROR] Graphviz is not installed.'); xprintln('[INFO] Install graphviz command: ' + DOT_INSTALL); return; } xprintln('[OK] Check graphviz installed: ' + $$.shell().commands('dot', '-V').mergeErrorOutput(true).start()[0].toString().trim().replace('\n', '; ')); var ebookConvert = $$.file(CALIBRE_HOME, CALIBRE_EBOOK_CONVERT); if (!(ebookConvert.exists())) { xprintln('[ERROR] Calibre is not installed.'); xprintln('[INFO] Install calibre URL: ' + CALIBRE_INSTALL_URL); return; } xprintln('[OK] Check calibre installed: ' + $$.shell().commands(ebookConvert.getAbsolutePath(), '--version').start()[0].list().get(0)); var gitbookShell = $$.shell(); var ebookConvertRes = $$.shell().commands('which', CALIBRE_EBOOK_CONVERT).start(); if ($STR(ebookConvertRes[0].toString().trim()) == '') { xprintln('[INFO] $PATH add calibre home: ' + CALIBRE_HOME); gitbookShell.env('PATH', '$PATH:' + CALIBRE_HOME); } var _type = args.val('t', 'type') || 'pdf'; var _dir = args.val('d', 'dir') || '.'; if ($STR(_type) != 'pdf') { xprintln('[ERROR] Currently only supports pdf.'); return; } var _tempDir = $$.file(_dir, '.tmp'); var plugins = []; var processors = args.vals('p', 'processor'); processors.forEach((p) => { xprintln('[INFO] Load processor: ' + p); plugins.push(require('file://' + p)); }); if (args.flg('default-processor')) { plugins.push(DEFAULT_PROCESSOR); } if (plugins.length > 0) { if (_tempDir.exists()) { xprintln('[INFO] Delete exists tmp dir: ' + _tempDir); FileUtil.deleteDirectory(_tempDir); } xprintln('[INFO] Create tmp dir: ' + _tempDir); _tempDir.mkdirs(); $ARR($$.file(_dir).listFiles()).forEach((f) => { if (f.getName().toLowerCase().endsWith('.md')) { var contents = $$.rFile(f).list(); var newContents = dealWithMarkdown(f, _tempDir, contents, plugins); if (newContents != null) { xprintln('[INFO] Update md file: ' + f.getName()); $$.rFile(_tempDir, f.getName()).write(newContents); } else { $$.rFile(_tempDir, f.getName()).write(contents.join('\n')); } } }); } var commands = []; commands.push(GITBOOK); commands.push(_type); commands.push((plugins.length > 0) ? _tempDir : _dir); commands.push(args[0]); xprintln('[INFO] Run gitbook command: ' + $TO_JAVA_LIST(commands)); gitbookShell.commands(commands).run(); if (_tempDir.exists()) { if (!(args.flg('skip-delete-tmp'))) { xprintln('[INFO] Delete tmp dir: ' + _tempDir); FileUtil.deleteDirectory(_tempDir); } } }; main();