Variables

- added variables `$varname` and system variables `$$varname`
- renamed CommandParser to preformatter because it also handles variables and stuff
- added global variable definition
develop
Trivernis 5 years ago
parent ee316c6c24
commit 2826341e4e

@ -16,3 +16,4 @@
- support for `mdconf.json`config file - support for `mdconf.json`config file
- MathJax script to html - MathJax script to html
- `mdconfig.json` extensions with `extends: "name"` - `mdconfig.json` extensions with `extends: "name"`
- variables prefixed with `$` and system variables prefixed with `$$`

@ -74,6 +74,32 @@ You can include your own stylesheet. It is applied after the default style. The
[!stylesheet]: path/to/style.css [!stylesheet]: path/to/style.css
``` ```
## Variables
Variables are prefixed with `$`.
You can define and use variables like this:
Defining:
```
$varname = value
$fruit = apple
```
Using:
```
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
## Configuration file ## Configuration file
You can also define plugins, stylesheets and other stuff by using a `mdconf.json` file in the same directory as the main markdown file. Example config: You can also define plugins, stylesheets and other stuff by using a `mdconf.json` file in the same directory as the main markdown file. Example config:

15
package-lock.json generated

@ -954,6 +954,11 @@
"whatwg-url": "^7.0.0" "whatwg-url": "^7.0.0"
} }
}, },
"date-format": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
"integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA=="
},
"debug": { "debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@ -3448,6 +3453,11 @@
"resolved": "https://registry.npmjs.org/markdown-it-imsize/-/markdown-it-imsize-2.0.1.tgz", "resolved": "https://registry.npmjs.org/markdown-it-imsize/-/markdown-it-imsize-2.0.1.tgz",
"integrity": "sha1-zKBCeQXQUziiR8ucqdloxc3dUXA=" "integrity": "sha1-zKBCeQXQUziiR8ucqdloxc3dUXA="
}, },
"markdown-it-inline-comments": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/markdown-it-inline-comments/-/markdown-it-inline-comments-1.0.1.tgz",
"integrity": "sha1-F26r5jGj4IElvXOVAPQ8UfUliW0="
},
"markdown-it-ins": { "markdown-it-ins": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-2.0.0.tgz", "resolved": "https://registry.npmjs.org/markdown-it-ins/-/markdown-it-ins-2.0.0.tgz",
@ -3476,6 +3486,11 @@
"resolved": "https://registry.npmjs.org/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz", "resolved": "https://registry.npmjs.org/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz",
"integrity": "sha1-ritPTFxxmgP55HXGZPeyaFIx2ek=" "integrity": "sha1-ritPTFxxmgP55HXGZPeyaFIx2ek="
}, },
"markdown-it-modify-token": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/markdown-it-modify-token/-/markdown-it-modify-token-1.0.2.tgz",
"integrity": "sha1-VCRxoyMnClwQKmNbB/47R8J47qA="
},
"markdown-it-multimd-table": { "markdown-it-multimd-table": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/markdown-it-multimd-table/-/markdown-it-multimd-table-3.2.2.tgz", "resolved": "https://registry.npmjs.org/markdown-it-multimd-table/-/markdown-it-multimd-table-3.2.2.tgz",

@ -30,6 +30,7 @@
"@types/puppeteer": "^1.19.0", "@types/puppeteer": "^1.19.0",
"argparse": "^1.0.10", "argparse": "^1.0.10",
"chokidar": "^3.0.2", "chokidar": "^3.0.2",
"date-format": "^2.1.0",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",
"jsdom": "^15.1.1", "jsdom": "^15.1.1",
"line-by-line": "^0.1.6", "line-by-line": "^0.1.6",
@ -46,11 +47,13 @@
"markdown-it-highlightjs": "^3.0.0", "markdown-it-highlightjs": "^3.0.0",
"markdown-it-implicit-figures": "^0.9.0", "markdown-it-implicit-figures": "^0.9.0",
"markdown-it-imsize": "^2.0.1", "markdown-it-imsize": "^2.0.1",
"markdown-it-inline-comments": "^1.0.1",
"markdown-it-ins": "^2.0.0", "markdown-it-ins": "^2.0.0",
"markdown-it-kbd": "^2.0.0", "markdown-it-kbd": "^2.0.0",
"markdown-it-mark": "^2.0.0", "markdown-it-mark": "^2.0.0",
"markdown-it-math": "^4.1.1", "markdown-it-math": "^4.1.1",
"markdown-it-mathjax": "^2.0.0", "markdown-it-mathjax": "^2.0.0",
"markdown-it-modify-token": "^1.0.2",
"markdown-it-multimd-table": "^3.2.2", "markdown-it-multimd-table": "^3.2.2",
"markdown-it-plantuml": "^1.4.1", "markdown-it-plantuml": "^1.4.1",
"markdown-it-smartarrows": "^1.0.1", "markdown-it-smartarrows": "^1.0.1",

@ -22,6 +22,7 @@
"header-sections", "header-sections",
"task-checkbox", "task-checkbox",
"underline", "underline",
"implicit-figures" "implicit-figures",
"inline-comments"
] ]
} }

@ -6,11 +6,13 @@ import {pageFormats} from "./formats";
import {PDFFormat} from "puppeteer"; import {PDFFormat} from "puppeteer";
import {getMarkdownPlugin} from "./utils"; import {getMarkdownPlugin} from "./utils";
import {logger} from "./logger"; import {logger} from "./logger";
import {globalVariables} from "./globvars";
export class CommandParser { export class PreFormatter {
public projectFiles: string[]; public projectFiles: string[];
public pageFormat: PDFFormat; public pageFormat: PDFFormat;
public stylesheets: string[]; public stylesheets: string[];
public variables: any;
private readonly resolvePath: {path: string, lines: number}[]; private readonly resolvePath: {path: string, lines: number}[];
@ -18,6 +20,7 @@ export class CommandParser {
this.projectFiles = []; this.projectFiles = [];
this.resolvePath = []; this.resolvePath = [];
this.stylesheets = []; this.stylesheets = [];
this.variables = Object.assign({}, globalVariables);
} }
async processCommands(doc: string, docpath: string, renderer: Renderer) { async processCommands(doc: string, docpath: string, renderer: Renderer) {
@ -44,25 +47,26 @@ export class CommandParser {
currentFile = this.resolvePath[this.resolvePath.length - 1]; currentFile = this.resolvePath[this.resolvePath.length - 1];
} }
} }
let match: RegExpExecArray = /\[ *!(\w+) *\]:? *(.*)/gu.exec(inputLine.replace(/\s/, '')); let commandMatch: RegExpExecArray = /\[ *!(\w+) *\]:? *(.*)/g.exec(inputLine);
let variableMatch: RegExpExecArray = /\$(\w+) *= *(.*?) *$/g.exec(inputLine);
if (match && match[0]) { // TODO: stylesheets if (commandMatch && commandMatch[0]) {
switch(match[1]) { switch(commandMatch[1]) {
case 'use': case 'use':
let plugins = match[2].split(','); let plugins = commandMatch[2].split(',');
logger.verbose(`Adding plugins: ${match[2]}`); logger.verbose(`Adding plugins: ${commandMatch[2]}`);
for (let mdPlugin of plugins) { for (let mdPlugin of plugins) {
renderer.addPlugin(getMarkdownPlugin(mdPlugin.replace(/^ *| *$/g, ''))); renderer.addPlugin(getMarkdownPlugin(mdPlugin.replace(/^ *| *$/g, '')));
} }
break; break;
case 'include': case 'include':
try { try {
if (!this.resolvePath.find(x => x.path === match[2])) { // if the include is in the path, it is a circular reference if (!this.resolvePath.find(x => x.path === commandMatch[2])) { // if the include is in the path, it is a circular reference
let included = await this.getInclude(match[2], mainDir); let included = await this.getInclude(commandMatch[2], mainDir);
inputLines.unshift(...included); inputLines.unshift(...included);
this.resolvePath.push({path: match[2], lines: included.length}); this.resolvePath.push({path: commandMatch[2], lines: included.length});
} else { } else {
logger.warning(`Circular reference detected. Skipping include ${match[2]}`); logger.warning(`Circular reference detected. Skipping include ${commandMatch[2]}`);
} }
} catch (err) { } catch (err) {
logger.error(err.message); logger.error(err.message);
@ -70,28 +74,40 @@ export class CommandParser {
} }
break; break;
case 'format': case 'format':
if (!this.pageFormat && Object.values(pageFormats).includes(match[2])) if (!this.pageFormat && Object.values(pageFormats).includes(commandMatch[2]))
// @ts-ignore // @ts-ignore
this.pageFormat = match[2]; this.pageFormat = commandMatch[2];
else else
logger.warning('Invalid page format or format already set: ' + match[2]); logger.warning('Invalid page format or format already set: ' + commandMatch[2]);
break; break;
case 'newpage': case 'newpage':
renderer.addPlugin(getMarkdownPlugin(markdownPlugins.div)); renderer.addPlugin(getMarkdownPlugin(markdownPlugins.div));
outputLines.push('::: .newpage \n:::'); outputLines.push('::: .newpage \n:::');
break; break;
case 'stylesheet': case 'stylesheet':
await this.addStylesheet(match[2], mainDir); await this.addStylesheet(commandMatch[2], mainDir);
break; break;
default: default:
outputLines.push(inputLine); outputLines.push(inputLine);
} }
} else if (variableMatch) {
this.variables[variableMatch[1]] = variableMatch[2];
logger.debug(`Added variable: "${variableMatch[1]}": "${variableMatch[2]}"`);
} else { } else {
outputLines.push(inputLine); outputLines.push(inputLine);
} }
} }
return outputLines.join('\n'); let documentContent = outputLines.join('\n');
// replacing all variables with their values.
for (let [key, value] of Object.entries(this.variables)) {
let varReplacer: RegExp = new RegExp(`\\$${key}`, "gi");
if (typeof value === "function")
value = await value();
// @ts-ignore
documentContent = documentContent.replace(varReplacer, value);
}
return documentContent;
} }
/** /**

@ -4,7 +4,7 @@ import * as path from 'path';
import * as chokidar from 'chokidar'; import * as chokidar from 'chokidar';
import * as puppeteer from 'puppeteer'; import * as puppeteer from 'puppeteer';
import {JSDOM} from 'jsdom'; import {JSDOM} from 'jsdom';
import {CommandParser} from "./CommandParser"; import {PreFormatter} from "./PreFormatter";
import {EventEmitter} from "events"; import {EventEmitter} from "events";
import {PDFFormat} from "puppeteer"; import {PDFFormat} from "puppeteer";
import {MarkdownConfig} from "./MarkdownConfig"; import {MarkdownConfig} from "./MarkdownConfig";
@ -15,7 +15,7 @@ export class Renderer extends EventEmitter {
private md: MarkdownIt; private md: MarkdownIt;
private readonly beforeRendering: Function[]; private readonly beforeRendering: Function[];
private readonly afterRendering: Function[]; private readonly afterRendering: Function[];
private commandParser: CommandParser; private commandParser: PreFormatter;
private config: MarkdownConfig; private config: MarkdownConfig;
constructor(config?: MarkdownConfig) { constructor(config?: MarkdownConfig) {
@ -24,7 +24,7 @@ export class Renderer extends EventEmitter {
this.md = new MarkdownIt(); this.md = new MarkdownIt();
this.beforeRendering = []; this.beforeRendering = [];
this.afterRendering = []; this.afterRendering = [];
this.commandParser = new CommandParser(); this.commandParser = new PreFormatter();
this.configure(); this.configure();
} }

@ -70,5 +70,8 @@ export const markdownPlugins: any = {
options: { options: {
figcaption: true figcaption: true
} }
},
'inline-comments': {
module: 'markdown-it-inline-comments'
} }
}; };

@ -36,6 +36,9 @@ figcaption
margin: 0.5em margin: 0.5em
font-style: italic font-style: italic
.footnote-backref
display: none
.page .page
page-break-before: always page-break-before: always
page-break-after: always page-break-after: always

Loading…
Cancel
Save