From 6f13ed6f46437fcc1b65f0ffdad1c54419af6522 Mon Sep 17 00:00:00 2001 From: Crphang Date: Sun, 8 Mar 2020 17:02:46 +0800 Subject: [PATCH] Add inline puml support --- docs/userGuide/puml.md | 35 ++++-- package-lock.json | 46 +++----- package.json | 1 + .../default/markbind-plugin-plantuml.js | 108 ++++++++---------- src/util/pluginUtil.js | 51 +++++++++ .../9c9e77fc0a983cb6b592e65733787bec.png | Bin 0 -> 6864 bytes test/functional/test_site/expected/index.html | 6 + .../test_site/expected/inline-output.png | Bin 0 -> 9392 bytes .../test_site/expected/testPlantUML.html | 6 + test/functional/test_site/testPlantUML.md | 36 ++++++ 10 files changed, 190 insertions(+), 99 deletions(-) create mode 100644 src/util/pluginUtil.js create mode 100644 test/functional/test_site/expected/9c9e77fc0a983cb6b592e65733787bec.png create mode 100644 test/functional/test_site/expected/inline-output.png diff --git a/docs/userGuide/puml.md b/docs/userGuide/puml.md index d46a132c3f..6bd174ca3b 100644 --- a/docs/userGuide/puml.md +++ b/docs/userGuide/puml.md @@ -30,19 +30,27 @@ A PlantUML diagram file (.puml) can be inserted into a Markbind page using a `

` tag, listed below: ****Options**** -Name | Type | Default | Description ---- | --- | --- | --- -alt | `string` | | **This must be specified.**
The alternative text of the diagram. -height | `string` | | The height of the diagram in pixels. -src | `string` | | **This must be specified.**
The URL of the diagram.
The URL can be specified as absolute or relative references. More info in: _[Intra-Site Links]({{baseUrl}}/userGuide/formattingContents.html#intraSiteLinks)_ -width | `string` | | The width of the diagram in pixels.
If both width and height are specified, width takes priority over height. It is to maintain the diagram's aspect ratio. +Name | Type | Description +--- | --- | --- +alt | `string` | **This must be specified.**
The alternative text of the diagram. +height | `string` | The height of the diagram in pixels. +name | `string` | The name of the output file. +src | `string` | The URL of the diagram if your PUML input is in another file.
The URL can be specified as absolute or relative references. More info in: _[Intra-Site Links]({{baseUrl}}/userGuide/formattingContents.html#intraSiteLinks)_ +width | `string` | The width of the diagram in pixels.
If both width and height are specified, width takes priority over height. It is to maintain the diagram's aspect ratio. ### Example +You could have your PUML be written in a separate file or inline. + +_Markbind page separate file_: +``` + +``` + _diagrams/sequence.puml_: ``` @startuml @@ -57,9 +65,20 @@ return success @enduml ``` -_Markbind page_: +_Markbind page inline_: ``` - + +@startuml +alice -> bob ++ : hello +bob -> bob ++ : self call +bob -> bib ++ #005500 : hello +bob -> george ** : create +return done +return rc +bob -> george !! : delete +return success +@enduml + ``` diff --git a/package-lock.json b/package-lock.json index 27d5346e83..5007394897 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1941,6 +1941,11 @@ "which": "^1.2.9" } }, + "crypto-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", + "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" + }, "css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -3226,8 +3231,7 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true, - "optional": true + "bundled": true }, "aproba": { "version": "1.2.0", @@ -3245,13 +3249,11 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true, - "optional": true + "bundled": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3264,18 +3266,15 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "concat-map": { "version": "0.0.1", - "bundled": true, - "optional": true + "bundled": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true, - "optional": true + "bundled": true }, "core-util-is": { "version": "1.0.2", @@ -3378,8 +3377,7 @@ }, "inherits": { "version": "2.0.3", - "bundled": true, - "optional": true + "bundled": true }, "ini": { "version": "1.3.5", @@ -3389,7 +3387,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -3402,20 +3399,17 @@ "minimatch": { "version": "3.0.4", "bundled": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true, - "optional": true + "bundled": true }, "minipass": { "version": "2.3.5", "bundled": true, - "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3432,7 +3426,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -3505,8 +3498,7 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true, - "optional": true + "bundled": true }, "object-assign": { "version": "4.1.1", @@ -3516,7 +3508,6 @@ "once": { "version": "1.4.0", "bundled": true, - "optional": true, "requires": { "wrappy": "1" } @@ -3592,8 +3583,7 @@ }, "safe-buffer": { "version": "5.1.2", - "bundled": true, - "optional": true + "bundled": true }, "safer-buffer": { "version": "2.1.2", @@ -3623,7 +3613,6 @@ "string-width": { "version": "1.0.2", "bundled": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3641,7 +3630,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -3680,13 +3668,11 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true, - "optional": true + "bundled": true }, "yallist": { "version": "3.0.3", - "bundled": true, - "optional": true + "bundled": true } } }, diff --git a/package.json b/package.json index 3df1a0b18a..926794d6cb 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "cheerio": "^0.22.0", "chokidar": "^3.3.0", "commander": "^3.0.2", + "crypto-js": "^4.0.0", "fastmatter": "^2.1.1", "figlet": "^1.2.4", "find-up": "^4.1.0", diff --git a/src/plugins/default/markbind-plugin-plantuml.js b/src/plugins/default/markbind-plugin-plantuml.js index a7d87b7a1f..4862a991e1 100644 --- a/src/plugins/default/markbind-plugin-plantuml.js +++ b/src/plugins/default/markbind-plugin-plantuml.js @@ -6,42 +6,35 @@ const cheerio = module.parent.require('cheerio'); const fs = require('fs'); const path = require('path'); + const { exec } = require('child_process'); const logger = require('../../util/logger'); +const pluginUtil = require('../../util/pluginUtil'); const JAR_PATH = path.resolve(__dirname, 'plantuml.jar'); const { ERR_PROCESSING, - ERR_READING, } = require('../../constants'); // Tracks diagrams that have already been processed const processedDiagrams = new Set(); /** - * Generates diagram and replaces src attribute of puml tag - * @param src src attribute of the puml tag - * @param cwf original file that contains the puml tag, we resolve relative src to this file + * Generates diagram and returns the file name of the diagram + * @param fileName name of the file to be generated + * @param content puml dsl used to generate the puml diagram * @param config sourcePath and resultPath from parser context - * @returns {string} resolved src attribute + * @returns {string} file name of diagram */ -function generateDiagram(src, cwf, config) { - const { sourcePath, resultPath } = config; - const _cwf = cwf || sourcePath; +function generateDiagram(fileName, content, config) { + const { resultPath } = config; - // For replacing img.src - const diagramSrc = src.replace('.puml', '.png'); + const outputDir = path.join(path.dirname(resultPath), path.dirname(fileName)); // Path of the .puml file - const rawDiagramPath = path.resolve(path.dirname(_cwf), src); - // Path of the .png to be generated - const outputFilePath = path.resolve(resultPath, path.relative(sourcePath, rawDiagramPath) - .replace('.puml', '.png')); - // Output dir for the png file - const outputDir = path.dirname(outputFilePath); - + const outputFilePath = path.join(outputDir, path.basename(fileName)); // Tracks built files to avoid accessing twice - if (processedDiagrams.has(outputFilePath)) { return diagramSrc; } + if (processedDiagrams.has(outputFilePath)) { return fileName; } processedDiagrams.add(outputFilePath); // Creates output dir if it doesn't exist @@ -49,49 +42,37 @@ function generateDiagram(src, cwf, config) { fs.mkdirSync(outputDir, { recursive: true }); } - // Read diagram file, launch PlantUML jar - fs.readFile(rawDiagramPath, (err, data) => { - if (err) { - logger.debug(err); - logger.error(`${ERR_READING} ${rawDiagramPath}`); - return; - } - - const umlCode = data.toString(); - - // Java command to launch PlantUML jar - const cmd = `java -jar "${JAR_PATH}" -pipe > "${outputFilePath}"`; - const childProcess = exec(cmd); - - let errorLog = ''; - - childProcess.stdin.write( - umlCode, - (e) => { - if (e) { - logger.debug(e); - logger.error(`${ERR_PROCESSING} ${rawDiagramPath}`); - } - childProcess.stdin.end(); - }, - ); - - childProcess.on('error', (error) => { - logger.debug(error); - logger.error(`${ERR_PROCESSING} ${rawDiagramPath}`); - }); + // Java command to launch PlantUML jar + const cmd = `java -jar "${JAR_PATH}" -pipe > "${outputFilePath}"`; + const childProcess = exec(cmd); + + let errorLog = ''; + childProcess.stdin.write( + content, + (e) => { + if (e) { + logger.debug(e); + logger.error(`${ERR_PROCESSING} ${fileName}`); + } + childProcess.stdin.end(); + }, + ); + + childProcess.on('error', (error) => { + logger.debug(error); + logger.error(`${ERR_PROCESSING} ${fileName}`); + }); - childProcess.stderr.on('data', (errorMsg) => { - errorLog += errorMsg; - }); + childProcess.stderr.on('data', (errorMsg) => { + errorLog += errorMsg; + }); - childProcess.on('exit', () => { - // This goes to the log file, but not shown on the console - logger.debug(errorLog); - }); + childProcess.on('exit', () => { + // This goes to the log file, but not shown on the console + logger.debug(errorLog); }); - return diagramSrc; + return fileName; } module.exports = { @@ -101,11 +82,14 @@ module.exports = { // Processes all tags const $ = cheerio.load(content, { xmlMode: true }); $('puml').each((i, tag) => { - // eslint-disable-next-line no-param-reassign tag.name = 'pic'; - const { src, cwf } = tag.attribs; - // eslint-disable-next-line no-param-reassign - tag.attribs.src = generateDiagram(src, cwf, config); + const { cwf } = tag.attribs; + const pumlContent = pluginUtil.getPluginContent($, tag, cwf); + + const filePath = pluginUtil.getFilePathForPlugin(tag.attribs, pumlContent); + + tag.attribs.src = generateDiagram(filePath, pumlContent, config); + tag.children = []; }); return $.html(); @@ -113,4 +97,6 @@ module.exports = { getSources: () => ({ tagMap: [['puml', 'src']], }), + + getSpecialTags: () => ['puml'], }; diff --git a/src/util/pluginUtil.js b/src/util/pluginUtil.js new file mode 100644 index 0000000000..15003674d0 --- /dev/null +++ b/src/util/pluginUtil.js @@ -0,0 +1,51 @@ +const cryptoJS = require('crypto-js'); +const fs = require('fs'); +const path = require('path'); +const fsUtil = require('./fsUtil'); +const logger = require('./logger'); + +const { + ERR_READING, +} = require('../constants'); + +const pluginUtil = { + /** + * Returns the file path for the plugin tag. + * Return based on given name if provided, or it will be based on src. + * If both are not provided, a md5 generated hash is provided for consistency. + */ + getFilePathForPlugin: (tagAttribs, content) => { + if (tagAttribs.name !== undefined) { + return `${fsUtil.removeExtension(tagAttribs.name)}.png`; + } + + if (tagAttribs.src !== undefined) { + const filePath = fsUtil.removeExtension(tagAttribs.src); + return `${filePath}.png`; + } + + const hashedContent = cryptoJS.MD5(content).toString(); + return `${hashedContent}.png`; + }, + + /** + * Returns the string content of the plugin. + */ + getPluginContent: ($, element, cwf) => { + if (element.attribs.src !== undefined) { + // Path of the plugin content + const rawPath = path.resolve(path.dirname(cwf), element.attribs.src); + try { + return fs.readFileSync(rawPath, 'utf8'); + } catch (err) { + logger.debug(err); + logger.error(`${ERR_READING} ${rawPath}`); + return ''; + } + } + + return $(element).text(); + }, +}; + +module.exports = pluginUtil; diff --git a/test/functional/test_site/expected/9c9e77fc0a983cb6b592e65733787bec.png b/test/functional/test_site/expected/9c9e77fc0a983cb6b592e65733787bec.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4fd1ece9544d223806ef349840697840fd0b91 GIT binary patch literal 6864 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 g{{HMarkbind Plugin Pre-render +

+

+ +

Sequence Diagram

diff --git a/test/functional/test_site/expected/inline-output.png b/test/functional/test_site/expected/inline-output.png new file mode 100644 index 0000000000000000000000000000000000000000..e0834af42cb6c75e17ea136a645a4ee42955a4f7 GIT binary patch literal 9392 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 Kt&Uc;4*ws7+74C# literal 0 HcmV?d00001 diff --git a/test/functional/test_site/expected/testPlantUML.html b/test/functional/test_site/expected/testPlantUML.html index e359c22e9b..8c273c7987 100644 --- a/test/functional/test_site/expected/testPlantUML.html +++ b/test/functional/test_site/expected/testPlantUML.html @@ -26,6 +26,12 @@

PlantUML Test

+

+ +

+

+ +

Sequence Diagram

diff --git a/test/functional/test_site/testPlantUML.md b/test/functional/test_site/testPlantUML.md index a407b745a9..ac8ca67531 100644 --- a/test/functional/test_site/testPlantUML.md +++ b/test/functional/test_site/testPlantUML.md @@ -1,5 +1,41 @@ **PlantUML Test** + + +@startuml +alice -> bob ++ : hello +bob -> bob ++ : self call +bob -> bib ++ #005500 : hello +bob -> george ** : create +return done +return rc +bob -> george !! : delete +return success +@enduml + + + + +@startuml +object Object01 +object Object02 +object Object03 +object Object04 +object Object05 +object Object06 +object Object07 +object Object08 +object user { + name = "Dummy" + id = 123 +} +Object01 <|-- Object02 +Object03 *-- Object04 +Object05 o-- "4" Object06 +Object07 .. Object08 : some labels +@enduml + + **Sequence Diagram**