diff --git a/demos/quadrantchart.html b/demos/quadrantchart.html index 3a340f76a..63a279bba 100644 --- a/demos/quadrantchart.html +++ b/demos/quadrantchart.html @@ -27,7 +27,7 @@
- %%{init: {"quadrantChart": {"xAxisPosition": "bottom"} } }%% + %%{init: {"quadrantChart": {"xAxisPosition": "bottom", "chartWidth": 600, "chartHeight": 600} } }%% quadrantChart x-axis "Completeness of Vision ❤" y-axis Ability to Execute diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 647657c25..3820f2c30 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -228,11 +228,13 @@ export interface PieDiagramConfig extends BaseDiagramConfig { } export interface QuadrantChartConfig extends BaseDiagramConfig { - quadrantPadding?: number; - xAxisLabelPadding?: number; - yAxisLabelPadding?: number; - xAxisLabelFontSize?: number; - yAxisLabelFontSize?: number; + chartWidth: number; + chartHeight: number; + quadrantPadding: number; + xAxisLabelPadding: number; + yAxisLabelPadding: number; + xAxisLabelFontSize: number; + yAxisLabelFontSize: number; quadrantLabelFontSize: number; quadrantTextTopPadding: number; pointTextPadding: number; diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index 24b9b7e8f..ec3f55cb5 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -1281,6 +1281,24 @@ const config: Partial= { }, quadrantChart: { + /** + * | Parameter | Description | Type | Required | Values | + * | --------------- | ---------------------------------- | ------- | -------- | ------------------- | + * | chartWidth | Width of the chart | number | Optional | Any positive number | + * + * **Notes:** + * Default value: 500 + */ + chartWidth: 500, + /** + * | Parameter | Description | Type | Required | Values | + * | --------------- | ---------------------------------- | ------- | -------- | ------------------- | + * | chartHeight | Height of the chart | number | Optional | Any positive number | + * + * **Notes:** + * Default value: 500 + */ + chartHeight: 500, /** * | Parameter | Description | Type | Required | Values | * | --------------- | ---------------------------------- | ------- | -------- | ------------------- | @@ -1389,6 +1407,19 @@ const config: Partial = { * Default value: left */ yAxisPosition: 'left', + /** + * | Parameter | Description | Type | Required | Values | + * | ----------- | ----------- | ------- | -------- | ----------- | + * | useMaxWidth | See Notes | boolean | Required | true, false | + * + * **Notes:** + * + * When this flag is set to true, the diagram width is locked to 100% and scaled based on + * available space. If set to false, the diagram reserves its absolute width. + * + * Default value: true + */ + useMaxWidth: true, }, /** The object containing configurations specific for req diagrams */ diff --git a/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison b/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison index 87d313371..ee8cf2ab2 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison +++ b/packages/mermaid/src/diagrams/quadrant-chart/parser/quadrant.jison @@ -21,130 +21,68 @@ %x point_x %x point_y %% -\%\%\{ { this.begin('open_directive'); return 'open_directive'; } - ((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } - ":" { this.popState(); this.begin('arg_directive'); return ':'; } - \}\%\% { this.popState(); this.popState(); return 'close_directive'; } - ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; -\%\%(?!\{)[^\n]* /* skip comments */ -[^\}]\%\%[^\n]* /* skip comments */ -[\n\r]+ return 'NEWLINE'; -\%\%[^\n]* /* do nothing */ +\%\%\{ { this.begin('open_directive'); return 'open_directive'; } + ((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } + ":" { this.popState(); this.begin('arg_directive'); return ':'; } + \}\%\% { this.popState(); this.popState(); return 'close_directive'; } + ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; +\%\%(?!\{)[^\n]* /* skip comments */ +[^\}]\%\%[^\n]* /* skip comments */ +[\n\r]+ return 'NEWLINE'; +\%\%[^\n]* /* do nothing */ -title { this.begin("title");return 'title'; } - (?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; } +title { this.begin("title");return 'title'; } + (?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; } -accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } - (?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } -accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } - (?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } -accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} - [\}] { this.popState(); } - [^\}]* return "acc_descr_multiline_value"; +accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } + (?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } +accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } + (?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } +accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} + [\}] { this.popState(); } + [^\}]* return "acc_descr_multiline_value"; -\s*"x-axis"\s* return 'X-AXIS'; -\s*"y-axis"\s* return 'Y-AXIS'; -\s*\-\-\>\s* return 'AXIS-TEXT-DELIMITER' -\s*"quadrant-1"\s* return 'QUADRANT_1'; -\s*"quadrant-2"\s* return 'QUADRANT_2'; -\s*"quadrant-3"\s* return 'QUADRANT_3'; -\s*"quadrant-4"\s* return 'QUADRANT_4'; +\s*"x-axis"\s* return 'X-AXIS'; +\s*"y-axis"\s* return 'Y-AXIS'; +\s*\-\-\>\s* return 'AXIS-TEXT-DELIMITER' +\s*"quadrant-1"\s* return 'QUADRANT_1'; +\s*"quadrant-2"\s* return 'QUADRANT_2'; +\s*"quadrant-3"\s* return 'QUADRANT_3'; +\s*"quadrant-4"\s* return 'QUADRANT_4'; -["][`] { this.begin("md_string");} - [^`"]+ { return "MD_STR";} - [`]["] { this.popState();} -["] this.begin("string"); - ["] this.popState(); - [^"]* return "STR"; +["][`] { this.begin("md_string");} + [^`"]+ { return "MD_STR";} + [`]["] { this.popState();} +["] this.begin("string"); + ["] this.popState(); + [^"]* return "STR"; -\s*\:\s*\[\s* {this.begin("point_start"); return 'point_start';} - (1)|(0(.\d+)?) {this.begin('point_x'); return 'point_x';} - \s*\] {this.popState();} - \s*\,\s* {this.popState(); this.begin('point_y');} - (1)|(0(.\d+)?) {this.popState(); return 'point_y';} +\s*\:\s*\[\s* {this.begin("point_start"); return 'point_start';} + (1)|(0(.\d+)?) {this.begin('point_x'); return 'point_x';} + \s*\] {this.popState();} + \s*\,\s* {this.popState(); this.begin('point_y');} + (1)|(0(.\d+)?) {this.popState(); return 'point_y';} -"quadrantChart"\s* return 'QUADRANT'; +"quadrantChart"\s* return 'QUADRANT'; -\[[0-1].?[0-9]{5}\] return 'POINT_VALUE' -[A-Za-z]+ return 'ALPHA'; -":" return 'COLON'; -\+ return 'PLUS'; -"," return 'COMMA'; -"=" return 'EQUALS'; -\= return 'EQUALS'; -"*" return 'MULT'; -\# return 'BRKT'; -[\_] return 'UNDERSCORE'; -"." return 'DOT'; -"&" return 'AMP'; -\- return 'MINUS'; -[0-9]+ return 'NUM'; -\s return 'SPACE'; -";" return 'SEMI'; -[!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION'; -[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]| -[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]| -[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]| -[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]| -[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]| -[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]| -[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]| -[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]| -[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]| -[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]| -[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]| -[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]| -[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]| -[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]| -[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]| -[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]| -[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]| -[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]| -[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]| -[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]| -[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]| -[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]| -[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]| -[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]| -[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]| -[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]| -[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]| -[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]| -[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]| -[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]| -[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]| -[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]| -[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]| -[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]| -[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]| -[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]| -[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]| -[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]| -[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]| -[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]| -[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]| -[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]| -[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]| -[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]| -[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]| -[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]| -[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]| -[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]| -[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]| -[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]| -[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]| -[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]| -[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]| -[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]| -[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]| -[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]| -[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]| -[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]| -[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]| -[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]| -[\uFFD2-\uFFD7\uFFDA-\uFFDC] - return 'UNICODE_TEXT'; -< > return 'EOF'; +\[[0-1].?[0-9]{5}\] return 'POINT_VALUE' +[A-Za-z]+ return 'ALPHA'; +":" return 'COLON'; +\+ return 'PLUS'; +"," return 'COMMA'; +"=" return 'EQUALS'; +\= return 'EQUALS'; +"*" return 'MULT'; +\# return 'BRKT'; +[\_] return 'UNDERSCORE'; +"." return 'DOT'; +"&" return 'AMP'; +\- return 'MINUS'; +[0-9]+ return 'NUM'; +\s return 'SPACE'; +";" return 'SEMI'; +[!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION'; +< > return 'EOF'; /lex @@ -241,7 +179,7 @@ alphaNum ; -alphaNumToken : PUNCTUATION | AMP | UNICODE_TEXT | NUM| ALPHA | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ; +alphaNumToken : PUNCTUATION | AMP | NUM| ALPHA | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ; textNoTagsToken: alphaNumToken | SPACE | MINUS; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.js b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.js deleted file mode 100644 index c4888cdce..000000000 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.js +++ /dev/null @@ -1,284 +0,0 @@ -import { scaleLinear } from 'd3'; - -export class QuadrantBuilder { - totalWidth = 500; - totalHeight = 500; - quadrantPadding = 5; - xAxisLabelPadding = 5; - yAxisLabelPadding = 5; - xAxisLabelFontSize = 16; - yAxisLabelFontSize = 16; - quadrantLabelFontSize = 16; - quadrantTextTopPadding = 5; - pointTextPadding = 5; - pointLabelFontSize = 12; - pointRadius = 5; - points = []; - quadrant1Text = ''; - quadrant2Text = ''; - quadrant3Text = ''; - quadrant4Text = ''; - xAxisLeftText = ''; - xAxisRightText = ''; - yAxisBottomText = ''; - yAxisTopText = ''; - xAxisPosition = 'top'; - yAxisPosition = 'left'; - quadrant1Fill = '#8bc2f3'; - quadrant2Fill = '#faebd7'; - quadrant3Fill = '#00ffff'; - quadrant4Fill = '#f0ffff'; - quadrant1TextFill = '#93690e'; - quadrant2TextFill = '#8644ff'; - quadrant3TextFill = '#e3004d'; - quadrant4TextFill = '#000000'; - pointFill = '#60B19C'; - pointTextFill = '#0000ff'; - xAxisTextFill = '#000000'; - yAxisTextFill = '#000000'; - showXAxis = true; - showYAxis = true; - - constructor() {} - - clear() { - this.points = []; - this.quadrant1Text = ''; - this.quadrant2Text = ''; - this.quadrant3Text = ''; - this.quadrant4Text = ''; - this.xAxisLeftText = ''; - this.xAxisRightText = ''; - this.yAxisBottomText = ''; - this.yAxisTopText = ''; - } - - addPoints(points) { - this.points = this.points.concat([...points]); - } - - set quadrant1Text(text) { - this.quadrant1Text = text; - } - - set quadrant2Text(text) { - this.quadrant2Text = text; - } - - set quadrant3Text(text) { - this.quadrant3Text = text; - } - - set quadrant4Text(text) { - this.quadrant4Text = text; - } - - set xAxisLeftText(text) { - this.xAxisLeftText = text; - } - - set xAxisRightText(text) { - this.xAxisRightText = text; - } - - set yAxisTopText(text) { - this.yAxisTopText = text; - } - - set yAxisBottomText(text) { - this.yAxisBottomText = text; - } - - set totalWidth(width) { - this.totalWidth = width; - } - - set totalHeight(height) { - this.totalHeight = height; - } - - build() { - const showXAxis = (!this.xAxisLeftText && !this.xAxisRightText) ? false: this.showXAxis; - const showYAxis = (!this.yAxisTopText && !this.yAxisBottomText) ? false: this.showYAxis; - const quadrantLeft = - this.quadrantPadding + - ((this.yAxisPosition === 'left' && showYAxis) ? this.yAxisLabelPadding * 2 + this.yAxisLabelFontSize : 0); - const quadrantTop = - this.quadrantPadding + - ((this.xAxisPosition === 'top' && showXAxis) ? this.xAxisLabelPadding * 2 + this.xAxisLabelFontSize : 0); - const quadrantWidth = - this.totalWidth - - (this.quadrantPadding * 2 + (showYAxis ? this.yAxisLabelPadding * 2 + this.yAxisLabelFontSize: 0)); - const quadrantHeight = - this.totalHeight - - (this.quadrantPadding * 2 + (showXAxis ? this.xAxisLabelPadding * 2 + this.xAxisLabelFontSize: 0)); - - const quadrantHalfWidth = quadrantWidth / 2; - const quadrantHalfHeight = quadrantHeight / 2; - - const axisLabels = []; - - if (this.xAxisLeftText && showXAxis) { - axisLabels.push({ - text: this.xAxisLeftText, - fill: this.xAxisTextFill, - x: quadrantLeft, - y: - this.xAxisPosition === 'top' - ? this.xAxisLabelPadding - : this.xAxisLabelPadding + quadrantTop + quadrantHeight, - fontSize: this.xAxisLabelFontSize, - verticalPos: 'left', - horizontalPos: 'top', - rotation: 0, - }); - } - if (this.xAxisRightText && showXAxis) { - axisLabels.push({ - text: this.xAxisRightText, - fill: this.xAxisTextFill, - x: quadrantLeft + quadrantHalfWidth, - y: - this.xAxisPosition === 'top' - ? this.xAxisLabelPadding - : this.xAxisLabelPadding + quadrantTop + quadrantHeight, - fontSize: this.xAxisLabelFontSize, - verticalPos: 'left', - horizontalPos: 'top', - rotation: 0, - }); - } - - if (this.yAxisBottomText && showYAxis) { - axisLabels.push({ - text: this.yAxisBottomText, - fill: this.yAxisTextFill, - x: - this.yAxisPosition === 'left' - ? this.yAxisLabelPadding - : this.yAxisLabelPadding + quadrantLeft + quadrantWidth, - y: quadrantTop + quadrantHeight, - fontSize: this.yAxisLabelFontSize, - verticalPos: 'left', - horizontalPos: 'top', - rotation: -90, - }); - } - if (this.yAxisTopText && showYAxis) { - axisLabels.push({ - text: this.yAxisTopText, - fill: this.yAxisTextFill, - x: - this.yAxisPosition === 'left' - ? this.yAxisLabelPadding - : this.yAxisLabelPadding + quadrantLeft + quadrantWidth, - y: quadrantTop + quadrantHalfHeight, - fontSize: this.yAxisLabelFontSize, - verticalPos: 'left', - horizontalPos: 'top', - rotation: -90, - }); - } - - const quadrants = [ - { - text: this.quadrant1Text, - textFill: this.quadrant1TextFill, - x: quadrantLeft + quadrantHalfWidth, - y: quadrantTop, - width: quadrantHalfWidth, - height: quadrantHalfHeight, - fill: this.quadrant1Fill, - }, - { - text: this.quadrant2Text, - textFill: this.quadrant2TextFill, - x: quadrantLeft, - y: quadrantTop, - width: quadrantHalfWidth, - height: quadrantHalfHeight, - fill: this.quadrant2Fill, - }, - { - text: this.quadrant3Text, - textFill: this.quadrant3TextFill, - x: quadrantLeft, - y: quadrantTop + quadrantHalfHeight, - width: quadrantHalfWidth, - height: quadrantHalfHeight, - fill: this.quadrant3Fill, - }, - { - text: this.quadrant4Text, - textFill: this.quadrant4TextFill, - x: quadrantLeft + quadrantHalfWidth, - y: quadrantTop + quadrantHalfHeight, - width: quadrantHalfWidth, - height: quadrantHalfHeight, - fill: this.quadrant4Fill, - }, - ]; - quadrants.forEach((quadrant, i) => { - // place the text in the center of the box - if (this.points.length === 0) { - quadrant.text = { - text: quadrant.text, - fill: quadrant.textFill, - x: quadrant.x + quadrant.width / 2, - y: quadrant.y + quadrant.height / 2, - fontSize: this.quadrantLabelFontSize, - verticalPos: 'center', - horizontalPos: 'center', - rotation: 0, - }; - // place the text top of the quadrant square - } else { - quadrant.text = { - text: quadrant.text, - fill: quadrant.textFill, - x: quadrant.x + quadrant.width / 2, - y: quadrant.y + this.quadrantTextTopPadding, - fontSize: this.quadrantLabelFontSize, - verticalPos: 'center', - horizontalPos: 'top', - rotation: 0, - }; - } - delete quadrant.textFill; - }); - - const xAxis = scaleLinear() - .domain([0, 1]) - .range([quadrantLeft, quadrantWidth + quadrantLeft]); - - const yAxis = scaleLinear() - .domain([0, 1]) - .range([quadrantHeight + quadrantTop, quadrantTop]); - - const points = this.points.map((point) => { - const props = { - x: xAxis(point.x), - y: yAxis(point.y), - fill: this.pointFill, - radius: this.pointRadius, - }; - props.text = { - text: point.text, - fill: this.pointTextFill, - x: props.x, - y: props.y + this.pointTextPadding, - verticalPos: 'center', - horizontalPos: 'top', - fontSize: this.pointLabelFontSize, - rotation: 0, - }; - return props; - }); - - return { - points, - quadrants, - axisLabels, - }; - } -} diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts new file mode 100644 index 000000000..4e0afb743 --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts @@ -0,0 +1,385 @@ +// @ts-ignore: TODO Fix ts errors +import { scaleLinear } from 'd3'; + +export type QuadrantPointInputType = { x: number; y: number; text: string }; + +export type TextVerticalPos = 'left' | 'center' | 'right'; +export type TextHorizontalPos = 'top' | 'middle' | 'bottom'; + +export type QuadrantTextType = { + text: string; + fill: string; + x: number; + y: number; + verticalPos: TextVerticalPos; + horizontalPos: TextHorizontalPos; + fontSize: number; + rotation: number; +}; + +export type QuadrantPointType = { + x: number; + y: number; + fill: string; + radius: number; + text: QuadrantTextType; +}; + +export type QuadrantQuadrantsType = { + text: QuadrantTextType; + x: number; + y: number; + width: number; + height: number; + fill: string; +}; + +export type QuadrantBuildType = { + points: QuadrantPointType[]; + quadrants: QuadrantQuadrantsType[]; + axisLabels: QuadrantTextType[]; +}; + +export class QuadrantBuilder { + private _quadrant1Text = ''; + private _quadrant2Text = ''; + private _quadrant3Text = ''; + private _quadrant4Text = ''; + private _xAxisLeftText = ''; + private _xAxisRightText = ''; + private _yAxisBottomText = ''; + private _yAxisTopText = ''; + private _totalHeight = 500; + private _totalWidth = 500; + public quadrantPadding = 5; + public xAxisLabelPadding = 5; + public yAxisLabelPadding = 5; + public xAxisLabelFontSize = 16; + public yAxisLabelFontSize = 16; + public quadrantLabelFontSize = 16; + public quadrantTextTopPadding = 5; + public pointTextPadding = 5; + public pointLabelFontSize = 12; + public pointRadius = 5; + public points: QuadrantPointInputType[] = []; + public xAxisPosition = 'top'; + public yAxisPosition = 'left'; + public quadrant1Fill = '#8bc2f3'; + public quadrant2Fill = '#faebd7'; + public quadrant3Fill = '#00ffff'; + public quadrant4Fill = '#f0ffff'; + public quadrant1TextFill = '#93690e'; + public quadrant2TextFill = '#8644ff'; + public quadrant3TextFill = '#e3004d'; + public quadrant4TextFill = '#000000'; + public pointFill = '#60B19C'; + public pointTextFill = '#0000ff'; + public xAxisTextFill = '#000000'; + public yAxisTextFill = '#000000'; + public showXAxis = true; + public showYAxis = true; + + clear() { + this.points = []; + this.quadrant1Text = ''; + this.quadrant2Text = ''; + this.quadrant3Text = ''; + this.quadrant4Text = ''; + this.xAxisLeftText = ''; + this.xAxisRightText = ''; + this.yAxisBottomText = ''; + this.yAxisTopText = ''; + } + + addPoints(points: QuadrantPointInputType[]) { + this.points = [...points, ...this.points]; + } + + set quadrant1Text(text: string) { + this._quadrant1Text = text; + } + + get quadrant1Text() { + return this._quadrant1Text; + } + + set quadrant2Text(text: string) { + this._quadrant2Text = text; + } + + get quadrant2Text() { + return this._quadrant2Text; + } + + set quadrant3Text(text: string) { + this._quadrant3Text = text; + } + + get quadrant3Text() { + return this._quadrant3Text; + } + + set quadrant4Text(text: string) { + this._quadrant4Text = text; + } + + get quadrant4Text() { + return this._quadrant4Text; + } + + set xAxisLeftText(text: string) { + this._xAxisLeftText = text; + } + + get xAxisLeftText() { + return this._xAxisLeftText; + } + + set xAxisRightText(text: string) { + this._xAxisRightText = text; + } + + get xAxisRightText() { + return this._xAxisRightText; + } + + set yAxisTopText(text: string) { + this._yAxisTopText = text; + } + + get yAxisTopText() { + return this._yAxisTopText; + } + + set yAxisBottomText(text: string) { + this._yAxisBottomText = text; + } + + get yAxisBottomText() { + return this._yAxisBottomText; + } + + set totalWidth(width: number) { + this._totalWidth = width; + } + + get totalWidth() { + return this._totalWidth; + } + + set totalHeight(height: number) { + this._totalHeight = height; + } + + get totalHeight() { + return this._totalHeight; + } + + build(): QuadrantBuildType { + const showXAxis = !this.xAxisLeftText && !this.xAxisRightText ? false : this.showXAxis; + const showYAxis = !this.yAxisTopText && !this.yAxisBottomText ? false : this.showYAxis; + const quadrantLeft = + this.quadrantPadding + + (this.yAxisPosition === 'left' && showYAxis + ? this.yAxisLabelPadding * 2 + this.yAxisLabelFontSize + : 0); + const quadrantTop = + this.quadrantPadding + + (this.xAxisPosition === 'top' && showXAxis + ? this.xAxisLabelPadding * 2 + this.xAxisLabelFontSize + : 0); + const quadrantWidth = + this.totalWidth - + (this.quadrantPadding * 2 + + (showYAxis ? this.yAxisLabelPadding * 2 + this.yAxisLabelFontSize : 0)); + const quadrantHeight = + this.totalHeight - + (this.quadrantPadding * 2 + + (showXAxis ? this.xAxisLabelPadding * 2 + this.xAxisLabelFontSize : 0)); + + const quadrantHalfWidth = quadrantWidth / 2; + const quadrantHalfHeight = quadrantHeight / 2; + + const axisLabels: QuadrantTextType[] = []; + + if (this.xAxisLeftText && showXAxis) { + axisLabels.push({ + text: this.xAxisLeftText, + fill: this.xAxisTextFill, + x: quadrantLeft, + y: + this.xAxisPosition === 'top' + ? this.xAxisLabelPadding + : this.xAxisLabelPadding + quadrantTop + quadrantHeight, + fontSize: this.xAxisLabelFontSize, + verticalPos: 'left', + horizontalPos: 'top', + rotation: 0, + }); + } + if (this.xAxisRightText && showXAxis) { + axisLabels.push({ + text: this.xAxisRightText, + fill: this.xAxisTextFill, + x: quadrantLeft + quadrantHalfWidth, + y: + this.xAxisPosition === 'top' + ? this.xAxisLabelPadding + : this.xAxisLabelPadding + quadrantTop + quadrantHeight, + fontSize: this.xAxisLabelFontSize, + verticalPos: 'left', + horizontalPos: 'top', + rotation: 0, + }); + } + + if (this.yAxisBottomText && showYAxis) { + axisLabels.push({ + text: this.yAxisBottomText, + fill: this.yAxisTextFill, + x: + this.yAxisPosition === 'left' + ? this.yAxisLabelPadding + : this.yAxisLabelPadding + quadrantLeft + quadrantWidth, + y: quadrantTop + quadrantHeight, + fontSize: this.yAxisLabelFontSize, + verticalPos: 'left', + horizontalPos: 'top', + rotation: -90, + }); + } + if (this.yAxisTopText && showYAxis) { + axisLabels.push({ + text: this.yAxisTopText, + fill: this.yAxisTextFill, + x: + this.yAxisPosition === 'left' + ? this.yAxisLabelPadding + : this.yAxisLabelPadding + quadrantLeft + quadrantWidth, + y: quadrantTop + quadrantHalfHeight, + fontSize: this.yAxisLabelFontSize, + verticalPos: 'left', + horizontalPos: 'top', + rotation: -90, + }); + } + + const quadrants: QuadrantQuadrantsType[] = [ + { + text: { + text: this.quadrant1Text, + fill: this.quadrant1TextFill, + x: 0, + y: 0, + fontSize: this.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft + quadrantHalfWidth, + y: quadrantTop, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.quadrant1Fill, + }, + { + text: { + text: this.quadrant2Text, + fill: this.quadrant2TextFill, + x: 0, + y: 0, + fontSize: this.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft, + y: quadrantTop, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.quadrant2Fill, + }, + { + text: { + text: this.quadrant3Text, + fill: this.quadrant3TextFill, + x: 0, + y: 0, + fontSize: this.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft, + y: quadrantTop + quadrantHalfHeight, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.quadrant3Fill, + }, + { + text: { + text: this.quadrant4Text, + fill: this.quadrant4TextFill, + x: 0, + y: 0, + fontSize: this.quadrantLabelFontSize, + verticalPos: 'center', + horizontalPos: 'middle', + rotation: 0, + }, + x: quadrantLeft + quadrantHalfWidth, + y: quadrantTop + quadrantHalfHeight, + width: quadrantHalfWidth, + height: quadrantHalfHeight, + fill: this.quadrant4Fill, + }, + ]; + quadrants.forEach((quadrant, i) => { + // place the text in the center of the box + if (this.points.length === 0) { + quadrant.text.x = quadrant.x + quadrant.width / 2; + quadrant.text.y = quadrant.y + quadrant.height / 2; + quadrant.text.horizontalPos = 'middle'; + // place the text top of the quadrant square + } else { + quadrant.text.x = quadrant.x + quadrant.width / 2; + quadrant.text.y = quadrant.y + this.quadrantTextTopPadding; + quadrant.text.horizontalPos = 'top'; + } + }); + + const xAxis = scaleLinear() + .domain([0, 1]) + .range([quadrantLeft, quadrantWidth + quadrantLeft]); + + const yAxis = scaleLinear() + .domain([0, 1]) + .range([quadrantHeight + quadrantTop, quadrantTop]); + + const points: QuadrantPointType[] = this.points.map((point) => { + const props: QuadrantPointType = { + x: xAxis(point.x), + y: yAxis(point.y), + fill: this.pointFill, + radius: this.pointRadius, + text: { + text: point.text, + fill: this.pointTextFill, + x: xAxis(point.x), + y: yAxis(point.y) + this.pointTextPadding, + verticalPos: 'center', + horizontalPos: 'top', + fontSize: this.pointLabelFontSize, + rotation: 0, + }, + }; + return props; + }); + + return { + points, + quadrants, + axisLabels, + }; + } +} diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.js b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts similarity index 61% rename from packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.js rename to packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts index a8d33a42d..630d6011c 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.js +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDb.ts @@ -15,54 +15,55 @@ import { QuadrantBuilder } from './quadrantBuilder.js'; const config = configApi.getConfig(); -function textSanitizer(text) { +function textSanitizer(text: string) { return sanitizeText(text.trim(), config); } +type LexTextObj = { text: string; type: 'text' | 'markdown' }; + const quadrantBuilder = new QuadrantBuilder(); -function setQuadrant1Text(textObj) { +function setQuadrant1Text(textObj: LexTextObj) { quadrantBuilder.quadrant1Text = textSanitizer(textObj.text); } -function setQuadrant2Text(textObj) { +function setQuadrant2Text(textObj: LexTextObj) { quadrantBuilder.quadrant2Text = textSanitizer(textObj.text); } -function setQuadrant3Text(textObj) { +function setQuadrant3Text(textObj: LexTextObj) { quadrantBuilder.quadrant3Text = textSanitizer(textObj.text); } -function setQuadrant4Text(textObj) { +function setQuadrant4Text(textObj: LexTextObj) { quadrantBuilder.quadrant4Text = textSanitizer(textObj.text); } -function setXAxisLeftText(textObj) { +function setXAxisLeftText(textObj: LexTextObj) { quadrantBuilder.xAxisLeftText = textSanitizer(textObj.text); } -function setXAxisRightText(textObj) { +function setXAxisRightText(textObj: LexTextObj) { quadrantBuilder.xAxisRightText = textSanitizer(textObj.text); } -function setYAxisTopText(textObj) { +function setYAxisTopText(textObj: LexTextObj) { quadrantBuilder.yAxisTopText = textSanitizer(textObj.text); } -function setYAxisBottomText(textObj) { +function setYAxisBottomText(textObj: LexTextObj) { quadrantBuilder.yAxisBottomText = textSanitizer(textObj.text); } -function addPoints(textObj, x, y) { - console.log(textObj, x, y); +function addPoints(textObj: LexTextObj, x: number, y: number) { quadrantBuilder.addPoints([{ x, y, text: textSanitizer(textObj.text) }]); } -function setWidth(width) { +function setWidth(width: number) { quadrantBuilder.totalWidth = width; } -function setHeight(height) { +function setHeight(height: number) { quadrantBuilder.totalHeight = height; } @@ -81,22 +82,25 @@ function getQuadrantData() { quadrantBuilder.pointTextFill = themeVariables.quadrantPointTextFill; quadrantBuilder.xAxisTextFill = themeVariables.quadrantXAxisTextFill; quadrantBuilder.yAxisTextFill = themeVariables.quadrantYAxisTextFill; - quadrantBuilder.quadrantPadding = quadrantChartConfig.quadrantPadding; - quadrantBuilder.xAxisLabelPadding = quadrantChartConfig.xAxisLabelPadding; - quadrantBuilder.yAxisLabelPadding = quadrantChartConfig.yAxisLabelPadding; - quadrantBuilder.xAxisLabelFontSize = quadrantChartConfig.xAxisLabelFontSize; - quadrantBuilder.yAxisLabelFontSize = quadrantChartConfig.yAxisLabelFontSize; - quadrantBuilder.quadrantLabelFontSize = quadrantChartConfig.quadrantLabelFontSize; - quadrantBuilder.quadrantTextTopPadding = quadrantChartConfig.quadrantTextTopPadding; - quadrantBuilder.pointTextPadding = quadrantChartConfig.pointTextPadding; - quadrantBuilder.pointLabelFontSize = quadrantChartConfig.pointLabelFontSize; - quadrantBuilder.pointRadius = quadrantChartConfig.pointRadius; - quadrantBuilder.xAxisPosition = quadrantChartConfig.xAxisPosition; - quadrantBuilder.yAxisPosition = quadrantChartConfig.yAxisPosition; + if (quadrantChartConfig) { + quadrantBuilder.quadrantPadding = quadrantChartConfig.quadrantPadding; + quadrantBuilder.xAxisLabelPadding = quadrantChartConfig.xAxisLabelPadding; + quadrantBuilder.yAxisLabelPadding = quadrantChartConfig.yAxisLabelPadding; + quadrantBuilder.xAxisLabelFontSize = quadrantChartConfig.xAxisLabelFontSize; + quadrantBuilder.yAxisLabelFontSize = quadrantChartConfig.yAxisLabelFontSize; + quadrantBuilder.quadrantLabelFontSize = quadrantChartConfig.quadrantLabelFontSize; + quadrantBuilder.quadrantTextTopPadding = quadrantChartConfig.quadrantTextTopPadding; + quadrantBuilder.pointTextPadding = quadrantChartConfig.pointTextPadding; + quadrantBuilder.pointLabelFontSize = quadrantChartConfig.pointLabelFontSize; + quadrantBuilder.pointRadius = quadrantChartConfig.pointRadius; + quadrantBuilder.xAxisPosition = quadrantChartConfig.xAxisPosition; + quadrantBuilder.yAxisPosition = quadrantChartConfig.yAxisPosition; + } return quadrantBuilder.build(); } -export const parseDirective = function (statement, context, type) { +export const parseDirective = function (statement: string, context: string, type: string) { + // @ts-ignore: TODO Fix ts errors mermaidAPI.parseDirective(this, statement, context, type); }; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts index ec3d6ed20..40ae798d2 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantDiagram.ts @@ -2,12 +2,11 @@ import { DiagramDefinition } from '../../diagram-api/types.js'; // @ts-ignore: TODO Fix ts errors import parser from './parser/quadrant.jison'; import db from './quadrantDb.js'; -import styles from './styles.js'; import renderer from './quadrantRenderer.js'; export const diagram: DiagramDefinition = { parser, db, renderer, - styles, + styles: () => '', }; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.js b/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.js deleted file mode 100644 index 91936fb82..000000000 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.js +++ /dev/null @@ -1,131 +0,0 @@ -import { select, scaleLinear } from 'd3'; -import * as configApi from '../../config.js'; -import { log } from '../../logger.js'; - -import { configureSvgSize } from '../../setupGraphViewbox.js'; - -export const draw = (txt, id, _version, diagObj) => { - - - function getDominantBaseLine(horizintalPos) { - return horizintalPos === 'top' ? 'text-before-edge' : 'middle'; - } - - function getTextAnchor(verticalPos) { - return verticalPos === 'left' ? 'start' : 'middle'; - } - - function getTransformation(data) { - return `translate(${data.x}, ${data.y}) rotate(${data.rotation || 0})`; - } - - const conf = configApi.getConfig(); - log.debug('Rendering info diagram\n' + txt); - - const securityLevel = conf.securityLevel; - // Handle root and Document for when rendering in sandbox mode - let sandboxElement; - if (securityLevel === 'sandbox') { - sandboxElement = select('#i' + id); - } - const root = - securityLevel === 'sandbox' - ? select(sandboxElement.nodes()[0].contentDocument.body) - : select('body'); - - const svg = root.select(`[id="${id}"]`); - - const group = svg.append('g').attr('class', 'main'); - - - // const bounds = svg.node().getBox(); - // const width = bounds.width + padding * 2; - // const height = bounds.height + padding * 2; - const width = 500; - const height = 500; - - diagObj.db.setHeight(height); - diagObj.db.setWidth(width); - - svg.attr('width', width); - svg.attr('height', height); - - const quadrantData = diagObj.db.getQuadrantData(); - - const quadrantsGroup = group.append('g').attr('class', 'quadrants'); - const dataPointGroup = group.append('g').attr('class', 'data-points'); - const labelGroup = group.append('g').attr('class', 'labels'); - - const quadrants = quadrantsGroup - .selectAll('g.quadrant') - .data(quadrantData.quadrants) - .enter() - .append('g') - .attr('class', 'quadrant'); - - quadrants - .append('rect') - .attr('x', data => data.x) - .attr('y', data => data.y) - .attr('width', data => data.width) - .attr('height', data => data.height) - .attr('fill', data => data.fill); - - quadrants - .append('text') - .attr('x', 0) - .attr('y', 0) - .attr('fill', data => data.text.fill) - .attr('font-size', data => data.text.fontSize) - .attr('dominant-baseline', data => getDominantBaseLine(data.text.horizontalPos)) - .attr('text-anchor', data => getTextAnchor(data.text.verticalPos)) - .attr('transform', data => getTransformation(data.text)) - .text(data => data.text.text); - - const labels = labelGroup - .selectAll('g.label') - .data(quadrantData.axisLabels) - .enter() - .append('g') - .attr('class', 'label') - - labels - .append('text') - .attr('x', 0) - .attr('y', 0) - .text(data => data.text) - .attr('fill', data => data.fill) - .attr('font-size', data => data.fontSize) - .attr('dominant-baseline', data => getDominantBaseLine(data.horizontalPos)) - .attr('text-anchor', data => getTextAnchor(data.verticalPos)) - .attr('transform', data => getTransformation(data)) - - const dataPoints = dataPointGroup - .selectAll('g.data-point') - .data(quadrantData.points) - .enter() - .append('g') - .attr('class', 'data-point') - - dataPoints - .append('circle') - .attr('cx', data => data.x) - .attr('cy', data => data.y) - .attr('r', data => data.radius) - .attr('fill', data => data.fill); - - dataPoints - .append('text') - .attr('x', 0) - .attr('y', 0) - .text(data => data.text.text) - .attr('fill', data => data.text.fill) - .attr('font-size', data => data.text.fontSize) - .attr('dominant-baseline', data => getDominantBaseLine(data.text.horizontalPos)) - .attr('text-anchor', data => getTextAnchor(data.text.verticalPos)) - .attr('transform', data => getTransformation(data.text)) -}; - -export default { - draw, -}; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts new file mode 100644 index 000000000..72639ba2e --- /dev/null +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts @@ -0,0 +1,144 @@ +// @ts-ignore: TODO Fix ts errors +import { select } from 'd3'; +import * as configApi from '../../config.js'; +import { log } from '../../logger.js'; + +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import { Diagram } from '../../Diagram.js'; +import { + QuadrantBuildType, + QuadrantPointType, + QuadrantQuadrantsType, + QuadrantTextType, + TextHorizontalPos, + TextVerticalPos, +} from './quadrantBuilder.js'; + +export const draw = (txt: string, id: string, _version: string, diagObj: Diagram) => { + function getDominantBaseLine(horizintalPos: TextHorizontalPos) { + return horizintalPos === 'top' ? 'text-before-edge' : 'middle'; + } + + function getTextAnchor(verticalPos: TextVerticalPos) { + return verticalPos === 'left' ? 'start' : 'middle'; + } + + function getTransformation(data: { x: number; y: number; rotation: number }) { + return `translate(${data.x}, ${data.y}) rotate(${data.rotation || 0})`; + } + + const conf = configApi.getConfig(); + + log.debug('Rendering info diagram\n' + txt); + + const securityLevel = conf.securityLevel; + // Handle root and Document for when rendering in sandbox mode + let sandboxElement; + if (securityLevel === 'sandbox') { + sandboxElement = select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? select(sandboxElement.nodes()[0].contentDocument.body) + : select('body'); + + const svg = root.select(`[id="${id}"]`); + + const group = svg.append('g').attr('class', 'main'); + + const width = conf.quadrantChart?.chartWidth || 500; + const height = conf.quadrantChart?.chartHeight || 500; + + configureSvgSize(svg, height, width, conf.quadrantChart?.useMaxWidth || true); + + svg.attr('viewBox', '0 0 ' + width + ' ' + height); + + // @ts-ignore: TODO Fix ts errors + diagObj.db.setHeight(height); + // @ts-ignore: TODO Fix ts errors + diagObj.db.setWidth(width); + + // @ts-ignore: TODO Fix ts errors + const quadrantData: QuadrantBuildType = diagObj.db.getQuadrantData(); + + const quadrantsGroup = group.append('g').attr('class', 'quadrants'); + const dataPointGroup = group.append('g').attr('class', 'data-points'); + const labelGroup = group.append('g').attr('class', 'labels'); + + const quadrants = quadrantsGroup + .selectAll('g.quadrant') + .data(quadrantData.quadrants) + .enter() + .append('g') + .attr('class', 'quadrant'); + + quadrants + .append('rect') + .attr('x', (data: QuadrantQuadrantsType) => data.x) + .attr('y', (data: QuadrantQuadrantsType) => data.y) + .attr('width', (data: QuadrantQuadrantsType) => data.width) + .attr('height', (data: QuadrantQuadrantsType) => data.height) + .attr('fill', (data: QuadrantQuadrantsType) => data.fill); + + quadrants + .append('text') + .attr('x', 0) + .attr('y', 0) + .attr('fill', (data: QuadrantQuadrantsType) => data.text.fill) + .attr('font-size', (data: QuadrantQuadrantsType) => data.text.fontSize) + .attr('dominant-baseline', (data: QuadrantQuadrantsType) => + getDominantBaseLine(data.text.horizontalPos) + ) + .attr('text-anchor', (data: QuadrantQuadrantsType) => getTextAnchor(data.text.verticalPos)) + .attr('transform', (data: QuadrantQuadrantsType) => getTransformation(data.text)) + .text((data: QuadrantQuadrantsType) => data.text.text); + + const labels = labelGroup + .selectAll('g.label') + .data(quadrantData.axisLabels) + .enter() + .append('g') + .attr('class', 'label'); + + labels + .append('text') + .attr('x', 0) + .attr('y', 0) + .text((data: QuadrantTextType) => data.text) + .attr('fill', (data: QuadrantTextType) => data.fill) + .attr('font-size', (data: QuadrantTextType) => data.fontSize) + .attr('dominant-baseline', (data: QuadrantTextType) => getDominantBaseLine(data.horizontalPos)) + .attr('text-anchor', (data: QuadrantTextType) => getTextAnchor(data.verticalPos)) + .attr('transform', (data: QuadrantTextType) => getTransformation(data)); + + const dataPoints = dataPointGroup + .selectAll('g.data-point') + .data(quadrantData.points) + .enter() + .append('g') + .attr('class', 'data-point'); + + dataPoints + .append('circle') + .attr('cx', (data: QuadrantPointType) => data.x) + .attr('cy', (data: QuadrantPointType) => data.y) + .attr('r', (data: QuadrantPointType) => data.radius) + .attr('fill', (data: QuadrantPointType) => data.fill); + + dataPoints + .append('text') + .attr('x', 0) + .attr('y', 0) + .text((data: QuadrantPointType) => data.text.text) + .attr('fill', (data: QuadrantPointType) => data.text.fill) + .attr('font-size', (data: QuadrantPointType) => data.text.fontSize) + .attr('dominant-baseline', (data: QuadrantPointType) => + getDominantBaseLine(data.text.horizontalPos) + ) + .attr('text-anchor', (data: QuadrantPointType) => getTextAnchor(data.text.verticalPos)) + .attr('transform', (data: QuadrantPointType) => getTransformation(data.text)); +}; + +export default { + draw, +}; diff --git a/packages/mermaid/src/diagrams/quadrant-chart/styles.js b/packages/mermaid/src/diagrams/quadrant-chart/styles.js deleted file mode 100644 index fc7ab4bfd..000000000 --- a/packages/mermaid/src/diagrams/quadrant-chart/styles.js +++ /dev/null @@ -1,5 +0,0 @@ -const getStyles = (options) => -` -`; - -export default getStyles; diff --git a/packages/mermaid/src/themes/theme-base.js b/packages/mermaid/src/themes/theme-base.js index 30bbfd5b6..53c5f73b6 100644 --- a/packages/mermaid/src/themes/theme-base.js +++ b/packages/mermaid/src/themes/theme-base.js @@ -1,4 +1,4 @@ -import { darken, lighten, adjust, invert } from 'khroma'; +import { darken, lighten, adjust, invert, isDark } from 'khroma'; import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, @@ -222,15 +222,21 @@ class Theme { /* quadrant-graph */ this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; - this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, {r: 5, g: 5, b: 5}); - this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, {r: 10, g: 10, b: 10}); - this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, {r: 15, g: 15, b: 15}); + this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, { r: 15, g: 15, b: 15 }); this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; - this.quadrant2TextFill = this.quadrant2TextFill || adjust(this.quadrant1TextFill, {r: -5, g: -5, b: -5}); - this.quadrant3TextFill = this.quadrant3TextFill || adjust(this.quadrant1TextFill, {r: -10, g: -10, b: -10}); - this.quadrant4TextFill = this.quadrant4TextFill || adjust(this.quadrant1TextFill, {r: -15, g: -15, b: -15}); - this.quadrantPointFill = this.quadrantPointFill || this.secondaryColor; - this.quadrantPointTextFill = this.quadrantPointTextFill || this.secondaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.quadrant1TextFill, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.quadrant1TextFill, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.quadrant1TextFill, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; diff --git a/packages/mermaid/src/themes/theme-dark.js b/packages/mermaid/src/themes/theme-dark.js index 41c624588..d1f5dbde6 100644 --- a/packages/mermaid/src/themes/theme-dark.js +++ b/packages/mermaid/src/themes/theme-dark.js @@ -1,4 +1,4 @@ -import { invert, lighten, darken, rgba, adjust } from 'khroma'; +import { invert, lighten, darken, rgba, adjust, isDark } from 'khroma'; import { mkBorder } from './theme-helpers.js'; class Theme { @@ -228,15 +228,21 @@ class Theme { /* quadrant-graph */ this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; - this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, {r: 5, g: 5, b: 5}); - this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, {r: 10, g: 10, b: 10}); - this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, {r: 15, g: 15, b: 15}); + this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, { r: 15, g: 15, b: 15 }); this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; - this.quadrant2TextFill = this.quadrant2TextFill || adjust(this.quadrant1TextFill, {r: -5, g: -5, b: -5}); - this.quadrant3TextFill = this.quadrant3TextFill || adjust(this.quadrant1TextFill, {r: -10, g: -10, b: -10}); - this.quadrant4TextFill = this.quadrant4TextFill || adjust(this.quadrant1TextFill, {r: -15, g: -15, b: -15}); - this.quadrantPointFill = this.quadrantPointFill || this.secondaryColor; - this.quadrantPointTextFill = this.quadrantPointTextFill || this.secondaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.quadrant1TextFill, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.quadrant1TextFill, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.quadrant1TextFill, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; diff --git a/packages/mermaid/src/themes/theme-default.js b/packages/mermaid/src/themes/theme-default.js index 091240af0..f73a05c4d 100644 --- a/packages/mermaid/src/themes/theme-default.js +++ b/packages/mermaid/src/themes/theme-default.js @@ -1,4 +1,4 @@ -import { invert, lighten, rgba, adjust, darken } from 'khroma'; +import { invert, lighten, rgba, adjust, darken, isDark } from 'khroma'; import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, @@ -249,15 +249,21 @@ class Theme { /* quadrant-graph */ this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; - this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, {r: 5, g: 5, b: 5}); - this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, {r: 10, g: 10, b: 10}); - this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, {r: 15, g: 15, b: 15}); + this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, { r: 15, g: 15, b: 15 }); this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; - this.quadrant2TextFill = this.quadrant2TextFill || adjust(this.quadrant1TextFill, {r: -5, g: -5, b: -5}); - this.quadrant3TextFill = this.quadrant3TextFill || adjust(this.quadrant1TextFill, {r: -10, g: -10, b: -10}); - this.quadrant4TextFill = this.quadrant4TextFill || adjust(this.quadrant1TextFill, {r: -15, g: -15, b: -15}); - this.quadrantPointFill = this.quadrantPointFill || this.secondaryColor; - this.quadrantPointTextFill = this.quadrantPointTextFill || this.secondaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.quadrant1TextFill, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.quadrant1TextFill, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.quadrant1TextFill, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; diff --git a/packages/mermaid/src/themes/theme-forest.js b/packages/mermaid/src/themes/theme-forest.js index 0c4af6ec3..f3e41adec 100644 --- a/packages/mermaid/src/themes/theme-forest.js +++ b/packages/mermaid/src/themes/theme-forest.js @@ -1,4 +1,4 @@ -import { darken, lighten, adjust, invert } from 'khroma'; +import { darken, lighten, adjust, invert, isDark } from 'khroma'; import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, @@ -217,15 +217,21 @@ class Theme { /* quadrant-graph */ this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; - this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, {r: 5, g: 5, b: 5}); - this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, {r: 10, g: 10, b: 10}); - this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, {r: 15, g: 15, b: 15}); + this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, { r: 15, g: 15, b: 15 }); this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; - this.quadrant2TextFill = this.quadrant2TextFill || adjust(this.quadrant1TextFill, {r: -5, g: -5, b: -5}); - this.quadrant3TextFill = this.quadrant3TextFill || adjust(this.quadrant1TextFill, {r: -10, g: -10, b: -10}); - this.quadrant4TextFill = this.quadrant4TextFill || adjust(this.quadrant1TextFill, {r: -15, g: -15, b: -15}); - this.quadrantPointFill = this.quadrantPointFill || this.secondaryColor; - this.quadrantPointTextFill = this.quadrantPointTextFill || this.secondaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.quadrant1TextFill, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.quadrant1TextFill, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.quadrant1TextFill, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor; diff --git a/packages/mermaid/src/themes/theme-neutral.js b/packages/mermaid/src/themes/theme-neutral.js index 1f069c4fd..f240404a7 100644 --- a/packages/mermaid/src/themes/theme-neutral.js +++ b/packages/mermaid/src/themes/theme-neutral.js @@ -1,4 +1,4 @@ -import { invert, darken, lighten, adjust } from 'khroma'; +import { invert, darken, lighten, adjust, isDark } from 'khroma'; import { mkBorder } from './theme-helpers.js'; import { oldAttributeBackgroundColorEven, @@ -248,15 +248,21 @@ class Theme { /* quadrant-graph */ this.quadrant1Fill = this.quadrant1Fill || this.primaryColor; - this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, {r: 5, g: 5, b: 5}); - this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, {r: 10, g: 10, b: 10}); - this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, {r: 15, g: 15, b: 15}); + this.quadrant2Fill = this.quadrant2Fill || adjust(this.quadrant1Fill, { r: 5, g: 5, b: 5 }); + this.quadrant3Fill = this.quadrant3Fill || adjust(this.quadrant1Fill, { r: 10, g: 10, b: 10 }); + this.quadrant4Fill = this.quadrant4Fill || adjust(this.quadrant1Fill, { r: 15, g: 15, b: 15 }); this.quadrant1TextFill = this.quadrant1TextFill || this.primaryTextColor; - this.quadrant2TextFill = this.quadrant2TextFill || adjust(this.quadrant1TextFill, {r: -5, g: -5, b: -5}); - this.quadrant3TextFill = this.quadrant3TextFill || adjust(this.quadrant1TextFill, {r: -10, g: -10, b: -10}); - this.quadrant4TextFill = this.quadrant4TextFill || adjust(this.quadrant1TextFill, {r: -15, g: -15, b: -15}); - this.quadrantPointFill = this.quadrantPointFill || this.secondaryColor; - this.quadrantPointTextFill = this.quadrantPointTextFill || this.secondaryTextColor; + this.quadrant2TextFill = + this.quadrant2TextFill || adjust(this.quadrant1TextFill, { r: -5, g: -5, b: -5 }); + this.quadrant3TextFill = + this.quadrant3TextFill || adjust(this.quadrant1TextFill, { r: -10, g: -10, b: -10 }); + this.quadrant4TextFill = + this.quadrant4TextFill || adjust(this.quadrant1TextFill, { r: -15, g: -15, b: -15 }); + this.quadrantPointFill = + this.quadrantPointFill || isDark(this.quadrant1Fill) + ? lighten(this.quadrant1Fill) + : darken(this.quadrant1Fill); + this.quadrantPointTextFill = this.quadrantPointTextFill || this.primaryTextColor; this.quadrantXAxisTextFill = this.quadrantXAxisTextFill || this.primaryTextColor; this.quadrantYAxisTextFill = this.quadrantYAxisTextFill || this.primaryTextColor;