mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-28 07:03:17 +08:00
Adding support for compound blocks
This commit is contained in:
parent
13114ebaa1
commit
b9531d56c4
@ -18,7 +18,7 @@ import {
|
|||||||
|
|
||||||
// TODO: Convert to generic TreeNode type? Convert to class?
|
// TODO: Convert to generic TreeNode type? Convert to class?
|
||||||
export interface Block {
|
export interface Block {
|
||||||
ID?: string;
|
ID: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
parent?: Block;
|
parent?: Block;
|
||||||
children?: Block[];
|
children?: Block[];
|
||||||
@ -32,16 +32,21 @@ export interface Link {
|
|||||||
|
|
||||||
let rootBlocks: Block[] = [];
|
let rootBlocks: Block[] = [];
|
||||||
let blocks: Block[] = [];
|
let blocks: Block[] = [];
|
||||||
let links: Link[] = [];
|
const links: Link[] = [];
|
||||||
|
let rootBlock = { ID: 'root', children: [], columns: -1 } as Block;
|
||||||
|
let currentBlock: Block | undefined;
|
||||||
|
|
||||||
const clear = (): void => {
|
const clear = (): void => {
|
||||||
|
rootBlocks = [];
|
||||||
blocks = [];
|
blocks = [];
|
||||||
commonClear();
|
commonClear();
|
||||||
|
rootBlock = { ID: 'root', children: [], columns: -1 };
|
||||||
|
currentBlock = rootBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
type IAddBlock = (block: Block) => Block;
|
type IAddBlock = (block: Block) => Block;
|
||||||
const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
|
const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
|
||||||
if(parent) {
|
if (parent) {
|
||||||
parent.children ??= [];
|
parent.children ??= [];
|
||||||
parent.children.push(block);
|
parent.children.push(block);
|
||||||
} else {
|
} else {
|
||||||
@ -57,14 +62,44 @@ const addLink: IAddLink = (link: Link): Link => {
|
|||||||
return link;
|
return link;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ISetColumns = (columnsStr: string) => void;
|
||||||
|
const setColumns = (columnsStr: string): void => {
|
||||||
|
const columns = columnsStr === 'auto' ? -1 : parseInt(columnsStr);
|
||||||
|
currentBlock!.columns = columns;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getBlock = (id: string, blocks: Block[]): Block | undefined => {
|
||||||
|
for (const block of blocks) {
|
||||||
|
if (block.ID === id) {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
if (block.children) {
|
||||||
|
const foundBlock = getBlock(id, block.children);
|
||||||
|
if (foundBlock) {
|
||||||
|
return foundBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
type IGetColumns = (blockID: string) => number;
|
||||||
|
const getColumns = (blockID: string): number => {
|
||||||
|
const blocks = [rootBlock];
|
||||||
|
const block = getBlock(blockID, blocks);
|
||||||
|
if (!block) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return block.columns || -1;
|
||||||
|
};
|
||||||
|
|
||||||
type IGetBlocks = () => Block[];
|
type IGetBlocks = () => Block[];
|
||||||
const getBlocks:IGetBlocks = () => blocks;
|
const getBlocks: IGetBlocks = () => blocks;
|
||||||
|
|
||||||
type IGetLinks = () => Link[];
|
type IGetLinks = () => Link[];
|
||||||
const getLinks:IGetLinks = () => links;
|
const getLinks: IGetLinks = () => links;
|
||||||
|
|
||||||
type IGetLogger = () => Console;
|
type IGetLogger = () => Console;
|
||||||
const getLogger:IGetLogger = () => console;
|
const getLogger: IGetLogger = () => console;
|
||||||
|
|
||||||
export interface BlockDB extends DiagramDB {
|
export interface BlockDB extends DiagramDB {
|
||||||
clear: () => void;
|
clear: () => void;
|
||||||
@ -74,6 +109,8 @@ export interface BlockDB extends DiagramDB {
|
|||||||
getLogger: IGetLogger;
|
getLogger: IGetLogger;
|
||||||
getBlocks: IGetBlocks;
|
getBlocks: IGetBlocks;
|
||||||
getLinks: IGetLinks;
|
getLinks: IGetLinks;
|
||||||
|
setColumns: ISetColumns;
|
||||||
|
getColumns: IGetColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
const db: BlockDB = {
|
const db: BlockDB = {
|
||||||
@ -89,6 +126,8 @@ const db: BlockDB = {
|
|||||||
// setAccDescription,
|
// setAccDescription,
|
||||||
// getDiagramTitle,
|
// getDiagramTitle,
|
||||||
// setDiagramTitle,
|
// setDiagramTitle,
|
||||||
|
setColumns,
|
||||||
|
getColumns,
|
||||||
clear,
|
clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
%x string
|
%x string
|
||||||
%x md_string
|
%x md_string
|
||||||
%x NODE
|
%x NODE
|
||||||
%options easy_keword_rules
|
|
||||||
|
|
||||||
|
|
||||||
// as per section 6.1 of RFC 2234 [2]
|
// as per section 6.1 of RFC 2234 [2]
|
||||||
@ -28,11 +27,15 @@ CRLF \u000D\u000A
|
|||||||
%%
|
%%
|
||||||
|
|
||||||
"block-beta" { return 'BLOCK_DIAGRAM_KEY'; }
|
"block-beta" { return 'BLOCK_DIAGRAM_KEY'; }
|
||||||
|
"block"\s+ { yy.getLogger().info('Found space-block'); return 'block';}
|
||||||
|
"block"\n+ { yy.getLogger().info('Found nl-block'); return 'block';}
|
||||||
// \s*\%\%.* { yy.getLogger().info('Found comment',yytext); }
|
// \s*\%\%.* { yy.getLogger().info('Found comment',yytext); }
|
||||||
[\s]+ { yy.getLogger().info('.', yytext); /* skip all whitespace */ }
|
[\s]+ { yy.getLogger().info('.', yytext); /* skip all whitespace */ }
|
||||||
[\n]+ {yy.getLogger().info('_', yytext); /* skip all whitespace */ }
|
[\n]+ {yy.getLogger().info('_', yytext); /* skip all whitespace */ }
|
||||||
// [\n] return 'NL';
|
// [\n] return 'NL';
|
||||||
<INITIAL>({CRLF}|{LF}) { return 'NL' }
|
<INITIAL>({CRLF}|{LF}) { return 'NL' }
|
||||||
|
"columns"\s+"auto" { yytext=-1; return 'COLUMNS'; }
|
||||||
|
"columns"\s+[\d]+ { yytext = yytext.replace(/columns\s+/,''); yy.getLogger().info('COLUMNS (LEX)', yytext); return 'COLUMNS'; }
|
||||||
["][`] { this.pushState("md_string");}
|
["][`] { this.pushState("md_string");}
|
||||||
<md_string>[^`"]+ { return "MD_STR";}
|
<md_string>[^`"]+ { return "MD_STR";}
|
||||||
<md_string>[`]["] { this.popState();}
|
<md_string>[`]["] { this.popState();}
|
||||||
@ -114,6 +117,7 @@ accDescr\s*"{"\s* { this.pushState("acc_descr_mul
|
|||||||
|
|
||||||
/lex
|
/lex
|
||||||
|
|
||||||
|
%left '^'
|
||||||
%start start
|
%start start
|
||||||
|
|
||||||
%% // language grammar
|
%% // language grammar
|
||||||
@ -133,12 +137,8 @@ seperator
|
|||||||
{yy.getLogger().info('Rule: seperator (EOF) ');}
|
{yy.getLogger().info('Rule: seperator (EOF) ');}
|
||||||
;
|
;
|
||||||
|
|
||||||
start: BLOCK_DIAGRAM_KEY document;
|
start: BLOCK_DIAGRAM_KEY document EOF;
|
||||||
|
|
||||||
blockDiagram
|
|
||||||
: blockDiagram document { return yy; }
|
|
||||||
| blockDiagram NL document { return yy; }
|
|
||||||
;
|
|
||||||
|
|
||||||
stop
|
stop
|
||||||
: NL {yy.getLogger().info('Stop NL ');}
|
: NL {yy.getLogger().info('Stop NL ');}
|
||||||
@ -149,8 +149,8 @@ stop
|
|||||||
;
|
;
|
||||||
|
|
||||||
document
|
document
|
||||||
: document statement
|
: statement { yy.getLogger().info("Rule: statement: ", $1);}
|
||||||
| statement
|
| statement document { yy.getLogger().info("Rule: document statement: ", $1);}
|
||||||
;
|
;
|
||||||
|
|
||||||
link
|
link
|
||||||
@ -162,6 +162,8 @@ link
|
|||||||
|
|
||||||
statement
|
statement
|
||||||
: nodeStatement
|
: nodeStatement
|
||||||
|
| columnsStatement
|
||||||
|
| blockStatement
|
||||||
// SPACELIST node { yy.getLogger().info('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type); }
|
// SPACELIST node { yy.getLogger().info('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type); }
|
||||||
// | SPACELIST ICON { yy.getLogger().info('Icon: ',$2);yy.decorateNode({icon: $2}); }
|
// | SPACELIST ICON { yy.getLogger().info('Icon: ',$2);yy.decorateNode({icon: $2}); }
|
||||||
// | SPACELIST CLASS { yy.decorateNode({class: $2}); }
|
// | SPACELIST CLASS { yy.decorateNode({class: $2}); }
|
||||||
@ -171,12 +173,22 @@ statement
|
|||||||
// | ICON { yy.decorateNode({icon: $1}); }
|
// | ICON { yy.decorateNode({icon: $1}); }
|
||||||
// | CLASS { yy.decorateNode({class: $1}); }
|
// | CLASS { yy.decorateNode({class: $1}); }
|
||||||
// // | SPACELIST
|
// // | SPACELIST
|
||||||
| EOF
|
|
||||||
;
|
;
|
||||||
|
|
||||||
nodeStatement: nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) ');}
|
nodeStatement
|
||||||
|node { yy.getLogger().info('Rule: nodeStatement (node) ');}
|
: nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) ');}
|
||||||
;
|
| node { yy.getLogger().info('Rule: nodeStatement (node) ', $1);}
|
||||||
|
;
|
||||||
|
|
||||||
|
columnsStatement
|
||||||
|
: COLUMNS { yy.getLogger().info("COLUMNS: ", $1);yy.setColumns($1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
blockStatement
|
||||||
|
: block document end { yy.getLogger().info('Rule: blockStatement : ', $1); }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
node
|
node
|
||||||
: NODE_ID
|
: NODE_ID
|
||||||
|
@ -55,19 +55,38 @@ describe('Block diagram', function () {
|
|||||||
|
|
||||||
block.parse(str);
|
block.parse(str);
|
||||||
});
|
});
|
||||||
it.skip('a diagram with column statements', async () => {
|
it('a diagram with column statements', async () => {
|
||||||
const str = `block-beta
|
const str = `block-beta
|
||||||
columns 1
|
columns 2
|
||||||
block1["Block 1"]
|
block1["Block 1"]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
block.parse(str);
|
block.parse(str);
|
||||||
|
expect(db.getColumns('root')).toBe(2);
|
||||||
|
// Todo: DB check that the we have one block and that the root block has one column
|
||||||
|
});
|
||||||
|
it('a diagram withput column statements', async () => {
|
||||||
|
const str = `block-beta
|
||||||
|
block1["Block 1"]
|
||||||
|
`;
|
||||||
|
|
||||||
|
block.parse(str);
|
||||||
|
expect(db.getColumns('root')).toBe(-1);
|
||||||
|
// Todo: DB check that the we have one block and that the root block has one column
|
||||||
|
});
|
||||||
|
it('a diagram with auto column statements', async () => {
|
||||||
|
const str = `block-beta
|
||||||
|
columns auto
|
||||||
|
block1["Block 1"]
|
||||||
|
`;
|
||||||
|
|
||||||
|
block.parse(str);
|
||||||
|
expect(db.getColumns('root')).toBe(-1);
|
||||||
// Todo: DB check that the we have one block and that the root block has one column
|
// Todo: DB check that the we have one block and that the root block has one column
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('blocks next to each other', async () => {
|
it('blocks next to each other', async () => {
|
||||||
const str = `block-beta
|
const str = `block-beta
|
||||||
block
|
|
||||||
columns 2
|
columns 2
|
||||||
block1["Block 1"]
|
block1["Block 1"]
|
||||||
block2["Block 2"]
|
block2["Block 2"]
|
||||||
@ -78,9 +97,8 @@ describe('Block diagram', function () {
|
|||||||
// Todo: DB check that the we have two blocks and that the root block has two columns
|
// Todo: DB check that the we have two blocks and that the root block has two columns
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('blocks on top of each other', async () => {
|
it('blocks on top of each other', async () => {
|
||||||
const str = `block-beta
|
const str = `block-beta
|
||||||
block
|
|
||||||
columns 1
|
columns 1
|
||||||
block1["Block 1"]
|
block1["Block 1"]
|
||||||
block2["Block 2"]
|
block2["Block 2"]
|
||||||
@ -91,13 +109,11 @@ describe('Block diagram', function () {
|
|||||||
// Todo: DB check that the we have two blocks and that the root block has one column
|
// Todo: DB check that the we have two blocks and that the root block has one column
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('compound blocks', async () => {
|
it('compound blocks', async () => {
|
||||||
const str = `block
|
const str = `block-beta
|
||||||
block
|
block
|
||||||
columns 2
|
aBlock["Block"]
|
||||||
block2["Block 2"]
|
end
|
||||||
block3["Block 3"]
|
|
||||||
end %% End the compound block
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
block.parse(str);
|
block.parse(str);
|
||||||
@ -121,7 +137,7 @@ describe('Block diagram', function () {
|
|||||||
columns 2
|
columns 2
|
||||||
block2["Block 2"]
|
block2["Block 2"]
|
||||||
block3["Block 3"]
|
block3["Block 3"]
|
||||||
end %% End the compound block
|
end
|
||||||
`;
|
`;
|
||||||
|
|
||||||
block.parse(str);
|
block.parse(str);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user