mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-30 18:34:09 +01:00 
			
		
		
		
	fix: #4818 support getClasses in external diagrams.
				
					
				
			This commit is contained in:
		| @@ -16,4 +16,4 @@ | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:78](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L78) | ||||
| [mermaidAPI.ts:61](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L61) | ||||
|   | ||||
| @@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present. | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L98) | ||||
| [mermaidAPI.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L81) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -51,4 +51,4 @@ The svg code for the rendered graph. | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L88) | ||||
| [mermaidAPI.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L71) | ||||
|   | ||||
| @@ -25,7 +25,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi) | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:82](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L82) | ||||
| [mermaidAPI.ts:65](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L65) | ||||
|  | ||||
| ## Variables | ||||
|  | ||||
| @@ -96,7 +96,7 @@ mermaid.initialize(config); | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:673](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L673) | ||||
| [mermaidAPI.ts:654](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L654) | ||||
|  | ||||
| ## Functions | ||||
|  | ||||
| @@ -127,7 +127,7 @@ Return the last node appended | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:310](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L310) | ||||
| [mermaidAPI.ts:293](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L293) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -153,7 +153,7 @@ the cleaned up svgCode | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:256](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L256) | ||||
| [mermaidAPI.ts:239](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L239) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -179,7 +179,7 @@ the string with all the user styles | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:185](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L185) | ||||
| [mermaidAPI.ts:168](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L168) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -190,10 +190,10 @@ the string with all the user styles | ||||
| #### Parameters | ||||
|  | ||||
| | Name        | Type                                                      | | ||||
| | :---------- | :----------------------------------------- | | ||||
| | :---------- | :-------------------------------------------------------- | | ||||
| | `config`    | `MermaidConfig`                                           | | ||||
| | `graphType` | `string`                                                  | | ||||
| | `classDefs` | `Record`<`string`, `DiagramStyleClassDef`> | | ||||
| | `classDefs` | `undefined` \| `Record`<`string`, `DiagramStyleClassDef`> | | ||||
| | `svgId`     | `string`                                                  | | ||||
|  | ||||
| #### Returns | ||||
| @@ -202,7 +202,7 @@ the string with all the user styles | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:233](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L233) | ||||
| [mermaidAPI.ts:216](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L216) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -229,7 +229,7 @@ with an enclosing block that has each of the cssClasses followed by !important; | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:169](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L169) | ||||
| [mermaidAPI.ts:152](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L152) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -249,7 +249,7 @@ with an enclosing block that has each of the cssClasses followed by !important; | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:155](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L155) | ||||
| [mermaidAPI.ts:138](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L138) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -269,7 +269,7 @@ with an enclosing block that has each of the cssClasses followed by !important; | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:126](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L126) | ||||
| [mermaidAPI.ts:109](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L109) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -295,7 +295,7 @@ Put the svgCode into an iFrame. Return the iFrame code | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:287](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L287) | ||||
| [mermaidAPI.ts:270](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L270) | ||||
|  | ||||
| --- | ||||
|  | ||||
| @@ -320,4 +320,4 @@ Remove any existing elements from the given document | ||||
|  | ||||
| #### Defined in | ||||
|  | ||||
| [mermaidAPI.ts:360](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L360) | ||||
| [mermaidAPI.ts:343](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L343) | ||||
|   | ||||
| @@ -43,7 +43,11 @@ export const addDiagrams = () => { | ||||
|         }, | ||||
|       }, | ||||
|       styles: {}, // should never be used | ||||
|       renderer: {}, // should never be used | ||||
|       renderer: { | ||||
|         draw: () => { | ||||
|           // should never be used | ||||
|         }, | ||||
|       }, | ||||
|       parser: { | ||||
|         parser: { yy: {} }, | ||||
|         parse: () => { | ||||
|   | ||||
| @@ -41,7 +41,11 @@ describe('DiagramAPI', () => { | ||||
|           }, | ||||
|           parser: { yy: {} }, | ||||
|         }, | ||||
|         renderer: {}, | ||||
|         renderer: { | ||||
|           draw: () => { | ||||
|             // no-op | ||||
|           }, | ||||
|         }, | ||||
|         styles: {}, | ||||
|       }, | ||||
|       detector | ||||
|   | ||||
| @@ -32,9 +32,26 @@ export interface DiagramDB { | ||||
|   bindFunctions?: (element: Element) => void; | ||||
| } | ||||
|  | ||||
| // This is what is returned from getClasses(...) methods. | ||||
| // It is slightly renamed to ..StyleClassDef instead of just ClassDef because "class" is a greatly ambiguous and overloaded word. | ||||
| // It makes it clear we're working with a style class definition, even though defining the type is currently difficult. | ||||
| export interface DiagramStyleClassDef { | ||||
|   id: string; | ||||
|   styles?: string[]; | ||||
|   textStyles?: string[]; | ||||
| } | ||||
|  | ||||
| export interface DiagramRenderer { | ||||
|   draw: DrawDefinition; | ||||
|   getClasses?: ( | ||||
|     text: string, | ||||
|     diagram: Pick<DiagramDefinition, 'db'> | ||||
|   ) => Record<string, DiagramStyleClassDef>; | ||||
| } | ||||
|  | ||||
| export interface DiagramDefinition { | ||||
|   db: DiagramDB; | ||||
|   renderer: any; | ||||
|   renderer: DiagramRenderer; | ||||
|   parser: ParserDefinition; | ||||
|   styles?: any; | ||||
|   init?: (config: MermaidConfig) => void; | ||||
| @@ -76,7 +93,7 @@ export type DrawDefinition = ( | ||||
|   id: string, | ||||
|   version: string, | ||||
|   diagramObject: Diagram | ||||
| ) => void; | ||||
| ) => void | Promise<void>; | ||||
|  | ||||
| export interface ParserDefinition { | ||||
|   parse: (text: string) => void; | ||||
|   | ||||
| @@ -34,7 +34,11 @@ describe('diagram detection', () => { | ||||
|                 yy: {}, | ||||
|               }, | ||||
|             }, | ||||
|             renderer: {}, | ||||
|             renderer: { | ||||
|               draw: () => { | ||||
|                 // no-op | ||||
|               }, | ||||
|             }, | ||||
|             styles: {}, | ||||
|           }, | ||||
|         }) | ||||
|   | ||||
| @@ -4,11 +4,10 @@ import insertMarkers from '../../../dagre-wrapper/markers.js'; | ||||
| import { insertEdgeLabel } from '../../../dagre-wrapper/edges.js'; | ||||
| import { findCommonAncestor } from './render-utils.js'; | ||||
| import { labelHelper } from '../../../dagre-wrapper/shapes/util.js'; | ||||
| import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js'; | ||||
| import { getConfig } from '../../../config.js'; | ||||
| import { log } from '../../../logger.js'; | ||||
| import { setupGraphViewbox } from '../../../setupGraphViewbox.js'; | ||||
| import common, { evaluate } from '../../common/common.js'; | ||||
| import common from '../../common/common.js'; | ||||
| import { interpolateToCurve, getStylesFromArray } from '../../../utils.js'; | ||||
| import ELK from 'elkjs/lib/elk.bundled.js'; | ||||
| const elk = new ELK(); | ||||
| @@ -651,7 +650,7 @@ const addMarkersToEdge = function (svgPath, edgeData, diagramType, arrowMarkerAb | ||||
|  * | ||||
|  * @param text | ||||
|  * @param diagObj | ||||
|  * @returns {object} ClassDef styles | ||||
|  * @returns {Record<string, import('../../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles | ||||
|  */ | ||||
| export const getClasses = function (text, diagObj) { | ||||
|   log.info('Extracting classes'); | ||||
|   | ||||
| @@ -338,7 +338,7 @@ export const addEdges = function (edges, g, diagObj) { | ||||
|  * | ||||
|  * @param text | ||||
|  * @param diagObj | ||||
|  * @returns {object} ClassDef styles | ||||
|  * @returns {Record<string, import('../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles | ||||
|  */ | ||||
| export const getClasses = function (text, diagObj) { | ||||
|   return diagObj.db.getClasses(); | ||||
|   | ||||
| @@ -269,7 +269,7 @@ export const addEdges = function (edges, g, diagObj) { | ||||
|  * | ||||
|  * @param text | ||||
|  * @param diagObj | ||||
|  * @returns {object} ClassDef styles | ||||
|  * @returns {Record<string, import('../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles | ||||
|  */ | ||||
| export const getClasses = function (text, diagObj) { | ||||
|   log.info('Extracting classes'); | ||||
|   | ||||
| @@ -81,7 +81,7 @@ export const setConf = function (cnf) { | ||||
|  * | ||||
|  * @param {string} text - the diagram text to be parsed | ||||
|  * @param diagramObj | ||||
|  * @returns {object} ClassDef styles (a Map with keys = strings, values = ) | ||||
|  * @returns {Record<string, import('../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles (a Map with keys = strings, values = ) | ||||
|  */ | ||||
| export const getClasses = function (text, diagramObj) { | ||||
|   diagramObj.db.extract(diagramObj.db.getRootDocV2()); | ||||
|   | ||||
| @@ -95,8 +95,10 @@ describe('when using mermaid and ', () => { | ||||
|       let loaded = false; | ||||
|       const dummyDiagram: DiagramDefinition = { | ||||
|         db: {}, | ||||
|         renderer: () => { | ||||
|           // do nothing | ||||
|         renderer: { | ||||
|           draw: () => { | ||||
|             // no-op | ||||
|           }, | ||||
|         }, | ||||
|         parser: { | ||||
|           parse: (_text) => { | ||||
|   | ||||
| @@ -31,16 +31,8 @@ import isEmpty from 'lodash-es/isEmpty.js'; | ||||
| import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js'; | ||||
| import { parseDirective } from './directiveUtils.js'; | ||||
| import { extractFrontMatter } from './diagram-api/frontmatter.js'; | ||||
| import type { DiagramStyleClassDef } from './diagram-api/types.js'; | ||||
|  | ||||
| // diagram names that support classDef statements | ||||
| const CLASSDEF_DIAGRAMS = [ | ||||
|   'graph', | ||||
|   'flowchart', | ||||
|   'flowchart-v2', | ||||
|   'flowchart-elk', | ||||
|   'stateDiagram', | ||||
|   'stateDiagram-v2', | ||||
| ]; | ||||
| const MAX_TEXTLENGTH = 50_000; | ||||
| const MAX_TEXTLENGTH_EXCEEDED_MSG = | ||||
|   'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa'; | ||||
| @@ -65,15 +57,6 @@ const IFRAME_NOT_SUPPORTED_MSG = 'The "iframe" tag is not supported by your brow | ||||
| const DOMPURIFY_TAGS = ['foreignobject']; | ||||
| const DOMPURIFY_ATTR = ['dominant-baseline']; | ||||
|  | ||||
| // This is what is returned from getClasses(...) methods. | ||||
| // It is slightly renamed to ..StyleClassDef instead of just ClassDef because "class" is a greatly ambiguous and overloaded word. | ||||
| // It makes it clear we're working with a style class definition, even though defining the type is currently difficult. | ||||
| interface DiagramStyleClassDef { | ||||
|   id: string; | ||||
|   styles?: string[]; | ||||
|   textStyles?: string[]; | ||||
| } | ||||
|  | ||||
| export interface ParseOptions { | ||||
|   suppressErrors?: boolean; | ||||
| } | ||||
| @@ -204,7 +187,7 @@ export const createCssStyles = ( | ||||
|   } | ||||
|  | ||||
|   // classDefs defined in the diagram text | ||||
|   if (!isEmpty(classDefs) && CLASSDEF_DIAGRAMS.includes(graphType)) { | ||||
|   if (!isEmpty(classDefs)) { | ||||
|     const htmlLabels = config.htmlLabels || config.flowchart?.htmlLabels; // TODO why specifically check the Flowchart diagram config? | ||||
|  | ||||
|     const cssHtmlElements = ['> *', 'span']; // TODO make a constant | ||||
| @@ -233,7 +216,7 @@ export const createCssStyles = ( | ||||
| export const createUserStyles = ( | ||||
|   config: MermaidConfig, | ||||
|   graphType: string, | ||||
|   classDefs: Record<string, DiagramStyleClassDef>, | ||||
|   classDefs: Record<string, DiagramStyleClassDef> | undefined, | ||||
|   svgId: string | ||||
| ): string => { | ||||
|   const userCSSstyles = createCssStyles(config, graphType, classDefs); | ||||
| @@ -492,9 +475,7 @@ const render = async function ( | ||||
|   // Insert an element into svg. This is where we put the styles | ||||
|   const svg = element.firstChild; | ||||
|   const firstChild = svg.firstChild; | ||||
|   const diagramClassDefs = CLASSDEF_DIAGRAMS.includes(diagramType) | ||||
|     ? diag.renderer.getClasses(text, diag) | ||||
|     : {}; | ||||
|   const diagramClassDefs = diag.renderer.getClasses?.(text, diag); | ||||
|  | ||||
|   const rules = createUserStyles(config, diagramType, diagramClassDefs, idSelector); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Sidharth Vinod
					Sidharth Vinod