More utility stuff

- added book config to extend from
- added metadata to mdconfig 
- added mapping of metadata to global variables
- added global variable wordcount
- added better error handling of puppeteer errors
- added style to utility classes and tables
develop
Trivernis 5 years ago
parent f6e33cfff5
commit 2bce9acbfa

@ -16,4 +16,6 @@
- support for `mdconf.json`config file
- MathJax script to html
- `mdconfig.json` extensions with `extends: "name"`
- `mdconfig.json` metadata under `meta` that is available as global variables
- variables prefixed with `$` and system variables prefixed with `$$`
- default config `book`

@ -76,7 +76,7 @@ You can include your own stylesheet. It is applied after the default style. The
## Variables
Variables are prefixed with `$`.
Variables are prefixed with `$`. They are case sensitive.
You can define and use variables like this:
Defining:
@ -93,12 +93,47 @@ I'm eating an $fruit.
There are system variables that are prefixed with `$$`.
Currently you can use
variable | value | example value
---------|-----------------|--------------
$now | current datetime| 31.07.2019 21:03:47
$date | current date | 31.07.2019
$time | current time | 21:03:47
variable | value | example value
------------|--------------------------|--------------
$$now | current datetime | 31.07.2019 21:03:47
$$date | current date | 31.07.2019
$$time | current time | 21:03:47
$$wordcount | words in the document | 200
All keys defined in the meta part of the `mdconfig.json` are also made
available as system variables as long as they don't overide existing variables.
## Environments
These environments need the `div` plugin to work.
```
:::multiline
One linebreak in here
Is one linebreak in the document.
:::
:::centered
Text is centered in here.
:::
:::page
This is rendered on one or more extra pages.
:::
:::tabular
| |
--------------|-----------------|----------
only the body | of the table is | displayed
and without | borders |
:::
:::title
Title page environment
All text is bigger
and is kept on one page (if possible).
:::
```
## Configuration file
@ -115,7 +150,13 @@ You can also define plugins, stylesheets and other stuff by using a `mdconf.json
],
"stylesheets": [
"customstyle.css"
]
],
"meta": { // all values defined here are also global variables
"author": "John Doe",
"title": "Markdown is great",
"subtitle": "Or is it?",
"hey": "Vsauce, Michael here!"
}
}
```

@ -0,0 +1,23 @@
{
"plugins": [
"footnote",
"anchor",
"mark",
"sub",
"attrs",
"abbr",
"imsize",
"highlightjs",
"smartarrows",
"math",
"div",
"multimd-table",
"toc-done-right",
"center-text",
"header-sections",
"task-checkbox",
"underline",
"implicit-figures",
"inline-comments"
]
}

@ -81,8 +81,13 @@ async function main() {
} else if (args.pdf) {
let outputFile = noExt(args.file) + '.pdf';
await renderer.renderPdf(args.file, outputFile);
console.log(`File stored as ${outputFile}`);
try {
await renderer.renderPdf(args.file, outputFile);
console.log(`File stored as ${outputFile}`);
} catch (err) {
logger.error(err);
console.error('Failed to render pdf.');
}
} else {

@ -2,6 +2,7 @@ import * as fsx from 'fs-extra';
import * as path from 'path';
import {getMarkdownPlugin} from "./utils";
import {logger} from "./logger";
import {addGlobalVar, globalVariables} from "./globvars";
const confName = 'mdconfig.json';
const confDir = `${__dirname}../../configs`;
@ -10,7 +11,8 @@ const confDir = `${__dirname}../../configs`;
* Configs that can be extended
*/
const configs: any = {
"full": `${confDir}/full-${confName}`
"full": `${confDir}/full-${confName}`,
"book": `${confDir}/book-${confName}`
};
/**
@ -53,6 +55,17 @@ export class MarkdownConfig {
this.plugins = new Set<string>(configData.plugins.map(getMarkdownPlugin));
if (configData.stylesheets)
this.stylesheets = new Set<string>(configData.stylesheets);
if (configData.meta) {
let meta: any = configData.meta;
// adding metadata as global variables
let definedGlobals = Object.keys(globalVariables);
for (let [key, value] of Object.entries(meta)) {
if (!definedGlobals.includes(key)) {
// @ts-ignore
addGlobalVar(key, value);
}
}
}
}
/**

@ -6,7 +6,7 @@ import {pageFormats} from "./formats";
import {PDFFormat} from "puppeteer";
import {getMarkdownPlugin} from "./utils";
import {logger} from "./logger";
import {globalVariables} from "./globvars";
import {addGlobalVar, globalVariables} from "./globvars";
export class PreFormatter {
public projectFiles: string[];
@ -20,7 +20,7 @@ export class PreFormatter {
this.projectFiles = [];
this.resolvePath = [];
this.stylesheets = [];
this.variables = Object.assign({}, globalVariables);
this.variables = {};
}
async processCommands(doc: string, docpath: string, renderer: Renderer) {
@ -99,6 +99,11 @@ export class PreFormatter {
}
let documentContent = outputLines.join('\n');
addGlobalVar('wordcount', () => {
let doc = documentContent.replace(/\[.*]/g, '').replace(/\s+/, ' ');
return doc.split(' ').length;
});
Object.assign(this.variables, globalVariables); // assign globals right before replacing
// replacing all variables with their values.
for (let [key, value] of Object.entries(this.variables)) {
let varReplacer: RegExp = new RegExp(`\\$${key}`, "gi");

@ -8,7 +8,7 @@ import {PreFormatter} from "./PreFormatter";
import {EventEmitter} from "events";
import {PDFFormat} from "puppeteer";
import {MarkdownConfig} from "./MarkdownConfig";
import {bundleImages, delay, includeMathJax} from "./utils";
import {bundleImages, delay, includeMathJax, replaceMultilineBreaks} from "./utils";
import {logger} from "./logger";
export class Renderer extends EventEmitter {
@ -191,6 +191,7 @@ export class Renderer extends EventEmitter {
return dom;
});
this.useAfter(includeMathJax);
this.useAfter(replaceMultilineBreaks);
// include all images as base64
if (this.config.bundle)
this.useAfter(bundleImages);

@ -4,7 +4,21 @@ const dateTimeFormat = "dd.MM.yyyy hh:mm:ss";
const dateFormat = "dd.MM.yyyy";
const timeFormat = "hh:mm:ss";
/**
* Adds a global variable
* @param name - name of the variable
* @param value - value of the variable
*/
export function addGlobalVar(name: string, value: string|Function) {
name = name.replace(/\W/g, ''); // only allow word characters because it is interpreted as regex
globalVariables[`\\$${name}`] = value;
}
/**
* All global variables that can be used in the document.
*/
export const globalVariables: any = {
"\\$wordcount": 0, // will be replaced in PreFormatter
"\\$now"() {
return format(dateTimeFormat, new Date());
},

@ -53,6 +53,18 @@ export function includeMathJax(dom: JSDOM): JSDOM {
return dom;
}
/**
* Replaces all linebreaks with <br> tags in a .multiline div (:::multiline:::)
* @param dom
*/
export function replaceMultilineBreaks(dom: JSDOM): JSDOM {
let document = dom.window.document;
let multis = document.querySelectorAll('.multiline p');
for (let multi of multis)
multi.innerHTML = multi.innerHTML.replace(/\n/g, '<br>');
return dom;
}
/**
* Returns the markdown plugin associated with the pluginName
* The plugin is first searched in the plugins definition.

@ -36,6 +36,15 @@ figcaption
margin: 0.5em
font-style: italic
table
border-collapse: collapse
td, th
padding: 0.2em
th
border-bottom: 2px solid $primary
td
border-bottom: 1px solid $inactive
.footnote-backref
display: none
@ -44,8 +53,31 @@ figcaption
page-break-after: always
page-break-inside: avoid
.page.title
page-break-before: avoid
.newpage
page-break-after: always
.text-align-center
text-align: center
.centered
text-align: center
table
margin: auto
.tabular
thead
display: none
td
border: none
.title
font-size: x-large
h1
font-size: 1.8em
h2
font-size: 1.3em
table
font-size: x-large

@ -1,2 +1,3 @@
$backgroundSecondary: #eee
$inactive: #444
$primary: #000

Loading…
Cancel
Save