From d1802406ad7e2bedb7b9fb4cd261fb544a63902c Mon Sep 17 00:00:00 2001 From: Jovyn Tan Date: Wed, 8 Mar 2023 18:52:30 +0800 Subject: [PATCH 1/2] Rename default plugins to TypeScript --- .eslintignore | 4 ++++ .gitignore | 4 ++++ ...{markbind-plugin-anchors.js => markbind-plugin-anchors.ts} | 0 ...arkbind-plugin-plantuml.js => markbind-plugin-plantuml.ts} | 0 ...-shorthandSyntax.js => markbind-plugin-shorthandSyntax.ts} | 0 .../{markbind-plugin-tree.js => markbind-plugin-tree.ts} | 0 6 files changed, 8 insertions(+) rename packages/core/src/plugins/default/{markbind-plugin-anchors.js => markbind-plugin-anchors.ts} (100%) rename packages/core/src/plugins/default/{markbind-plugin-plantuml.js => markbind-plugin-plantuml.ts} (100%) rename packages/core/src/plugins/default/{markbind-plugin-shorthandSyntax.js => markbind-plugin-shorthandSyntax.ts} (100%) rename packages/core/src/plugins/default/{markbind-plugin-tree.js => markbind-plugin-tree.ts} (100%) diff --git a/.eslintignore b/.eslintignore index d4cc03e62f..d9dce030ca 100644 --- a/.eslintignore +++ b/.eslintignore @@ -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/* diff --git a/.gitignore b/.gitignore index 2665c7bb68..0ab061fa52 100644 --- a/.gitignore +++ b/.gitignore @@ -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 --- diff --git a/packages/core/src/plugins/default/markbind-plugin-anchors.js b/packages/core/src/plugins/default/markbind-plugin-anchors.ts similarity index 100% rename from packages/core/src/plugins/default/markbind-plugin-anchors.js rename to packages/core/src/plugins/default/markbind-plugin-anchors.ts diff --git a/packages/core/src/plugins/default/markbind-plugin-plantuml.js b/packages/core/src/plugins/default/markbind-plugin-plantuml.ts similarity index 100% rename from packages/core/src/plugins/default/markbind-plugin-plantuml.js rename to packages/core/src/plugins/default/markbind-plugin-plantuml.ts diff --git a/packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.js b/packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.ts similarity index 100% rename from packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.js rename to packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.ts diff --git a/packages/core/src/plugins/default/markbind-plugin-tree.js b/packages/core/src/plugins/default/markbind-plugin-tree.ts similarity index 100% rename from packages/core/src/plugins/default/markbind-plugin-tree.js rename to packages/core/src/plugins/default/markbind-plugin-tree.ts From 4bfa855db2b295cfcfa67d531800bf3dc10c1441 Mon Sep 17 00:00:00 2001 From: Jovyn Tan Date: Wed, 8 Mar 2023 18:52:53 +0800 Subject: [PATCH 2/2] Adapt default plugins to TypeScript --- package-lock.json | 11 ++++ packages/core/package.json | 1 + .../default/markbind-plugin-anchors.ts | 8 ++- .../default/markbind-plugin-plantuml.ts | 43 +++++++------ .../markbind-plugin-shorthandSyntax.ts | 8 ++- .../plugins/default/markbind-plugin-tree.ts | 63 ++++++++++--------- 6 files changed, 79 insertions(+), 55 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3251c43cd3..c035610bfa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@tlylt/markdown-it-imsize": "^3.0.0", "@types/bluebird": "^3.5.36", "@types/cheerio": "^0.22.31", + "@types/crypto-js": "^4.1.1", "@types/domhandler": "^2.4.2", "@types/fs-extra": "^9.0.13", "@types/htmlparser2": "^3.10.3", @@ -3962,6 +3963,11 @@ "@types/node": "*" } }, + "node_modules/@types/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" + }, "node_modules/@types/domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@types/domhandler/-/domhandler-2.4.2.tgz", @@ -25076,6 +25082,11 @@ "@types/node": "*" } }, + "@types/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" + }, "@types/domhandler": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@types/domhandler/-/domhandler-2.4.2.tgz", diff --git a/packages/core/package.json b/packages/core/package.json index f2fede9e04..dfa532b324 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -76,6 +76,7 @@ "devDependencies": { "@types/bluebird": "^3.5.36", "@types/cheerio": "^0.22.31", + "@types/crypto-js": "^4.1.1", "@types/domhandler": "^2.4.2", "@types/fs-extra": "^9.0.13", "@types/htmlparser2": "^3.10.3", diff --git a/packages/core/src/plugins/default/markbind-plugin-anchors.ts b/packages/core/src/plugins/default/markbind-plugin-anchors.ts index f20cb5d969..3aae3a6c52 100644 --- a/packages/core/src/plugins/default/markbind-plugin-anchors.ts +++ b/packages/core/src/plugins/default/markbind-plugin-anchors.ts @@ -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'; @@ -7,9 +9,9 @@ const HEADER_REGEX = /^h[1-6]$/; /** * Adds anchor links to headers */ -module.exports = { +export = { getLinks: () => [``], - postProcessNode: (pluginContext, node) => { + postProcessNode: (_pluginContext: PluginContext, node: MbNode) => { if (HEADER_REGEX.test(node.name) && node.attribs.id) { cheerio(node).append( ``); diff --git a/packages/core/src/plugins/default/markbind-plugin-plantuml.ts b/packages/core/src/plugins/default/markbind-plugin-plantuml.ts index c08949c2de..85c12ef615 100644 --- a/packages/core/src/plugins/default/markbind-plugin-plantuml.ts +++ b/packages/core/src/plugins/default/markbind-plugin-plantuml.ts @@ -3,15 +3,18 @@ * Replaces tags with 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'); @@ -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); @@ -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; }); @@ -66,7 +69,7 @@ function generateDiagram(imageOutputPath, content) { }); } -module.exports = { +export = { tagConfig: { puml: { isSpecial: true, @@ -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!'); } @@ -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 tag`); return; } @@ -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); diff --git a/packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.ts b/packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.ts index 08b8746f45..6f9d794ffd 100644 --- a/packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.ts +++ b/packages/core/src/plugins/default/markbind-plugin-shorthandSyntax.ts @@ -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') { diff --git a/packages/core/src/plugins/default/markbind-plugin-tree.ts b/packages/core/src/plugins/default/markbind-plugin-tree.ts index b22c7f2858..737ddc6e44 100644 --- a/packages/core/src/plugins/default/markbind-plugin-tree.ts +++ b/packages/core/src/plugins/default/markbind-plugin-tree.ts @@ -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'; @@ -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; @@ -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; } @@ -40,9 +48,8 @@ class TreeNode { /** * Returns the token to append before the content. - * @return {string} */ - getPositionalToken() { + getPositionalToken(): string { return this.isLastChild() ? TOKEN.lastChild : TOKEN.child; } @@ -50,27 +57,26 @@ class TreeNode { * 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]; @@ -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; } @@ -119,15 +125,15 @@ 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); }); } @@ -135,20 +141,18 @@ class TreeNode { /** * 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) => { @@ -158,19 +162,20 @@ class TreeNode { } } -module.exports = { +export = { tagConfig: { tree: { isSpecial: true, }, }, getLinks: () => [``], - 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); }, };