From d7bf92b39f756315617a85900240331732001d42 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Fri, 28 Oct 2022 14:13:24 +0530 Subject: [PATCH] fix: Use AST to replace notes & warnings. --- .vscode/launch.json | 11 +++ cSpell.json | 5 +- docs/community/newDiagram.md | 13 ++-- docs/config/8.6.0_docs.md | 36 +++------- docs/config/theming.md | 4 +- docs/config/usage.md | 34 +++------- docs/syntax/sequenceDiagram.md | 4 +- packages/mermaid/src/docs.mts | 67 +++++-------------- .../mermaid/src/docs/community/newDiagram.md | 9 ++- packages/mermaid/src/docs/config/usage.md | 10 +-- packages/mermaid/src/mermaidAPI.ts | 2 +- 11 files changed, 68 insertions(+), 127 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 92df7056e..83b80fa40 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -12,6 +12,17 @@ "args": ["run", "${relativeFile}"], "smartStep": true, "console": "integratedTerminal" + }, + { + "name": "Docs generation", + "type": "node", + "request": "launch", + "args": ["src/docs.mts"], + "runtimeArgs": ["--loader", "ts-node/esm"], + "cwd": "${workspaceRoot}/packages/mermaid", + "skipFiles": ["/**", "**/node_modules/**"], + "smartStep": true, + "internalConsoleOptions": "openOnSessionStart" } ] } diff --git a/cSpell.json b/cSpell.json index 7e7c82b75..4a6d092e9 100644 --- a/cSpell.json +++ b/cSpell.json @@ -2,19 +2,20 @@ "version": "0.2", "language": "en", "words": [ + "blockquotes", "customizability", "Gantt", "jison", "knsv", "Knut", + "mermiad", "mindmap", "Mindmaps", "mitigations", "sandboxed", "Sveidqvist", "verdana", - "Visio", - "mermiad" + "Visio" ], "ignoreWords": [ "Faber", diff --git a/docs/community/newDiagram.md b/docs/community/newDiagram.md index 82243f81f..df3ea2aae 100644 --- a/docs/community/newDiagram.md +++ b/docs/community/newDiagram.md @@ -32,10 +32,8 @@ statement In the extract of the grammar above, it is defined that a call to the setTitle method in the data object will be done when parsing and the title keyword is encountered. -> **Note**\ +> **Note** > Make sure that the `parseError` function for the parser is defined and calling `mermaid.parseError`. This way a common way of detecting parse errors is provided for the end-user. -> -> > For more info look in the example diagram type: @@ -50,8 +48,7 @@ exports.parseError = function (err, hash) { when parsing the `yy` object is initialized as per below: ```javascript -var parser; -parser = exampleParser.parser; +const parser = exampleParser.parser; parser.yy = db; ``` @@ -74,8 +71,8 @@ At this point when mermaid is trying to render the diagram, it will detect it as ### Setup ```javascript -var graph = require('./graphDb'); -var flow = require('./parser/flow'); +const graph = require('./graphDb'); +const flow = require('./parser/flow'); flow.parser.yy = graph; ``` @@ -96,7 +93,7 @@ graph.getEdges(); The parser is also exposed in the mermaid api by calling: ```javascript -var parser = mermaid.getParser(); +const parser = mermaid.getParser(); ``` Note that the parse needs a graph object to store the data as per: diff --git a/docs/config/8.6.0_docs.md b/docs/config/8.6.0_docs.md index 8fb8d0b6a..46c181799 100644 --- a/docs/config/8.6.0_docs.md +++ b/docs/config/8.6.0_docs.md @@ -52,10 +52,8 @@ Implementors can only modify configurations using directives, and cannot change The Two types of directives: are `init` (or `initialize`) and `wrap`. -> **Note**\ +> **Note** > All directives are enclosed in `%%{ }%%` -> -> > Older versions of mermaid will not parse directives because `%%` will comment out the directive. This makes the update backwards-compatible. @@ -67,7 +65,7 @@ Older versions of mermaid will not parse directives because `%%` will comment ou | --------- | ----------------------- | --------- | -------- | ----------------------------------------------- | | init | modifies configurations | Directive | Optional | Any parameters not included in the secure array | -> **Note**\ +> **Note** > init would be an argument-directive: `%%{init: { **insert argument here**}}%%` > > The json object that is passed as {**argument** } must be valid, quoted json or it will be ignored. @@ -78,8 +76,6 @@ Older versions of mermaid will not parse directives because `%%` will comment ou > Configurations that are passed through init cannot change the parameters in a secure array at a higher level. In the event of a collision, mermaid will give priority to secure arrays and parse the request without changing the values of those parameters in conflict. > > When deployed within code, init is called before the graph/diagram description. -> -> > **for example**: @@ -113,7 +109,7 @@ Older versions of mermaid will not parse directives because `%%` will comment ou | --------- | ----------------------------- | --------- | -------- | ---------- | | wrap | a callable text-wrap function | Directive | Optional | %%{wrap}%% | -> **Note**\ +> **Note** > Wrap is a function that is currently only deployable for sequence diagrams. > > `Wrap respects a manually added
, so if the user wants to break up their text, they have full control over line breaks by adding
tags.` @@ -121,8 +117,6 @@ Older versions of mermaid will not parse directives because `%%` will comment ou > It is a non-argument directive and can be executed thusly: > > `%%{wrap}%%` . -> -> > **An example of text wrapping in a sequence diagram**: @@ -164,14 +158,12 @@ Example of **object.Assign**: | --------------- | ------------------------------------- | ----------- | --------------------------------------- | ---------- | ---------- | | `setSiteConfig` | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array | conf | siteConfig | -> **Note**\ +> **Note** > Sets the siteConfig. The siteConfig is a protected configuration for repeat use. Calls to reset() will reset > the currentConfig to siteConfig. Calls to reset(configApi.defaultConfig) will reset siteConfig and currentConfig > to the defaultConfig > Note: currentConfig is set in this function。 > Default value: will mirror Global Config -> -> > ## getSiteConfig @@ -179,10 +171,8 @@ Example of **object.Assign**: | --------------- | --------------------------------------------------- | ----------- | ---------------------------------- | | `getSiteConfig` | Returns the current `siteConfig` base configuration | Get Request | Returns Any Values in `siteConfig` | -> **Note**\ +> **Note** > Returns any values in siteConfig. -> -> > ## setConfig @@ -190,12 +180,10 @@ Example of **object.Assign**: | ----------- | ------------------------------------------ | ----------- | --------------------------------- | ---------- | ---------------------------------------------- | | `setConfig` | Sets the `currentConfig` to desired values | Put Request | Any Values, those in secure array | conf | `currentConfig` merged with the sanitized conf | -> **Note**\ +> **Note** > Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure keys. Any > values found in conf with key found in siteConfig.secure will be replaced with the corresponding > siteConfig value. -> -> > ## getConfig @@ -203,10 +191,8 @@ Example of **object.Assign**: | ----------- | --------------------------- | ----------- | ------------------------------- | | `getConfig` | Obtains the `currentConfig` | Get Request | Any Values from `currentConfig` | -> **Note**\ +> **Note** > Returns any values in currentConfig. -> -> > ## sanitize @@ -214,11 +200,9 @@ Example of **object.Assign**: | ---------- | ---------------------------------------- | -------------- | ------ | | `sanitize` | Sets the `siteConfig` to desired values. | Put Request(?) | None | -> **Note**\ +> **Note** > modifies options in-place > Ensures options parameter does not attempt to override siteConfig secure keys. -> -> > ## reset @@ -232,9 +216,7 @@ Example of **object.Assign**: | --------- | ------------------------------------------------------------ | ---------- | -------- | -------------------------------------------- | | `conf` | base set of values, which `currentConfig` could be reset to. | Dictionary | Required | Any Values, with respect to the secure Array | -> **Note**\ +> **Note** > default: current siteConfig (optional, default `getSiteConfig()`) -> -> > ## For more information, read [Setup](setup/README). diff --git a/docs/config/theming.md b/docs/config/theming.md index 5e81c91f9..6ec46f5bb 100644 --- a/docs/config/theming.md +++ b/docs/config/theming.md @@ -156,10 +156,8 @@ You can create your own themes, by changing any of the given variables below. If ## Theme Variables Reference Table -> **Note**\ +> **Note** > Variables that are unique to some diagrams can be affected by changes in Theme Variables -> -> > | Variable | Default/Base/Factor value | Calc | Description | | -------------------- | ------------------------------ | ---- | -------------------------------------------------------------------------------------------------------------------------------- | diff --git a/docs/config/usage.md b/docs/config/usage.md index 0a348ff71..241fec4e5 100644 --- a/docs/config/usage.md +++ b/docs/config/usage.md @@ -119,11 +119,9 @@ Values: - **antiscript**: html tags in text are allowed, (only script element is removed), click functionality is enabled - **sandbox**: With this security level all rendering takes place in a sandboxed iframe. This prevent any JavaScript running in the context. This may hinder interactive functionality of the diagram like scripts, popups in sequence diagram or links to other tabs/targets etc. -> **Note**\ +> **Note** > This changes the default behaviour of mermaid so that after upgrade to 8.2, unless the `securityLevel` is not changed, tags in flowcharts are encoded as tags and clicking is disabled. > **sandbox** security level is still in the beta version. -> -> > **If you are taking responsibility for the diagram source security you can set the `securityLevel` to a value of your choosing . This allows clicks and tags are allowed.** @@ -188,10 +186,8 @@ Or with no config object, and a jQuery selection: mermaid.init(undefined, $('#someId .yetAnotherClass')); ``` -> **Warning**\ +> **Warning** > This type of integration is deprecated. Instead the preferred way of handling more complex integration is to use the mermaidAPI instead. -> -> > ## Usage with webpack @@ -230,7 +226,7 @@ The example code below is an extract of what mermaid does when using the API. Th bind events to an SVG when using the API for rendering. ```javascript -var insertSvg = function (svgCode, bindFunctions) { +const insertSvg = function (svgCode, bindFunctions) { element.innerHTML = svgCode; if (typeof callback !== 'undefined') { callback(id); @@ -238,7 +234,7 @@ var insertSvg = function (svgCode, bindFunctions) { bindFunctions(element); }; -var id = 'theGraph'; +const id = 'theGraph'; mermaidAPI.render(id, txt, insertSvg, element); ``` @@ -254,7 +250,7 @@ mermaidAPI.render(id, txt, insertSvg, element); This is the renderer used for transforming the documentation from Markdown to html with mermaid diagrams in the html. ```javascript -var renderer = new marked.Renderer(); +const renderer = new marked.Renderer(); renderer.code = function (code, language) { if (code.match(/^sequenceDiagram/) || code.match(/^graph/)) { return '
' + code + '
'; @@ -305,8 +301,8 @@ mermaid.parseError = function (err, hash) { displayErrorInGui(err); }; -var textFieldUpdated = function () { - var textStr = getTextFromFormField('code'); +const textFieldUpdated = function () { + const textStr = getTextFromFormField('code'); if (mermaid.parse(textStr)) { reRender(textStr); @@ -345,10 +341,8 @@ on what kind of integration you use. ``` -> **Note**\ +> **Note** > This is the preferred way of configuring mermaid. -> -> > ### The following methods are deprecated and are kept only for backwards compatibility. @@ -364,10 +358,8 @@ approach are: mermaid.startOnLoad = true; ``` -> **Warning**\ +> **Warning** > This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility. -> -> > ## Using the mermaid_config @@ -381,10 +373,8 @@ approach are: mermaid_config.startOnLoad = true; ``` -> **Warning**\ +> **Warning** > This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility. -> -> > ## Using the mermaid.init call @@ -397,7 +387,5 @@ To set some configuration via the mermaid object. The two parameters that are su mermaid_config.startOnLoad = true; ``` -> **Warning**\ +> **Warning** > This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility. -> -> > diff --git a/docs/syntax/sequenceDiagram.md b/docs/syntax/sequenceDiagram.md index da33b8ff6..b7467323a 100644 --- a/docs/syntax/sequenceDiagram.md +++ b/docs/syntax/sequenceDiagram.md @@ -24,12 +24,10 @@ sequenceDiagram Alice-)John: See you later! ``` -> **Note**\ +> **Note** > A note on nodes, the word "end" could potentially break the diagram, due to the way that the mermaid language is scripted. > > If unavoidable, one must use parentheses(), quotation marks "", or brackets {},\[], to enclose the word "end". i.e : (end), \[end], {end}. -> -> > ## Syntax diff --git a/packages/mermaid/src/docs.mts b/packages/mermaid/src/docs.mts index 2c62c9ea8..870aa9e7b 100644 --- a/packages/mermaid/src/docs.mts +++ b/packages/mermaid/src/docs.mts @@ -133,49 +133,15 @@ const copyTransformedContents = (filename: string, doCopy = false, transformedCo logWasOrShouldBeTransformed(fileInFinalDocDir, doCopy); }; -const transformAnnotation = (content: string, type: 'warning' | 'tip' | 'note') => { - let transformed = content; - let regex = /```note\n[\s\S]+?```/gm; - let text = 'Note'; - - switch (type) { - case 'note': - regex = /```note\s?\n[\s\S]+?```/gm; - break; - case 'tip': - regex = /```tip\s?\n[\s\S]+?```/gm; - text = 'Note'; - break; - case 'warning': - regex = /```warning\s?\n[\s\S]+?```/gm; - text = 'Warning'; - break; - default: - break; - } - - const matches = content.match(regex); - if (matches) { - console.log(`found ${matches.length} of ${type}`); - - const formatted = matches.map((element) => - element - .replace(`\`\`\`${type}`, `> **${text}** `) - .replace('```', '>') - .split('\n') - .join('\n> ') - ); - let n = 0; - for (const match of matches) { - transformed = transformed.replace(match, formatted[n++]); - } - } - return transformed; -}; const readSyncedUTF8file = (filename: string): string => { return readFileSync(filename, 'utf8'); }; +const transformToBlockQuote = (content: string, type: string) => { + const title = type === 'warning' ? 'Warning' : 'Note'; + return `> **${title}** \n> ${content.replace(/\n/g, '\n> ')}`; +}; + /** * Transform a markdown file and write the transformed file to the directory for published * documentation @@ -189,24 +155,25 @@ const readSyncedUTF8file = (filename: string): string => { * @param file {string} name of the file that will be verified */ const transformMarkdown = (file: string) => { - let doc = readSyncedUTF8file(file).replace(//g, MERMAID_MAJOR_VERSION); - - doc = transformAnnotation(doc, 'warning'); - doc = transformAnnotation(doc, 'tip'); - doc = transformAnnotation(doc, 'note'); - + const doc = readSyncedUTF8file(file).replace(//g, MERMAID_MAJOR_VERSION); const ast: Root = remark.parse(doc); const out = flatmap(ast, (c: Code) => { - if (c.type !== 'code') { + if (c.type !== 'code' || !c.lang) { return [c]; } - if (c.lang === 'mermaid' || c.lang === 'mmd') { + + // Convert mermaid code blocks to mermaid-example blocks + if (['mermaid', 'mmd', 'mermaid-example'].includes(c.lang)) { c.lang = 'mermaid-example'; + return [c, Object.assign({}, c, { lang: 'mermaid' })]; } - if (c.lang !== 'mermaid-example') { - return [c]; + + // Transform codeblocks into block quotes. + if (['note', 'tip', 'warning'].includes(c.lang)) { + return [remark.parse(transformToBlockQuote(c.value, c.lang))]; } - return [c, Object.assign({}, c, { lang: 'mermaid' })]; + + return [c]; }); // Add the AUTOGENERATED_TEXT to the start of the file diff --git a/packages/mermaid/src/docs/community/newDiagram.md b/packages/mermaid/src/docs/community/newDiagram.md index a902f1961..74026b3ff 100644 --- a/packages/mermaid/src/docs/community/newDiagram.md +++ b/packages/mermaid/src/docs/community/newDiagram.md @@ -43,8 +43,7 @@ exports.parseError = function (err, hash) { when parsing the `yy` object is initialized as per below: ```javascript -var parser; -parser = exampleParser.parser; +const parser = exampleParser.parser; parser.yy = db; ``` @@ -67,8 +66,8 @@ At this point when mermaid is trying to render the diagram, it will detect it as ### Setup ```javascript -var graph = require('./graphDb'); -var flow = require('./parser/flow'); +const graph = require('./graphDb'); +const flow = require('./parser/flow'); flow.parser.yy = graph; ``` @@ -89,7 +88,7 @@ graph.getEdges(); The parser is also exposed in the mermaid api by calling: ```javascript -var parser = mermaid.getParser(); +const parser = mermaid.getParser(); ``` Note that the parse needs a graph object to store the data as per: diff --git a/packages/mermaid/src/docs/config/usage.md b/packages/mermaid/src/docs/config/usage.md index e7c745f78..63b80e578 100644 --- a/packages/mermaid/src/docs/config/usage.md +++ b/packages/mermaid/src/docs/config/usage.md @@ -224,7 +224,7 @@ The example code below is an extract of what mermaid does when using the API. Th bind events to an SVG when using the API for rendering. ```javascript -var insertSvg = function (svgCode, bindFunctions) { +const insertSvg = function (svgCode, bindFunctions) { element.innerHTML = svgCode; if (typeof callback !== 'undefined') { callback(id); @@ -232,7 +232,7 @@ var insertSvg = function (svgCode, bindFunctions) { bindFunctions(element); }; -var id = 'theGraph'; +const id = 'theGraph'; mermaidAPI.render(id, txt, insertSvg, element); ``` @@ -248,7 +248,7 @@ mermaidAPI.render(id, txt, insertSvg, element); This is the renderer used for transforming the documentation from Markdown to html with mermaid diagrams in the html. ```javascript -var renderer = new marked.Renderer(); +const renderer = new marked.Renderer(); renderer.code = function (code, language) { if (code.match(/^sequenceDiagram/) || code.match(/^graph/)) { return '
' + code + '
'; @@ -299,8 +299,8 @@ mermaid.parseError = function (err, hash) { displayErrorInGui(err); }; -var textFieldUpdated = function () { - var textStr = getTextFromFormField('code'); +const textFieldUpdated = function () { + const textStr = getTextFromFormField('code'); if (mermaid.parse(textStr)) { reRender(textStr); diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index 06cfdde45..d6bc9672a 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -508,7 +508,7 @@ export default mermaidAPI; * * ```html *