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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(er): add entity name alias #4758

Merged
merged 10 commits into from Aug 26, 2023
17 changes: 17 additions & 0 deletions cypress/integration/rendering/erDiagram.spec.js
Expand Up @@ -305,4 +305,21 @@ ORDER ||--|{ LINE-ITEM : contains
{}
);
});

it('should render entities with entity name aliases', () => {
imgSnapshotTest(
`
erDiagram
p[Person] {
varchar(64) firstName
varchar(64) lastName
}
c["Customer Account"] {
varchar(128) email
}
p ||--o| c : has
`,
{ logLevel: 1 }
);
});
});
14 changes: 14 additions & 0 deletions demos/er.html
Expand Up @@ -110,6 +110,20 @@
}
MANUFACTURER only one to zero or more CAR : makes
</pre>
<hr />

<pre class="mermaid">
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
</pre>
<hr />

<script type="module">
import mermaid from './mermaid.esm.mjs';
Expand Down
28 changes: 28 additions & 0 deletions docs/syntax/entityRelationshipDiagram.md
Expand Up @@ -198,6 +198,34 @@ erDiagram

The `type` values must begin with an alphabetic character and may contain digits, hyphens, underscores, parentheses and square brackets. The `name` values follow a similar format to `type`, but may start with an asterisk as another option to indicate an attribute is a primary key. Other than that, there are no restrictions, and there is no implicit set of valid data types.

### Entity Name Aliases (v\<MERMAID_RELEASE_VERSION>+)

An alias can be added to an entity using square brackets. If provided, the alias will be showed in the diagram instead of the entity name.

```mermaid-example
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
```

```mermaid
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
```

#### Attribute Keys and Comments

Attributes may also have a `key` or comment defined. Keys can be `PK`, `FK` or `UK`, for Primary Key, Foreign Key or Unique Key. To specify multiple key constraints on a single attribute, separate them with a comma (e.g., `PK, FK`).. A `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them.
Expand Down
7 changes: 5 additions & 2 deletions packages/mermaid/src/diagrams/er/erDb.js
Expand Up @@ -32,10 +32,13 @@ export const parseDirective = function (statement, context, type) {
mermaidAPI.parseDirective(this, statement, context, type);
};

const addEntity = function (name) {
const addEntity = function (name, alias = undefined) {
if (entities[name] === undefined) {
entities[name] = { attributes: [] };
entities[name] = { attributes: [], alias: alias };
log.info('Added new entity :', name);
} else if (entities[name] && !entities[name].alias && alias) {
entities[name].alias = alias;
log.info(`Add alias '${alias}' to entity '${name}'`);
}

return entities[name];
Expand Down
2 changes: 1 addition & 1 deletion packages/mermaid/src/diagrams/er/erRenderer.js
Expand Up @@ -326,7 +326,7 @@ const drawEntities = function (svgNode, entities, graph) {
.style('text-anchor', 'middle')
.style('font-family', getConfig().fontFamily)
.style('font-size', conf.fontSize + 'px')
.text(entityName);
.text(entities[entityName].alias ?? entityName);

const { width: entityWidth, height: entityHeight } = drawAttributes(
groupNode,
Expand Down
12 changes: 9 additions & 3 deletions packages/mermaid/src/diagrams/er/parser/erDiagram.jison
Expand Up @@ -35,6 +35,8 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
<block>[\n]+ /* nothing */
<block>"}" { this.popState(); return 'BLOCK_STOP'; }
<block>. return yytext[0];
"[" return 'SQS';
"]" return 'SQE';

"one or zero" return 'ZERO_OR_ONE';
"one or more" return 'ONE_OR_MORE';
Expand Down Expand Up @@ -102,17 +104,21 @@ statement
yy.addEntity($1);
yy.addEntity($3);
yy.addRelationship($1, $5, $3, $2);
/*console.log($1 + $2 + $3 + ':' + $5);*/
}
| entityName BLOCK_START attributes BLOCK_STOP
{
/* console.log('detected block'); */
yy.addEntity($1);
yy.addAttributes($1, $3);
/* console.log('handled block'); */
}
| entityName BLOCK_START BLOCK_STOP { yy.addEntity($1); }
| entityName { yy.addEntity($1); }
| entityName SQS entityName SQE BLOCK_START attributes BLOCK_STOP
{
yy.addEntity($1, $3);
yy.addAttributes($1, $6);
}
| entityName SQS entityName SQE BLOCK_START BLOCK_STOP { yy.addEntity($1, $3); }
| entityName SQS entityName SQE { yy.addEntity($1, $3); }
| title title_value { $$=$2.trim();yy.setAccTitle($$); }
| acc_title acc_title_value { $$=$2.trim();yy.setAccTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
Expand Down
37 changes: 37 additions & 0 deletions packages/mermaid/src/diagrams/er/parser/erDiagram.spec.js
Expand Up @@ -133,6 +133,43 @@ describe('when parsing ER diagram it...', function () {
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(hyphensUnderscore)).toBe(true);
});

it('can have an alias', function () {
const entity = 'foo';
const alias = 'bar';
erDiagram.parser.parse(`erDiagram\n${entity}["${alias}"]\n`);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(entity)).toBe(true);
expect(entities[entity].alias).toBe(alias);
});

it('can have an alias even if the relationship is defined before class', function () {
const firstEntity = 'foo';
const secondEntity = 'bar';
const alias = 'batman';
erDiagram.parser.parse(
`erDiagram\n${firstEntity} ||--o| ${secondEntity} : rel\nclass ${firstEntity}["${alias}"]\n`
);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(firstEntity)).toBe(true);
expect(entities.hasOwnProperty(secondEntity)).toBe(true);
expect(entities[firstEntity].alias).toBe(alias);
expect(entities[secondEntity].alias).toBeUndefined();
});

it('can have an alias even if the relationship is defined after class', function () {
const firstEntity = 'foo';
const secondEntity = 'bar';
const alias = 'batman';
erDiagram.parser.parse(
`erDiagram\nclass ${firstEntity}["${alias}"]\n${firstEntity} ||--o| ${secondEntity} : rel\n`
);
const entities = erDb.getEntities();
expect(entities.hasOwnProperty(firstEntity)).toBe(true);
expect(entities.hasOwnProperty(secondEntity)).toBe(true);
expect(entities[firstEntity].alias).toBe(alias);
expect(entities[secondEntity].alias).toBeUndefined();
});
});

describe('attribute name', () => {
Expand Down
16 changes: 16 additions & 0 deletions packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md
Expand Up @@ -144,6 +144,22 @@ erDiagram

The `type` values must begin with an alphabetic character and may contain digits, hyphens, underscores, parentheses and square brackets. The `name` values follow a similar format to `type`, but may start with an asterisk as another option to indicate an attribute is a primary key. Other than that, there are no restrictions, and there is no implicit set of valid data types.

### Entity Name Aliases (v<MERMAID_RELEASE_VERSION>+)

An alias can be added to an entity using square brackets. If provided, the alias will be showed in the diagram instead of the entity name.

```mermaid-example
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
```

#### Attribute Keys and Comments

Attributes may also have a `key` or comment defined. Keys can be `PK`, `FK` or `UK`, for Primary Key, Foreign Key or Unique Key. To specify multiple key constraints on a single attribute, separate them with a comma (e.g., `PK, FK`).. A `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them.
Expand Down