Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ packages/core/test/unit/html/includePanelProcessor.test.js
packages/core/test/unit/html/SiteLinkManager.test.js
packages/core/test/unit/utils/utils.js
packages/core/test/unit/utils/data.js
packages/core/src/plugins/default/markbind-plugin-anchors.js
packages/core/src/plugins/default/markbind-plugin-plantuml.js
packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.js
packages/core/src/plugins/default/markbind-plugin-tree.js

# Rules for pure JS files
packages/core/src/lib/markdown-it/patches/*
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,9 @@ packages/core/test/unit/html/includePanelProcessor.test.js
packages/core/test/unit/html/SiteLinkManager.test.js
packages/core/test/unit/utils/utils.js
packages/core/test/unit/utils/data.js
packages/core/src/plugins/default/markbind-plugin-anchors.js
packages/core/src/plugins/default/markbind-plugin-plantuml.js
packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.js
packages/core/src/plugins/default/markbind-plugin-tree.js

# --- packages/core end ---
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"devDependencies": {
"@types/bluebird": "^3.5.36",
"@types/cheerio": "^0.22.31",
"@types/crypto-js": "^4.1.1",
Comment thread
tlylt marked this conversation as resolved.
"@types/domhandler": "^2.4.2",
"@types/fs-extra": "^9.0.13",
"@types/htmlparser2": "^3.10.3",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const cheerio = module.parent.require('cheerio');
import cheerio from 'cheerio';
import { MbNode } from '../../utils/node';
import { PluginContext } from '../Plugin';

const CSS_FILE_NAME = 'markbind-plugin-anchors.css';

Expand All @@ -7,9 +9,9 @@ const HEADER_REGEX = /^h[1-6]$/;
/**
* Adds anchor links to headers
*/
module.exports = {
export = {
getLinks: () => [`<link rel="stylesheet" href="${CSS_FILE_NAME}">`],
postProcessNode: (pluginContext, node) => {
postProcessNode: (_pluginContext: PluginContext, node: MbNode) => {
if (HEADER_REGEX.test(node.name) && node.attribs.id) {
cheerio(node).append(
`<a class="fa fa-anchor" href="#${node.attribs.id}" onclick="event.stopPropagation()"></a>`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
* Replaces <puml> tags with <pic> tags with the appropriate src attribute and generates the diagrams
* by running the JAR executable
*/
const cheerio = module.parent.require('cheerio');
const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const cryptoJS = require('crypto-js');

const fsUtil = require('../../utils/fsUtil');
const logger = require('../../utils/logger');
const urlUtil = require('../../utils/urlUtil');
import cheerio from 'cheerio';
import fs from 'fs';
import path from 'path';
import { exec } from 'child_process';
import cryptoJS from 'crypto-js';

import * as fsUtil from '../../utils/fsUtil';
import * as logger from '../../utils/logger';
import * as urlUtil from '../../utils/urlUtil';
import { PluginContext } from '../Plugin';
import { NodeProcessorConfig } from '../../html/NodeProcessor';
import { MbNode } from '../../utils/node';

const JAR_PATH = path.resolve(__dirname, 'plantuml.jar');

Expand All @@ -24,7 +27,7 @@ let graphvizCheckCompleted = false;
* @param imageOutputPath output path of the diagram to be generated
* @param content puml dsl used to generate the puml diagram
*/
function generateDiagram(imageOutputPath, content) {
function generateDiagram(imageOutputPath: string, content: string) {
// Avoid generating twice
if (processedDiagrams.has(imageOutputPath)) { return; }
processedDiagrams.add(imageOutputPath);
Expand All @@ -40,23 +43,23 @@ function generateDiagram(imageOutputPath, content) {
const childProcess = exec(cmd);

let errorLog = '';
childProcess.stdin.write(
childProcess.stdin?.write(
content,
(e) => {
if (e) {
logger.debug(e);
logger.debug(e as unknown as string);
logger.error(`Error generating ${imageOutputPath}`);
}
childProcess.stdin.end();
childProcess.stdin?.end();
},
);

childProcess.on('error', (error) => {
logger.debug(error);
logger.debug(error as unknown as string);
logger.error(`Error generating ${imageOutputPath}`);
});

childProcess.stderr.on('data', (errorMsg) => {
childProcess.stderr?.on('data', (errorMsg) => {
errorLog += errorMsg;
});

Expand All @@ -66,7 +69,7 @@ function generateDiagram(imageOutputPath, content) {
});
}

module.exports = {
export = {
tagConfig: {
puml: {
isSpecial: true,
Expand All @@ -89,12 +92,12 @@ module.exports = {
graphvizCheckCompleted = false;
},

processNode: (pluginContext, node, config) => {
processNode: (_pluginContext: PluginContext, node: MbNode, config: NodeProcessorConfig) => {
if (node.name !== 'puml') {
return;
}
if (config.plantumlCheck && !graphvizCheckCompleted) {
exec(`java -jar "${JAR_PATH}" -testdot`, (error, stdout, stderr) => {
exec(`java -jar "${JAR_PATH}" -testdot`, (_error, _stdout, stderr) => {
if (stderr.includes('Error: No dot executable found')) {
logger.warn('You are using PlantUML diagrams but Graphviz is not installed!');
}
Expand All @@ -116,7 +119,7 @@ module.exports = {
try {
pumlContent = fs.readFileSync(rawPath, 'utf8');
} catch (err) {
logger.debug(err);
logger.debug(err as string);
logger.error(`Error reading ${rawPath} for <puml> tag`);
return;
}
Expand All @@ -143,7 +146,7 @@ module.exports = {
node.attribs.src = `${config.baseUrl}/${pathFromRootToImage}`;
}

delete node.children;
node.children = [];

const imageOutputPath = path.resolve(config.outputPath, pathFromRootToImage);
generateDiagram(imageOutputPath, pumlContent);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { MbNode } from '../../utils/node';
import { PluginContext } from '../Plugin';

/**
* Converts shorthand syntax to proper MarkBind syntax
* @param content of the page
*/
module.exports = {
processNode: (pluginContext, node) => {
export = {
processNode: (_pluginContext: PluginContext, node: MbNode) => {
// panel>span[heading]
if (node.name === 'span'
&& node.attribs
&& node.attribs.heading !== undefined
&& node.parent
&& node.parent.name === 'panel') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
* that are easier to visualise the relationships.
* A common use case is folder structures visualisations.
*/
const _ = {};
_.has = require('lodash/has');
import has from 'lodash/has';
import { MbNode } from '../../utils/node';
import { PluginContext } from '../Plugin';

const _ = { has };

const md = require('../../lib/markdown-it');

const CSS_FILE_NAME = 'markbind-plugin-tree.css';
Expand All @@ -18,7 +22,12 @@ const TOKEN = {
};

class TreeNode {
constructor(content, parent, children, level) {
content: string;
parent: TreeNode | null;
children: TreeNode[];
level: number;

constructor(content: string, parent: TreeNode | null, children: TreeNode[], level: number) {
this.content = content;
this.parent = parent;
this.children = children;
Expand All @@ -29,9 +38,8 @@ class TreeNode {
* Returns true if this node is the last child of its parent.
* A root node is considered to be the last child.
* This is used to determine the correct connector to use.
* @return {boolean}
*/
isLastChild() {
isLastChild(): boolean {
if (this.parent === null) {
return true;
}
Expand All @@ -40,37 +48,35 @@ class TreeNode {

/**
* Returns the token to append before the content.
* @return {string}
*/
getPositionalToken() {
getPositionalToken(): string {
return this.isLastChild() ? TOKEN.lastChild : TOKEN.child;
}

/**
* Determines the level of a line.
* Every 2 spaces from the start of the line means 1 level.
* The root node is level 0.
* @return {number}
*/
static levelize(line) {
return Math.floor(line.match(/^\s*/)[0].length / 2);
static levelize(line: string): number {
const lineMatch = line.match(/^\s*/) ?? [''];
return Math.floor(lineMatch[0].length / 2);
}

/**
* Returns formatted TreeNode content.
* Removes dashes (-), asterisks (*), or plus signs (+) at the beginning of the line
* @return {string}
*/
static getContent(raw) {
static getContent(raw: string): string {
return raw.trim().replace(/^[-+*]\s/, '');
}

/**
* Creates TreeNode objects from the raw text.
* @param {string} raw - The raw text to parse.
* @return {TreeNode} - The dummy root node of the tree.
* @param raw - The raw text to parse.
* @return The dummy root node of the tree.
*/
static parse(raw) {
static parse(raw: string): TreeNode {
const lines = raw.split('\n').filter(line => line.trim() !== '');
const rootNode = new TreeNode('.', null, [], -1); // dummy root node
const prevParentStack = [rootNode];
Expand Down Expand Up @@ -102,10 +108,10 @@ class TreeNode {

/**
* Traverses the tree and appends the tokens to the given array.
* @param {TreeNode} node - The node to traverse.
* @param {Array} treeTokens - The array to append the tokens to.
* @param currNode - The node to traverse.
* @param result - The array to append the tokens to.
*/
static traverse(currNode, result) {
static traverse(currNode: TreeNode, result: string[]) {
if (!currNode.children) {
return;
}
Expand All @@ -119,36 +125,34 @@ class TreeNode {
];

// computes the strings appended to the content of the TreeNode
let curr = currNode.parent;
while (_.has(curr, 'parent.parent')) {
let curr: TreeNode | null = currNode.parent;
while (curr && _.has(curr, 'parent.parent')) {
tokens.push(curr.isLastChild() ? TOKEN.space : TOKEN.connector);
curr = curr.parent;
}

result.push(tokens.reverse().join(''));
}
currNode.children.forEach((child) => {
currNode.children.forEach((child: TreeNode) => {
TreeNode.traverse(child, result);
});
}

/**
* Returns the TreeNode as a string.
* This assumes that the node is a root node.
* @return {string}
*/
toString() {
const treeTokens = [];
toString(): string {
const treeTokens: string[] = [];
TreeNode.traverse(this, treeTokens);
return treeTokens.join('');
}

/**
* Returns the rendered tree.
* @param {string} raw - The raw text to parse.
* @return {string}
* @param raw - The raw text to parse.
*/
static visualize(raw) {
static visualize(raw: string): string {
const dummyRootNode = TreeNode.parse(raw);
return dummyRootNode.children
.reduce((prev, curr) => {
Expand All @@ -158,19 +162,20 @@ class TreeNode {
}
}

module.exports = {
export = {
tagConfig: {
tree: {
isSpecial: true,
},
},
getLinks: () => [`<link rel="stylesheet" href="${CSS_FILE_NAME}">`],
processNode: (pluginContext, node) => {
processNode: (_pluginContext: PluginContext, node: MbNode) => {
if (node.name !== 'tree') {
return;
}
node.name = 'div';
node.attribs.class = node.attribs.class ? `${node.attribs.class} tree` : 'tree';
node.children = node.children ?? [];
node.children[0].data = TreeNode.visualize(node.children[0].data);
},
};