UNPKG

markdawn

Version:

(multi)markdown for paged documents. Outputs to pdf

220 lines 9.41 kB
"use strict"; var __assign = (this && this.__assign) || Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [0, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var fs = require("fs"); var hljs = require("highlight.js"); var toc = require("markdown-toc"); var os = require("os"); var path = require("path"); var puppeteer = require("puppeteer"); var Remarkable = require("remarkable"); var config_1 = require("./config"); var utils = require("./utils"); var md = new Remarkable('full', { linkify: true, typographer: true, html: true, quotes: '“”‘’', _strict: false, highlight: function (str, lang) { function logErr() { console.warn("highlighting failed for the following snippet " + str); } if (lang && hljs.getLanguage(lang)) { try { return hljs.highlight(lang, str).value; } catch (err) { logErr(); } } try { return hljs.highlightAuto(str).value; } catch (err) { logErr(); } return ''; // use external default escaping }, }); function generateIndex(index) { var indexText = fs.readFileSync(index, 'utf8'); return "<!DOCTYPE html>\n" + indexText; } // parse the multimarkdown-style metadata function parseMetadata(text) { var lines = text.split('\n'); var metadata = {}; var count = 0; for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) { var line = lines_1[_i]; if (!line || line.indexOf(':') === -1) { break; } ++count; var index = line.indexOf(':'); var key = line.substr(0, index); var val = line.substr(index + 1); metadata[key] = val; } return { count: count, metadata: metadata, }; } function stripMetadata(text, count) { var lines = text.split('\n'); lines.splice(0, count); return lines.join('\n'); } function addToc(text, html) { var tocObj = { TOC: md.render(toc(text).content), }; return utils.interpolate(html, tocObj); } /** * make the `href` and `src` attributes in an html text point to the provided folder */ function absolutePaths(html, indexPath) { html = utils.rebaseAttribute(html, indexPath, 'href'); html = utils.rebaseAttribute(html, indexPath, 'src'); return html; } /** * generate the pdf document with the following input * @param text the markdwon text to insert in the docuement * @param opts object containing configuration keys for generating the pdf * - index: path to the index.html file that defines a theme * - format: (e.g. "Letter", "A4") overrides the format specified in the theme * - out: name of output file * - theme: name of a preconfigured theme to use (it has priority over the `index` property) * - contentDir: content directory to take the content source from * @return the html that generates the pdf, useful for debugging purposes */ function generate(text, opts) { return __awaiter(this, void 0, void 0, function () { var out, index, indexPath, html, _a, count, metadata, markdown, pdfOptions, filePath, browser, page; return __generator(this, function (_b) { switch (_b.label) { case 0: // sanitize input opts = opts || {}; if (!text) { console.warn('the input text is empty'); } out = opts.out || 'out.pdf'; opts.contentDir = opts.contentDir || './'; index = opts.index; if (opts.theme) { // select the theme index = path.resolve(config_1.default.themePath, opts.theme, 'index.html'); } // validate that the index file exists if (!index || !fs.existsSync(index)) { console.warn("Warning: the index file provided (" + index + ") doesn't exist." + " Markdawn will use the default theme"); index = config_1.default.defaultTheme; } indexPath = path.dirname(path.resolve(index)); html = generateIndex(index); _a = parseMetadata(text), count = _a.count, metadata = _a.metadata; text = stripMetadata(text, count); html = utils.interpolate(html, metadata); // add TOC html = addToc(text, html); html = absolutePaths(html, indexPath); markdown = md.render(text); markdown = absolutePaths(markdown, opts.contentDir); // insert markdown into index html html = utils.interpolate(html, { content: markdown, }); pdfOptions = {}; try { pdfOptions = require(path.resolve(indexPath, 'page.json')); } catch (e) { console.warn("Warning: missing file page.json in the index folder (" + index + ")." + " Using default page settings"); } if (opts.format) { // overwrite the format pdfOptions.format = opts.format; } do { filePath = path.join(os.tmpdir(), "markdawn-tmp-" + Math.random() + ".html"); } while (fs.existsSync(filePath)); fs.writeFileSync(filePath, html); return [4 /*yield*/, puppeteer.launch()]; case 1: browser = _b.sent(); return [4 /*yield*/, browser.newPage()]; case 2: page = _b.sent(); return [4 /*yield*/, page.goto("file://" + filePath)]; case 3: _b.sent(); return [4 /*yield*/, page.pdf(__assign({}, pdfOptions, { path: out }))]; case 4: _b.sent(); return [4 /*yield*/, browser.close()]; case 5: _b.sent(); return [2 /*return*/, html]; } }); }); } exports.generate = generate; /** * get the list of preconfigured thems that can be used * @return a list of strings, each string representing a name of a theme */ function getThemes() { return fs.readdirSync(config_1.default.themePath).filter(function (f) { return f[0] !== '_'; }); } exports.getThemes = getThemes; //# sourceMappingURL=core.js.map