#5237 making styles take preceedence and adding test

This commit is contained in:
Knut Sveidqvist
2024-06-18 11:15:59 +02:00
parent a6f3316ddb
commit 83f2663f68
7 changed files with 203 additions and 64 deletions

View File

@@ -110,6 +110,7 @@ strikethrough
stringifying
struct
STYLECLASS
STYLEDEF
STYLEOPTS
subcomponent
subcomponents

View File

@@ -558,6 +558,29 @@ stateDiagram-v2
{ logLevel: 0, fontFamily: 'courier' }
);
});
it(' can have styles applied ', () => {
imgSnapshotTest(
`
stateDiagram-v2
AState
style AState fill:#636,border:1px solid red,color:white;
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
it(' should let styles take preceedence over classes', () => {
imgSnapshotTest(
`
stateDiagram-v2
AState: Should NOT be white
BState
classDef exampleStyleClass fill:#fff,color: blue;
class AState,BState exampleStyleClass
style AState fill:#636,border:1px solid red,color:white;
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
});
it('1433: should render a simple state diagram with a title', () => {
imgSnapshotTest(

View File

@@ -75,12 +75,127 @@
</style>
</head>
<body>
<pre id="diagram" class="mermaid">
flowchart LR
<h4>Case 1</h4>
<div class="flex">
<pre id="diagram" class="mermaid">
stateDiagram-v2
AState: Should NOT be white
BState
classDef exampleStyleClass fill:#fff,color: blue;
class AState,BState exampleStyleClass
style AState fill:#636,border:1px solid red,color:white;
</pre>
<pre id="diagram" class="mermaid">
%%{init: {"look": "classic"} }%%
stateDiagram-v2
AState: Should NOT be white
BState
classDef exampleStyleClass fill:#fff,color: blue;
class AState,BState exampleStyleClass
style AState fill:#636,border:1px solid red,color:white;
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram-v2
Apa --AA--> C
</pre
>
classDef exampleStyleClass background:#bbb,border:1px solid red;
a --> b
class a exampleStyleClass
%% a:::exampleStyleClass
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram
direction TB
accTitle: This is the accessible title
accDescr: This is an accessible description
classDef notMoving fill:white
classDef movement font-style:italic;
classDef badBadEvent fill:#f00,color:white,font-weight:bold,stroke-width:2px,stroke:yellow
[*] --> Still:::notMoving
Still --> [*]
Still --> Moving:::movement
Moving --> Still
Moving --> Crash:::movement
Crash:::badBadEvent --> [*]
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram-v2
MyState
note left of MyState : I am a leftie
note right of MyState : I am a rightie
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram
%% direction LR
state C0 {
A0 --> B0
}
C0 --> Apa0
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram
direction LR
state C1 {
A1 --> B1
}
C1 --> Apa1
</pre>
</div>
<h4>Case 2</h4>
<div class="flex">
<pre id="diagram" class="mermaid2">
stateDiagram
direction LR
state Gorilla0 {
state Apa0 {
A0 --> B0
}
}
Apa --> Gorilla0:Label
A0 --> C0
%% C1: "`This is C`"
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram
direction LR
state Apa1 {
A1
}
Apa11 --> Apa1
A1 --> C1
%% C1: "`This is C`"
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram
[*] --> Level1
state Level1 {
[*] --> Level2
state Level2 {
[*] --> level2
level2 --> Level3
state Level3 {
[*] --> level3
level3 --> [*]
}
}
}
</pre>
</div>
<pre id="diagram" class="mermaid2">
flowchart LR
subgraph Apa["Apa"]
@@ -127,20 +242,7 @@ Apa --> C
A --> B & C["C"]
</pre
>
<pre id="diagram" class="mermaid">
stateDiagram
direction LR
state Gorilla0 {
state Apa0 {
A0 --> B0
}
}
Apa0 --> C0
A0 --> C0
C1: "`This is C`"
</pre
>
<pre id="diagram" class="mermaid2">
flowchart LR
subgraph Gorilla
@@ -180,7 +282,7 @@ stateDiagram
</pre
>
<pre id="diagram" class="mermaid">
<pre id="diagram" class="mermaid2">
flowchart LR
Apa --Hello--> C
@@ -318,7 +420,7 @@ stateDiagram-v2
mermaid.initialize({
// theme: 'base',
// handdrawnSeed: 12,
// look: 'handdrawn',
look: 'handdrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',

View File

@@ -221,41 +221,46 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
describe('style statement for a state (style)', () => {
describe('defining (style)', () => {
it('has "style" as a keyword, an id, and can set a css style attribute', function () {
stateDiagram.parser.parse(`
stateDiagram-v2
style id1 background:#bbb;`);
stateDiagram.parser.parse(`stateDiagram-v2
id1
style id1 background:#bbb`);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const data4Layout = stateDiagram.parser.yy.getData();
// const styleClasses = stateDb.getClasses();
// expect(styleClasses.get('exampleClass').styles.length).toEqual(1);
// expect(styleClasses.get('exampleClass').styles[0]).toEqual('background:#bbb');
expect(data4Layout.nodes[0].cssStyles).toEqual(['background:#bbb']);
});
it('has "style" as a keyword, an id, and can set a css style attribute', function () {
stateDiagram.parser.parse(`stateDiagram-v2
id1
id2
style id1,id2 background:#bbb`);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const data4Layout = stateDiagram.parser.yy.getData();
expect(data4Layout.nodes[0].cssStyles).toEqual(['background:#bbb']);
expect(data4Layout.nodes[1].cssStyles).toEqual(['background:#bbb']);
});
it('has handles multiple ids', function () {
stateDiagram.parser.parse(`
stateDiagram-v2
style id1,id2 background:#bbb;`);
it('can define multiple attributes separated by commas', function () {
stateDiagram.parser.parse(`stateDiagram-v2
id1
id2
style id1,id2 background:#bbb, font-weight:bold, font-style:italic;`);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const data4Layout = stateDiagram.parser.yy.getData();
// const styleClasses = stateDb.getClasses();
// expect(styleClasses.get('exampleClass').styles.length).toEqual(1);
// expect(styleClasses.get('exampleClass').styles[0]).toEqual('background:#bbb');
expect(data4Layout.nodes[0].cssStyles).toEqual([
'background:#bbb',
'font-weight:bold',
'font-style:italic',
]);
expect(data4Layout.nodes[1].cssStyles).toEqual([
'background:#bbb',
'font-weight:bold',
'font-style:italic',
]);
});
// it('can define multiple attributes separated by commas', function () {
// stateDiagram.parser.parse(
// 'stateDiagram-v2\n classDef exampleClass background:#bbb, font-weight:bold, font-style:italic;'
// );
// stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
// const styleClasses = stateDb.getClasses();
// expect(styleClasses.get('exampleClass').styles.length).toEqual(3);
// expect(styleClasses.get('exampleClass').styles[0]).toEqual('background:#bbb');
// expect(styleClasses.get('exampleClass').styles[1]).toEqual('font-weight:bold');
// expect(styleClasses.get('exampleClass').styles[2]).toEqual('font-style:italic');
// });
});
});
});

View File

@@ -202,13 +202,13 @@ const extract = (_doc) => {
ids.forEach((id) => {
const state = getState(id);
if (state !== undefined) {
state.styles = styles;
state.styles = styles.map((s) => s.replace(/;/g, '')?.trim());
}
});
}
break;
case STMT_APPLYCLASS:
setStyle(item.id.trim(), item.styleClass);
setCssClass(item.id.trim(), item.styleClass);
break;
}
});

View File

@@ -198,7 +198,16 @@ export const createText = (
} = {},
config: MermaidConfig
) => {
log.info('createText', text, style, isTitle, classes, useHtmlLabels, isNode, addSvgBackground);
log.info(
'IPI createText',
text,
style,
isTitle,
classes,
useHtmlLabels,
isNode,
addSvgBackground
);
if (useHtmlLabels) {
// TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?

View File

@@ -1,6 +1,5 @@
import { getConfig } from '$root/diagram-api/diagramAPI.js';
import type { Node } from '$root/rendering-util/types.d.ts';
import styles from '../../../../dist/diagrams/packet/styles';
// Striped fill like start or fork nodes in state diagrams
export const solidStateFill = (color: string) => {
@@ -22,31 +21,33 @@ export const compileStyles = (node: Node) => {
// node.cssStyles is an array of styles directly set on the node
// concat the arrays and remove duplicates such that the values from node.cssStyles are used if there are duplicates
return [...(node.cssCompiledStyles || []), ...(node.cssStyles || [])];
const stylesMap = styles2Map([...(node.cssCompiledStyles || []), ...(node.cssStyles || [])]);
return { stylesMap, stylesArray: [...stylesMap] };
};
export const styles2Map = (styles: string[]) => {
const styleMap = new Map();
const styleMap = new Map<string, string>();
styles.forEach((style) => {
const [key, value] = style.split(':');
styleMap.set(key.trim(), value.trim());
styleMap.set(key.trim(), value?.trim());
});
return styleMap;
};
export const styles2String = (node: Node) => {
const styles = compileStyles(node);
const { stylesArray } = compileStyles(node);
const labelStyles: string[] = [];
const nodeStyles: string[] = [];
styles.forEach((style) => {
const [key, value] = style.split(':');
stylesArray.forEach((style) => {
const key = style[0];
if (key === 'color') {
labelStyles.push(style);
labelStyles.push(style.join(':') + ' !important');
} else {
nodeStyles.push(style);
nodeStyles.push(style.join(':') + ' !important');
}
});
return { labelStyles: labelStyles.join(';'), nodeStyles: nodeStyles.join(';') };
};
@@ -55,18 +56,16 @@ export const styles2String = (node: Node) => {
export const userNodeOverrides = (node: Node, options: any) => {
const { themeVariables, handdrawnSeed } = getConfig();
const { nodeBorder, mainBkg } = themeVariables;
const styles = compileStyles(node);
const { stylesArray: styles, stylesMap } = compileStyles(node);
// index the style array to a map object
const styleMap = styles2Map(styles);
const result = Object.assign(
{
roughness: 0.7,
fill: styleMap.get('fill') || mainBkg,
fill: stylesMap.get('fill') || mainBkg,
fillStyle: 'hachure', // solid fill
fillWeight: 3.5,
stroke: styleMap.get('stroke') || nodeBorder,
stroke: stylesMap.get('stroke') || nodeBorder,
seed: handdrawnSeed,
strokeWidth: 1.3,
},