Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: move from objects to Maps #5468

Merged
merged 20 commits into from May 16, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 10 additions & 10 deletions docs/config/setup/modules/mermaidAPI.md
Expand Up @@ -167,10 +167,10 @@ Create the user styles

#### Parameters

| Name | Type | Description |
| :---------- | :------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ |
| `config` | `MermaidConfig` | configuration that has style and theme settings to use |
| `classDefs` | `undefined` \| `null` \| `Record`<`string`, `DiagramStyleClassDef`> | the classDefs in the diagram text. Might be null if none were defined. Usually is the result of a call to getClasses(...) |
| Name | Type | Description |
| :---------- | :--------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ |
| `config` | `MermaidConfig` | configuration that has style and theme settings to use |
| `classDefs` | `undefined` \| `null` \| `Map`<`string`, `DiagramStyleClassDef`> | the classDefs in the diagram text. Might be null if none were defined. Usually is the result of a call to getClasses(...) |

#### Returns

Expand All @@ -190,12 +190,12 @@ the string with all the user styles

#### Parameters

| Name | Type |
| :---------- | :-------------------------------------------------------- |
| `config` | `MermaidConfig` |
| `graphType` | `string` |
| `classDefs` | `undefined` \| `Record`<`string`, `DiagramStyleClassDef`> |
| `svgId` | `string` |
| Name | Type |
| :---------- | :----------------------------------------------------- |
| `config` | `MermaidConfig` |
| `graphType` | `string` |
| `classDefs` | `undefined` \| `Map`<`string`, `DiagramStyleClassDef`> |
| `svgId` | `string` |

#### Returns

Expand Down
6 changes: 3 additions & 3 deletions packages/mermaid-flowchart-elk/src/flowRenderer-elk.js
Expand Up @@ -41,12 +41,12 @@
export const addVertices = async function (vert, svgId, root, doc, diagObj, parentLookupDb, graph) {
const svg = root.select(`[id="${svgId}"]`);
const nodes = svg.insert('g').attr('class', 'nodes');
const keys = Object.keys(vert);
const keys = [...vert.keys()];

// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
await Promise.all(
keys.map(async function (id) {
const vertex = vert[id];
const vertex = vert.get(id);

/**
* Variable for storing the classes for the vertex
Expand All @@ -64,7 +64,7 @@
let vertexText = vertex.text !== undefined ? vertex.text : vertex.id;

// We create a SVG label, either by delegating to addHtmlLabel or manually
let vertexNode;

Check warning on line 67 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

'vertexNode' is defined but never used

Check warning on line 67 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

'vertexNode' is defined but never used
const labelData = { width: 0, height: 0 };

const ports = [
Expand Down Expand Up @@ -188,7 +188,7 @@
nodeEl = await insertNode(nodes, node, vertex.dir);
boundingBox = nodeEl.node().getBBox();
} else {
const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');

Check warning on line 191 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

'svgLabel' is assigned a value but never used

Check warning on line 191 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

'svgLabel' is assigned a value but never used
// svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
// const rows = vertexText.split(common.lineBreakRegex);
// for (const row of rows) {
Expand Down Expand Up @@ -394,7 +394,7 @@
* Add edges to graph based on parsed graph definition
*
* @param {object} edges The edges to add to the graph
* @param {object} g The graph object

Check warning on line 397 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

Expected @param names to be "edges, diagObj, graph, svg". Got "edges, g, cy, diagObj, graph, svg"

Check warning on line 397 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

Expected @param names to be "edges, diagObj, graph, svg". Got "edges, g, cy, diagObj, graph, svg"
* @param cy
* @param diagObj
* @param graph
Expand Down Expand Up @@ -595,7 +595,7 @@
*
* @param text
* @param diagObj
* @returns {Record<string, import('../../mermaid/src/diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
* @returns {Map<string, import('../../mermaid/src/diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
*/
export const getClasses = function (text, diagObj) {
log.info('Extracting classes');
Expand Down Expand Up @@ -677,7 +677,7 @@
/**
* Recursive function that iterates over an array of nodes and inserts the children of each node.
* It also recursively populates the inserts the children of the children and so on.
* @param {*} graph

Check warning on line 680 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

Expected @param names to be "nodeArray, parentLookupDb". Got "graph, nodeArray, parentLookupDb"

Check warning on line 680 in packages/mermaid-flowchart-elk/src/flowRenderer-elk.js

View workflow job for this annotation

GitHub Actions / lint

Expected @param names to be "nodeArray, parentLookupDb". Got "graph, nodeArray, parentLookupDb"
* @param nodeArray
* @param parentLookupDb
*/
Expand Down
2 changes: 1 addition & 1 deletion packages/mermaid/src/diagram-api/types.ts
Expand Up @@ -70,7 +70,7 @@ export interface DiagramRenderer {
getClasses?: (
text: string,
diagram: Pick<DiagramDefinition, 'db'>
) => Record<string, DiagramStyleClassDef>;
) => Map<string, DiagramStyleClassDef>;
}

export interface DiagramDefinition {
Expand Down
63 changes: 32 additions & 31 deletions packages/mermaid/src/diagrams/block/blockDB.ts
Expand Up @@ -6,16 +6,16 @@ import { clear as commonClear } from '../common/commonDb.js';
import type { Block, ClassDef } from './blockTypes.js';

// Initialize the node database for simple lookups
let blockDatabase: Record<string, Block> = {};
let blockDatabase: Map<string, Block> = new Map();
let edgeList: Block[] = [];
let edgeCount: Record<string, number> = {};
let edgeCount: Map<string, number> = new Map();

const COLOR_KEYWORD = 'color';
const FILL_KEYWORD = 'fill';
const BG_FILL = 'bgFill';
const STYLECLASS_SEP = ',';

let classes = {} as Record<string, ClassDef>;
let classes: Map<string, ClassDef> = new Map();

/**
* Called when the parser comes across a (style) class definition
Expand All @@ -26,10 +26,10 @@ let classes = {} as Record<string, ClassDef>;
*/
export const addStyleClass = function (id: string, styleAttributes = '') {
// create a new style class object with this id
if (classes[id] === undefined) {
classes[id] = { id: id, styles: [], textStyles: [] }; // This is a classDef
if (!classes.has(id)) {
classes.set(id, { id: id, styles: [], textStyles: [] }); // This is a classDef
}
const foundClass = classes[id];
const foundClass = classes.get(id)!;
Yash-Singh1 marked this conversation as resolved.
Show resolved Hide resolved
if (styleAttributes !== undefined && styleAttributes !== null) {
styleAttributes.split(STYLECLASS_SEP).forEach((attrib) => {
// remove any trailing ;
Expand All @@ -54,7 +54,7 @@ export const addStyleClass = function (id: string, styleAttributes = '') {
* @param styles - the string with 1 or more style attributes (each separated by a comma)
*/
export const addStyle2Node = function (id: string, styles = '') {
const foundBlock = blockDatabase[id];
const foundBlock = blockDatabase.get(id)!;
if (styles !== undefined && styles !== null) {
foundBlock.styles = styles.split(STYLECLASS_SEP);
}
Expand All @@ -70,16 +70,16 @@ export const addStyle2Node = function (id: string, styles = '') {
*/
export const setCssClass = function (itemIds: string, cssClassName: string) {
itemIds.split(',').forEach(function (id: string) {
let foundBlock = blockDatabase[id];
let foundBlock = blockDatabase.get(id);
if (foundBlock === undefined) {
const trimmedId = id.trim();
blockDatabase[trimmedId] = { id: trimmedId, type: 'na', children: [] } as Block;
foundBlock = blockDatabase[trimmedId];
blockDatabase.set(trimmedId, { id: trimmedId, type: 'na', children: [] } as Block);
foundBlock = blockDatabase.get(trimmedId);
}
if (!foundBlock.classes) {
foundBlock.classes = [];
if (!foundBlock!.classes) {
foundBlock!.classes = [];
}
foundBlock.classes.push(cssClassName);
foundBlock!.classes.push(cssClassName);
});
};

Expand All @@ -104,12 +104,12 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block):
if (block.type === 'column-setting') {
parent.columns = block.columns || -1;
} else if (block.type === 'edge') {
if (edgeCount[block.id]) {
edgeCount[block.id]++;
if (edgeCount.has(block.id)) {
edgeCount.set(block.id, edgeCount.get(block.id)! + 1);
} else {
edgeCount[block.id] = 1;
edgeCount.set(block.id, 1);
}
block.id = edgeCount[block.id] + '-' + block.id;
block.id = edgeCount.get(block.id)! + '-' + block.id;
edgeList.push(block);
} else {
if (!block.label) {
Expand All @@ -120,16 +120,17 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block):
block.label = block.id;
}
}
const newBlock = !blockDatabase[block.id];
if (newBlock) {
blockDatabase[block.id] = block;
const isCreatingBlock = !blockDatabase.has(block.id);

if (isCreatingBlock) {
blockDatabase.set(block.id, block);
} else {
// Add newer relevant data to aggregated node
if (block.type !== 'na') {
blockDatabase[block.id].type = block.type;
blockDatabase.get(block.id)!.type = block.type;
}
if (block.label !== block.id) {
blockDatabase[block.id].label = block.label;
blockDatabase.get(block.id)!.label = block.label;
}
}

Expand All @@ -142,10 +143,10 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block):
for (let j = 0; j < w; j++) {
const newBlock = clone(block);
newBlock.id = newBlock.id + '-' + j;
blockDatabase[newBlock.id] = newBlock;
blockDatabase.set(newBlock.id, newBlock);
children.push(newBlock);
}
} else if (newBlock) {
} else if (isCreatingBlock) {
children.push(block);
}
}
Expand All @@ -160,12 +161,12 @@ const clear = (): void => {
log.debug('Clear called');
commonClear();
rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
blockDatabase = { root: rootBlock };
blockDatabase = new Map([['root', rootBlock]]);
blocks = [] as Block[];
classes = {} as Record<string, ClassDef>;
classes = new Map();

edgeList = [];
edgeCount = {};
edgeCount = new Map();
};

export function typeStr2Type(typeStr: string) {
Expand Down Expand Up @@ -241,7 +242,7 @@ const setHierarchy = (block: Block[]): void => {
};

const getColumns = (blockId: string): number => {
const block = blockDatabase[blockId];
const block = blockDatabase.get(blockId);
if (!block) {
return -1;
}
Expand All @@ -259,7 +260,7 @@ const getColumns = (blockId: string): number => {
* @returns
*/
const getBlocksFlat = () => {
return [...Object.values(blockDatabase)];
return [...blockDatabase.values()];
};
/**
* Returns the hierarchy of blocks
Expand All @@ -273,11 +274,11 @@ const getEdges = () => {
return edgeList;
};
const getBlock = (id: string) => {
return blockDatabase[id];
return blockDatabase.get(id);
};

const setBlock = (block: Block) => {
blockDatabase[block.id] = block;
blockDatabase.set(block.id, block);
};

const getLogger = () => console;
Expand Down
19 changes: 18 additions & 1 deletion packages/mermaid/src/diagrams/block/parser/block.spec.ts
Expand Up @@ -388,7 +388,7 @@ describe('Block diagram', function () {
const mc = blocks[0];
expect(mc.classes).toContain('black');
const classes = db.getClasses();
const black = classes.black;
const black = classes.get('black')!;
expect(black.id).toBe('black');
expect(black.styles[0]).toEqual('color:#ffffff');
});
Expand All @@ -406,4 +406,21 @@ columns 1
expect(B.styles).toContain('fill:#f9F');
});
});

describe('prototype properties', function () {
function validateProperty(prop: string) {
expect(() => block.parse(`block-beta\n${prop}`)).not.toThrow();
expect(() =>
block.parse(`block-beta\nA; classDef ${prop} color:#ffffff,fill:#000000; class A ${prop}`)
).not.toThrow();
}

it('should work with a __proto__ property', function () {
validateProperty('__proto__');
});

it('should work with a constructor property', function () {
validateProperty('constructor');
});
});
});