diff --git a/cypress/integration/rendering/quadrantChart.spec.js b/cypress/integration/rendering/quadrantChart.spec.js index 512a82468..64e198ac1 100644 --- a/cypress/integration/rendering/quadrantChart.spec.js +++ b/cypress/integration/rendering/quadrantChart.spec.js @@ -239,12 +239,12 @@ describe('Quadrant Chart', () => { quadrant-3 Re-evaluate quadrant-4 May be improved Campaign A: [0.3, 0.6] radius: 20 - Campaign B: [0.45, 0.23] color: #ff0000 - Campaign C: [0.57, 0.69] stroke-color: #ff00ff - Campaign D: [0.78, 0.34] stroke-width: 3px - Campaign E: [0.40, 0.34] radius: 20, color: #ff0000, stroke-color: #ff00ff, stroke-width: 3px - Campaign F: [0.35, 0.78] stroke-width: 3px, color: #ff0000, radius: 20, stroke-color: #ff00ff - Campaign G: [0.22, 0.22] stroke-width: 3px, color: #309708, radius: 20, stroke-color: #5060ff + Campaign B: [0.45, 0.23] color: #ff0000 + Campaign C: [0.57, 0.69] stroke-color: #ff00ff + Campaign D: [0.78, 0.34] stroke-width: 3px + Campaign E: [0.40, 0.34] radius: 20, color: #ff0000 , stroke-color : #ff00ff, stroke-width : 3px + Campaign F: [0.35, 0.78] stroke-width: 3px , color: #ff0000, radius: 20, stroke-color: #ff00ff + Campaign G: [0.22, 0.22] stroke-width: 3px , color: #309708 , radius : 20 , stroke-color: #5060ff Campaign H: [0.22, 0.44] `, {} diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts index 9da6026c5..4aaeb45b9 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts @@ -18,13 +18,8 @@ export interface StylesObject { strokeWidth?: string; } -export interface QuadrantPointInputType extends Point { +export interface QuadrantPointInputType extends Point, StylesObject { text: string; - className?: string; - radius?: number; - color?: string; - strokeColor?: string; - strokeWidth?: string; } export interface QuadrantTextType extends Point { @@ -36,12 +31,12 @@ export interface QuadrantTextType extends Point { rotation: number; } -export interface QuadrantPointType extends Point { +export interface QuadrantPointType + extends Point, + Pick { fill: string; radius: number; text: QuadrantTextType; - strokeColor: string; - strokeWidth: string; } export interface QuadrantQuadrantsType extends Point { @@ -132,7 +127,7 @@ export class QuadrantBuilder { private config: QuadrantBuilderConfig; private themeConfig: QuadrantBuilderThemeConfig; private data: QuadrantBuilderData; - private classes: StylesObject[] = []; + private classes: Record = {}; constructor() { this.config = this.getDefaultConfig(); @@ -219,10 +214,7 @@ export class QuadrantBuilder { } addClass(className: string, styles: StylesObject) { - this.classes.push({ - className, - ...styles, - }); + this.classes[className] = styles; } setConfig(config: Partial) { @@ -493,7 +485,7 @@ export class QuadrantBuilder { .range([quadrantHeight + quadrantTop, quadrantTop]); const points: QuadrantPointType[] = this.data.points.map((point) => { - const classStyles = this.classes.find((obj) => obj.className === point.className); + const classStyles = this.classes[point.className as keyof typeof this.classes]; if (classStyles !== undefined) { if (classStyles.color !== undefined) { point.color = classStyles.color; @@ -511,11 +503,8 @@ export class QuadrantBuilder { const props: QuadrantPointType = { x: xAxis(point.x), y: yAxis(point.y), - fill: - point.color !== undefined && point.color !== '' - ? point.color - : this.themeConfig.quadrantPointFill, - radius: point.radius !== undefined && point.radius ? point.radius : this.config.pointRadius, + fill: point.color || this.themeConfig.quadrantPointFill, + radius: point.radius || this.config.pointRadius, text: { text: point.text, fill: this.themeConfig.quadrantPointTextFill, diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.spec.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.spec.ts index a0d0f65a7..9a49a067f 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.spec.ts +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.spec.ts @@ -29,22 +29,22 @@ describe('quadrant unit tests', () => { it('should throw an error for unacceptable style value', () => { let styles: string[] = ['radius: f']; expect(() => quadrantDb.parseStyles(styles)).toThrowError( - 'value for radius f is unvalid, requires a number' + 'value for radius f is invalid, please use a valid number' ); styles = ['color: ffaa']; expect(() => quadrantDb.parseStyles(styles)).toThrowError( - 'value for color ffaa is unvalid, requires a valid hex code' + 'value for color ffaa is invalid, please use a valid hex code' ); styles = ['stroke-color: #f677779']; expect(() => quadrantDb.parseStyles(styles)).toThrowError( - 'value for stroke-color #f677779 is unvalid, requires a valid hex code' + 'value for stroke-color #f677779 is invalid, please use a valid hex code' ); styles = ['stroke-width: 30']; expect(() => quadrantDb.parseStyles(styles)).toThrowError( - 'value for stroke-width 30 is unvalid, requires a valid number of pixels (eg. 10px)' + 'value for stroke-width 30 is invalid, please use a valid number of pixels (eg. 10px)' ); }); }); diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts index 9d8dbe732..e3da724f8 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts @@ -11,6 +11,12 @@ import { } from '../common/commonDb.js'; import type { StylesObject } from './quadrantBuilder.js'; import { QuadrantBuilder } from './quadrantBuilder.js'; +import { + validateHexCode, + validateSizeInPixels, + validateNumber, + InvalidStyleError, +} from './utils.js'; const config = getConfig(); @@ -56,36 +62,30 @@ function setYAxisBottomText(textObj: LexTextObj) { function parseStyles(styles: string[]): StylesObject { const stylesObject: StylesObject = {}; - if (styles.length !== 0) { - for (const item of styles) { - const style = item.trim().split(/\s*:\s*/); - if (style[0] == 'radius') { - if (!/^\d+$/.test(style[1])) { - throw new Error(`value for radius ${style[1]} is unvalid, requires a number`); - } - stylesObject.radius = parseInt(style[1]); - } else if (style[0] == 'color') { - if (!/^#?([\dA-Fa-f]{6}|[\dA-Fa-f]{3})$/.test(style[1])) { - throw new Error(`value for color ${style[1]} is unvalid, requires a valid hex code`); - } - stylesObject.color = style[1]; - } else if (style[0] == 'stroke-color') { - if (!/^#?([\dA-Fa-f]{6}|[\dA-Fa-f]{3})$/.test(style[1])) { - throw new Error( - `value for stroke-color ${style[1]} is unvalid, requires a valid hex code` - ); - } - stylesObject.strokeColor = style[1]; - } else if (style[0] == 'stroke-width') { - if (!/^\d+px$/.test(style[1])) { - throw new Error( - `value for stroke-width ${style[1]} is unvalid, requires a valid number of pixels (eg. 10px)` - ); - } - stylesObject.strokeWidth = style[1]; - } else { - throw new Error(`stlye named ${style[0]} is unacceptable`); + for (const style of styles) { + const [key, value] = style.trim().split(/\s*:\s*/); + if (key == 'radius') { + if (validateNumber(value)) { + throw new InvalidStyleError(key, value, 'number'); } + stylesObject.radius = parseInt(value); + } else if (key == 'color') { + if (validateHexCode(value)) { + throw new InvalidStyleError(key, value, 'hex code'); + } + stylesObject.color = value; + } else if (key == 'stroke-color') { + if (validateHexCode(value)) { + throw new InvalidStyleError(key, value, 'hex code'); + } + stylesObject.strokeColor = value; + } else if (key == 'stroke-width') { + if (validateSizeInPixels(value)) { + throw new InvalidStyleError(key, value, 'number of pixels (eg. 10px)'); + } + stylesObject.strokeWidth = value; + } else { + throw new Error(`stlye named ${key} is unacceptable`); } } return stylesObject; @@ -97,12 +97,9 @@ function addPoint(textObj: LexTextObj, className: string, x: number, y: number, { x, y, - className: className, text: textSanitizer(textObj.text), - radius: stylesObject.radius, - color: stylesObject.color, - strokeColor: stylesObject.strokeColor, - strokeWidth: stylesObject.strokeWidth, + className, + ...stylesObject, }, ]); } diff --git a/packages/mermaid/src/diagrams/quadrant-chart/utils.ts b/packages/mermaid/src/diagrams/quadrant-chart/utils.ts new file mode 100644 index 000000000..fca3c8f9a --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/utils.ts @@ -0,0 +1,20 @@ +class InvalidStyleError extends Error { + constructor(style: string, value: string, type: string) { + super(`value for ${style} ${value} is invalid, please use a valid ${type}`); + this.name = 'InvalidStyleError'; + } +} + +function validateHexCode(value: string): boolean { + return !/^#?([\dA-Fa-f]{6}|[\dA-Fa-f]{3})$/.test(value); +} + +function validateNumber(value: string): boolean { + return !/^\d+$/.test(value); +} + +function validateSizeInPixels(value: string): boolean { + return !/^\d+px$/.test(value); +} + +export { validateHexCode, validateNumber, validateSizeInPixels, InvalidStyleError };