diff --git a/packages/mermaid/src/diagrams/xychart/parser/xychart.jison b/packages/mermaid/src/diagrams/xychart/parser/xychart.jison index 1ecd6edf4..743647df7 100644 --- a/packages/mermaid/src/diagrams/xychart/parser/xychart.jison +++ b/packages/mermaid/src/diagrams/xychart/parser/xychart.jison @@ -1,7 +1,6 @@ %lex %options case-insensitive -%x string %x string %x md_string %x title @@ -12,24 +11,9 @@ %x acc_title %x acc_descr %x acc_descr_multiline -%x chart_config -%x chart_orientation -%x x_axis -%x y_axis -%x axis_title -%x axis_data -%x axis_data_band -%x axis_data_band_capture -%x line -%x line_title -%x line_data -%x line_data_entries -%x line_data_without_label -%x bar_data_without_label -%x bar -%x bar_title -%x bar_data -%x bar_data_entries +%s axis_data +%s data +%s data_inner %% \%\%\{ { this.begin('open_directive'); return 'open_directive'; } ((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; } @@ -38,63 +22,38 @@ ((?:(?!\}\%\%).|\n)*) return 'arg_directive'; \%\%(?!\{)[^\n]* /* skip comments */ [^\}]\%\%[^\n]* /* skip comments */ +(\r?\n) { this.popState(); return 'NEWLINE'; } +(\r?\n) { this.popState(); return 'NEWLINE'; } [\n\r]+ return 'NEWLINE'; \%\%[^\n]* /* do nothing */ -title { this.begin("title");return 'title'; } +title { this.begin("title"); return 'title'; } (?!\n|;|#)*[^\n]* { this.popState(); return "title_value"; } + accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } <acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } <acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} <acc_descr_multiline>[\}] { this.popState(); } -<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value"; +<acc_descr_multiline>[^\}]* { return "acc_descr_multiline_value"; } -" "*"xychart-beta" {this.begin("chart_config"); return 'XYCHART';} -<chart_config>" "+("vertical"|"horizontal") {this.begin("chart_orientation"); return 'chart_orientation';} -<chart_orientation>[\s]* {this.popState(); this.popState(); return 'CHART_CONFIG_END';} -<chart_config>[\s]* {this.popState(); return 'CHART_CONFIG_END';} +"xychart-beta" {return 'XYCHART';} +("vertical"|"horizontal") {return 'CHART_ORIENTATION'} -"x-axis"" "* { this.begin("x_axis"); return "X_AXIS";} -"y-axis"" "* { this.begin("y_axis"); return "Y_AXIS";} -<x_axis,y_axis>["] {this.begin("axis_title");} -<axis_title>[^"]+ {return 'AXIS_TITLE';} -<axis_title>["]" "*(\r?\n) {this.popState(); this.popState();} -<axis_title>["]" "* {this.popState(); this.begin("axis_data");} -<x_axis,y_axis>[^\s]+" "*(\r?\n) {this.popState(); return 'AXIS_TITLE';} -<x_axis,y_axis>[^\s]+" "* {this.begin("axis_data"); return 'AXIS_TITLE'; } - -<axis_data>[+-]?\d+(?:\.\d+)?" "*"-->"" "*[+-]?\d+(?:\.\d+)?" "* { return 'AXIS_RANGE_DATA';} - -<axis_data>[\[]" "* {this.begin("axis_data_band"), this.begin("axis_data_band_capture")} -<axis_data_band_capture>(["][^",]+["]|[^\s\"\,]]+)" "*([,]" "*(["][^",]+["]|[^\s\]",]+)" "*)* { this.popState(); return "AXIS_BAND_DATA"; } -<axis_data_band>[\]]" "* {this.popState(); return "AXIS_BAND_DATA_END"} -<axis_data>[\s]+ {this.popState(); this.popState();} +"x-axis" { this.begin("axis_data"); return "X_AXIS"; } +"y-axis" { this.begin("axis_data"); return "Y_AXIS"; } +<axis_data>[\[] { this.popState(); return 'SQUARE_BRACES_START'; } +<axis_data>[+-]?\d+(?:\.\d+)? { return 'NUMBER_WITH_DECIMAL'; } +<axis_data>"-->" { return 'ARROW_DELIMITER'; } -"line"" "* {this.begin("line"); return 'LINE';} -<line>["] {this.begin("line_title");} -<line_title>[^"]+ {return 'LINE_TITLE';} -<line_title>["]" "* {this.popState(); this.begin("line_data");} -<line_data>"["" "* {this.begin('line_data_entries');} -<line_data_without_label,line_data_entries>(?:[+-]?\d+(?:\.\d+)?)+(?:" "*[,]" "*(?:[+-]?\d+(?:\.\d+)?)+)*" "* {return 'LINE_DATA'} -<line_data_entries>"]"" "* {this.popState(); this.popState(); this.popState()} -<line_data_without_label>"]"" "* {this.popState(); this.popState()} -<line>[^\s\[]+" "* {this.begin("line_data"); return 'LINE_TITLE';} -<line>"["" "* {this.begin('line_data_without_label');} - -"bar"" "* {this.begin("bar"); return 'BAR';} -<bar>["] {this.begin("bar_title");} -<bar_title>[^"]+ {return 'BAR_TITLE';} -<bar_title>["]" "* {this.popState(); this.begin("bar_data");} -<bar_data>"["" "* {this.begin('bar_data_entries');} -<bar_data_without_label,bar_data_entries>(?:[+-]?\d+(?:\.\d+)?)+(?:" "*[,]" "*(?:[+-]?\d+(?:\.\d+)?)+)*" "* {return 'BAR_DATA'} -<bar_data_entries>"]"" "* {this.popState(); this.popState(); this.popState()} -<bar_data_without_label>"]"" "* {this.popState(); this.popState()} -<bar>[^\s\[]+" "* {this.begin("bar_data"); return 'BAR_TITLE';} -<bar>"["" "* {this.begin('bar_data_without_label');} +"line" { this.begin("data"); return 'LINE'; } +"bar" { this.begin("data"); return 'BAR'; } +<data>[\[] { this.popState(); this.begin("data_inner"); return 'SQUARE_BRACES_START'; } +<data_inner>[+-]?\d+(?:\.\d+)? { return 'NUMBER_WITH_DECIMAL';} +<data_inner>[\]] { this.popState(); return 'SQUARE_BRACES_END'; } @@ -106,6 +65,9 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} <string>["] this.popState(); <string>[^"]* return "STR"; + +[\[] return 'SQUARE_BRACES_START' +[\]] return 'SQUARE_BRACES_END' [A-Za-z]+ return 'ALPHA'; ":" return 'COLON'; \+ return 'PLUS'; @@ -119,7 +81,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} "&" return 'AMP'; \- return 'MINUS'; [0-9]+ return 'NUM'; -\s return 'SPACE'; +\s /* skip */ ";" return 'SEMI'; [!"#$%&'*+,-.`?\\_/] return 'PUNCTUATION'; <<EOF>> return 'EOF'; @@ -132,60 +94,63 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} start : eol start - | SPACE start | directive start - | XYCHART chartConfig CHART_CONFIG_END document - | XYCHART CHART_CONFIG_END document + | XYCHART chartConfig start + | XYCHART start + | document ; chartConfig - : chart_orientation {yy.setOrientation($1.trim());} + : CHART_ORIENTATION { yy.setOrientation($1); } ; document : /* empty */ - | document line + | document statement ; line - : statement eol + : statement ; statement - : - | SPACE statement - | directive - | title title_value { $$=$2.trim();yy.setDiagramTitle($$); } + : statement eol + | title title_value { yy.setDiagramTitle($title_value.trim()); } | X_AXIS parseXAxis | Y_AXIS parseYAxis - | parseLine - | parseBar + | LINE parseLineData { yy.setLineData({text: '', type: 'text'}, $parseLineData); } + | LINE text parseLineData { yy.setLineData($text, $parseLineData); } + | BAR parseBarData { yy.setBarData({text: '', type: 'text'}, $parseBarData); } + | BAR text parseBarData { yy.setBarData($text, $parseBarData); } ; -parseLine - : LINE LINE_DATA {yy.setLineData('', $2.split(',').map(d => Number(d.trim())));} - | LINE LINE_TITLE LINE_DATA {yy.setLineData($2.trim(), $3.split(',').map(d => Number(d.trim())));} +parseLineData + : SQUARE_BRACES_START NUMBER_WITH_DECIMAL parseLineData {$parseLineData.unshift(Number($NUMBER_WITH_DECIMAL)); $$ = $parseLineData} + | COMMA NUMBER_WITH_DECIMAL parseLineData {$parseLineData.unshift(Number($NUMBER_WITH_DECIMAL)); $$ = $parseLineData;} + | SQUARE_BRACES_END {$$ = []} ; -parseBar - : BAR BAR_DATA {yy.setBarData('', $2.split(',').map(d => Number(d.trim())));} - | BAR BAR_TITLE BAR_DATA {yy.setBarData($2.trim(), $3.split(',').map(d => Number(d.trim())));} +parseBarData + : SQUARE_BRACES_START NUMBER_WITH_DECIMAL parseBarData {$parseBarData.unshift(Number($NUMBER_WITH_DECIMAL)); $$ = $parseBarData} + | COMMA NUMBER_WITH_DECIMAL parseBarData {$parseBarData.unshift(Number($NUMBER_WITH_DECIMAL)); $$ = $parseBarData;} + | SQUARE_BRACES_END {$$ = []} ; parseXAxis - : AXIS_TITLE statement {yy.setXAxisTitle($1.trim());} - | AXIS_TITLE xAxisBandData statement {yy.setXAxisTitle($1.trim());} - | AXIS_TITLE AXIS_RANGE_DATA statement {yy.setXAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setXAxisRangeData(Number($$[0]), Number($$[1]));} + : text {yy.setXAxisTitle($text);} + | text xAxisBandData {yy.setXAxisTitle($text); yy.setXAxisBand($xAxisBandData);} + | text NUMBER_WITH_DECIMAL ARROW_DELIMITER NUMBER_WITH_DECIMAL {yy.setXAxisTitle($text); yy.setXAxisRangeData(Number($2), Number($4));} ; xAxisBandData - : AXIS_BAND_DATA xAxisBandData {yy.setXAxisBand($1.split(',').map(d => { let m = d.trim().match(/^(?:["]([^"]+)["]|([^\s"]+))$/); return m ? m[1] || m[2] : "";}));} - | AXIS_BAND_DATA_END + : SQUARE_BRACES_START text xAxisBandData {$xAxisBandData.unshift($text); $$ = $xAxisBandData} + | COMMA text xAxisBandData {$xAxisBandData.unshift($text); $$ = $xAxisBandData;} + | SQUARE_BRACES_END {$$ = []} ; parseYAxis - : AXIS_TITLE statement {yy.setYAxisTitle($1.trim());} - | AXIS_TITLE AXIS_RANGE_DATA statement {yy.setYAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setYAxisRangeData(Number($$[0]), Number($$[1]));} + : text {yy.setYAxisTitle($text);} + | text NUMBER_WITH_DECIMAL ARROW_DELIMITER NUMBER_WITH_DECIMAL {yy.setYAxisTitle($text); yy.setYAxisRangeData(Number($2), Number($4));} ; directive @@ -215,26 +180,22 @@ closeDirective : close_directive { yy.parseDirective('}%%', 'close_directive', 'xychart'); } ; -text: alphaNumToken - { $$={text:$1, type: 'text'};} - | text textNoTagsToken - { $$={text:$1.text+''+$2, type: $1.type};} +text: alphaNum + { $$={text:$alphaNum, type: 'text'};} | STR - { $$={text: $1, type: 'text'};} + { $$={text: $STR, type: 'text'};} | MD_STR - { $$={text: $1, type: 'markdown'};} + { $$={text: $MD_STR, type: 'markdown'};} ; alphaNum : alphaNumToken - {$$=$1;} + {$$=$alphaNumToken;} | alphaNum alphaNumToken - {$$=$1+''+$2;} + {$$=$alphaNum+''+$alphaNumToken;} ; -alphaNumToken : PUNCTUATION | AMP | NUM| ALPHA | COMMA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ; - -textNoTagsToken: alphaNumToken | SPACE | MINUS; +alphaNumToken : PUNCTUATION | AMP | NUM | ALPHA | PLUS | EQUALS | MULT | DOT | BRKT| UNDERSCORE ; %% diff --git a/packages/mermaid/src/diagrams/xychart/parser/xychart.jison.spec.ts b/packages/mermaid/src/diagrams/xychart/parser/xychart.jison.spec.ts index 605793110..24c6f2891 100644 --- a/packages/mermaid/src/diagrams/xychart/parser/xychart.jison.spec.ts +++ b/packages/mermaid/src/diagrams/xychart/parser/xychart.jison.spec.ts @@ -80,106 +80,190 @@ describe('Testing xychart jison file', () => { it('parse x-axis', () => { let str = 'xychart-beta \nx-axis xAxisName\n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ + text: 'xAxisName', + type: 'text', + }); clearMocks(); str = 'xychart-beta \nx-axis xAxisName \n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ + text: 'xAxisName', + type: 'text', + }); clearMocks(); str = 'xychart-beta \n x-axis "xAxisName has space"\n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName has space'); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ + text: 'xAxisName has space', + type: 'text', + }); clearMocks(); str = 'xychart-beta \n x-axis " xAxisName has space " \n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName has space'); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ + text: ' xAxisName has space ', + type: 'text', + }); clearMocks(); str = 'xychart-beta \nx-axis xAxisName 45.5 --> 33 \n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ + text: 'xAxisName', + type: 'text', + }); expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 33); clearMocks(); - str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2 ] \n '; + str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2a ] \n '; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setXAxisBand).toHaveBeenCalledWith(['cat1', 'cat2']); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ + text: 'xAxisName', + type: 'text', + }); + expect(mockDB.setXAxisBand).toHaveBeenCalledWith([ + { + text: 'cat1', + type: 'text', + }, + { text: 'cat2a', type: 'text' }, + ]); clearMocks(); str = `xychart-beta \n x-axis "this is x axis" [category1, "category 2", category3]\n`; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('this is x axis'); - expect(mockDB.setXAxisBand).toHaveBeenCalledWith(['category1', 'category 2', 'category3']); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'this is x axis', type: 'text' }); + expect(mockDB.setXAxisBand).toHaveBeenCalledWith([ + { text: 'category1', type: 'text' }, + { text: 'category 2', type: 'text' }, + { text: 'category3', type: 'text' }, + ]); clearMocks(); str = 'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 , cat3] \n '; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setXAxisBand).toHaveBeenCalledWith(['cat1 with space', 'cat2', 'cat3']); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setXAxisBand).toHaveBeenCalledWith([ + { text: 'cat1 with space', type: 'text' }, + { text: 'cat2', type: 'text' }, + { text: 'cat3', type: 'text' }, + ]); clearMocks(); str = 'xychart-beta \nx-axis xAxisName [ "cat1 with space" , cat2 asdf , cat3] \n '; - expect(parserFnConstructor(str)).toThrow(); + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setXAxisBand).toHaveBeenCalledWith([ + { text: 'cat1 with space', type: 'text' }, + { text: 'cat2asdf', type: 'text' }, + { text: 'cat3', type: 'text' }, + ]); }); it('parse y-axis', () => { let str = 'xychart-beta \ny-axis yAxisName\n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); clearMocks(); str = 'xychart-beta \ny-axis yAxisName \n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); clearMocks(); str = 'xychart-beta \n y-axis "yAxisName has space"\n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName has space'); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ + text: 'yAxisName has space', + type: 'text', + }); clearMocks(); str = 'xychart-beta \n y-axis " yAxisName has space " \n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName has space'); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ + text: ' yAxisName has space ', + type: 'text', + }); clearMocks(); str = 'xychart-beta \ny-axis yAxisName 45.5 --> 33 \n'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 33); + + clearMocks(); + + str = 'xychart-beta \ny-axis yAxisName [ 45.3, 33 ] \n'; + expect(parserFnConstructor(str)).toThrow(); + + clearMocks(); + + str = 'xychart-beta \ny-axis yAxisName\n'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + }); + it('parse both axis', () => { + let str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + + clearMocks(); + + str = 'xychart-beta \nx-axis xAxisName\n'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ + text: 'xAxisName', + type: 'text', + }); + + clearMocks(); + + str = 'xychart-beta \ny-axis yAxisName'; + expect(parserFnConstructor(str)).not.toThrow(); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + + clearMocks(); }); it('parse line Data', () => { let str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line lineTitle [23, 45, 56.6]'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle', [23, 45, 56.6]); + expect(mockDB.setLineData).toHaveBeenCalledWith( + { text: 'lineTitle', type: 'text' }, + [23, 45, 56.6] + ); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); clearMocks(); str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line "lineTitle with space" [ +23 , -45 , 56.6 ] '; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle with space', [23, -45, 56.6]); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setLineData).toHaveBeenCalledWith( + { text: 'lineTitle with space', type: 'text' }, + [23, -45, 56.6] + ); // set line data without title str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n line [ +23 , -45 , 56.6 ] '; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setLineData).toHaveBeenCalledWith('', [23, -45, 56.6]); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setLineData).toHaveBeenCalledWith({ text: '', type: 'text' }, [23, -45, 56.6]); clearMocks(); str = @@ -189,26 +273,32 @@ describe('Testing xychart jison file', () => { it('parse bar Data', () => { let str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar barTitle [23, 45, 56.6]'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle', [23, 45, 56.6]); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setBarData).toHaveBeenCalledWith( + { text: 'barTitle', type: 'text' }, + [23, 45, 56.6] + ); clearMocks(); str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar "barTitle with space" [ +23 , -45 , 56.6 ] '; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle with space', [23, -45, 56.6]); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setBarData).toHaveBeenCalledWith( + { text: 'barTitle with space', type: 'text' }, + [23, -45, 56.6] + ); clearMocks(); // set bar data without title str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar [ +23 , -45 , 56.6 ] '; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setBarData).toHaveBeenCalledWith('', [23, -45, 56.6]); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setBarData).toHaveBeenCalledWith({ text: '', type: 'text' }, [23, -45, 56.6]); clearMocks(); str = @@ -219,12 +309,24 @@ describe('Testing xychart jison file', () => { let str = 'xychart-beta\nx-axis xAxisName\ny-axis yAxisName\n bar barTitle1 [23, 45, 56.6] \n line lineTitle1 [11, 45.5, 67, 23] \n bar barTitle2 [13, 42, 56.89] \n line lineTitle2 [45, 99, 012]'; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName'); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName'); - expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle1', [23, 45, 56.6]); - expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle2', [13, 42, 56.89]); - expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle1', [11, 45.5, 67, 23]); - expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle2', [45, 99, 12]); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yAxisName', type: 'text' }); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'xAxisName', type: 'text' }); + expect(mockDB.setBarData).toHaveBeenCalledWith( + { text: 'barTitle1', type: 'text' }, + [23, 45, 56.6] + ); + expect(mockDB.setBarData).toHaveBeenCalledWith( + { text: 'barTitle2', type: 'text' }, + [13, 42, 56.89] + ); + expect(mockDB.setLineData).toHaveBeenCalledWith( + { text: 'lineTitle1', type: 'text' }, + [11, 45.5, 67, 23] + ); + expect(mockDB.setLineData).toHaveBeenCalledWith( + { text: 'lineTitle2', type: 'text' }, + [45, 99, 12] + ); clearMocks(); str = ` @@ -237,13 +339,29 @@ describe('Testing xychart jison file', () => { bar barTitle2 [13, 42, 56.89] line lineTitle2 [45, 99, 012]`; expect(parserFnConstructor(str)).not.toThrow(); - expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yaxisText'); + expect(mockDB.setYAxisTitle).toHaveBeenCalledWith({ text: 'yaxisText', type: 'text' }); expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(10, 150); - expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('this is x axis'); - expect(mockDB.setXAxisBand).toHaveBeenCalledWith(['category1', 'category 2', 'category3']); - expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle1', [23, 45, 56.6]); - expect(mockDB.setBarData).toHaveBeenCalledWith('barTitle2', [13, 42, 56.89]); - expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle1', [11, 45.5, 67, 23]); - expect(mockDB.setLineData).toHaveBeenCalledWith('lineTitle2', [45, 99, 12]); + expect(mockDB.setXAxisTitle).toHaveBeenCalledWith({ text: 'this is x axis', type: 'text' }); + expect(mockDB.setXAxisBand).toHaveBeenCalledWith([ + { text: 'category1', type: 'text' }, + { text: 'category 2', type: 'text' }, + { text: 'category3', type: 'text' }, + ]); + expect(mockDB.setBarData).toHaveBeenCalledWith( + { text: 'barTitle1', type: 'text' }, + [23, 45, 56.6] + ); + expect(mockDB.setBarData).toHaveBeenCalledWith( + { text: 'barTitle2', type: 'text' }, + [13, 42, 56.89] + ); + expect(mockDB.setLineData).toHaveBeenCalledWith( + { text: 'lineTitle1', type: 'text' }, + [11, 45.5, 67, 23] + ); + expect(mockDB.setLineData).toHaveBeenCalledWith( + { text: 'lineTitle2', type: 'text' }, + [45, 99, 12] + ); }); }); diff --git a/packages/mermaid/src/diagrams/xychart/xychartDb.ts b/packages/mermaid/src/diagrams/xychart/xychartDb.ts index a818037f3..8f1e80e61 100644 --- a/packages/mermaid/src/diagrams/xychart/xychartDb.ts +++ b/packages/mermaid/src/diagrams/xychart/xychartDb.ts @@ -1,5 +1,5 @@ // @ts-ignore: TODO Fix ts errors -import { adjust, channel, toHsla, isDark, lighten, darken } from 'khroma'; +import { adjust, channel } from 'khroma'; import mermaidAPI from '../../mermaidAPI.js'; import * as configApi from '../../config.js'; import { sanitizeText } from '../common/common.js'; @@ -133,6 +133,11 @@ let plotColorPalette = Array.isArray(xyChartThemeConfig.xychartPlotBaseColor) let hasSetXAxis = false; let hasSetYAxis = false; +interface NormalTextType { + type: 'text'; + text: string; +} + function textSanitizer(text: string) { return sanitizeText(text.trim(), config); } @@ -149,23 +154,23 @@ function setOrientation(oriantation: string) { xyChartConfig.chartOrientation = 'vertical'; } } -function setXAxisTitle(title: string) { - xyChartData.xAxis.title = textSanitizer(title); +function setXAxisTitle(title: NormalTextType) { + xyChartData.xAxis.title = textSanitizer(title.text); } function setXAxisRangeData(min: number, max: number) { xyChartData.xAxis = { type: 'linear', title: xyChartData.xAxis.title, min, max }; hasSetXAxis = true; } -function setXAxisBand(categories: string[]) { +function setXAxisBand(categories: NormalTextType[]) { xyChartData.xAxis = { type: 'band', title: xyChartData.xAxis.title, - categories: categories.map((c) => textSanitizer(c)), + categories: categories.map((c) => textSanitizer(c.text)), }; hasSetXAxis = true; } -function setYAxisTitle(title: string) { - xyChartData.yAxis.title = textSanitizer(title); +function setYAxisTitle(title: NormalTextType) { + xyChartData.yAxis.title = textSanitizer(title.text); } function setYAxisRangeData(min: number, max: number) { xyChartData.yAxis = { type: 'linear', title: xyChartData.yAxis.title, min, max }; @@ -224,7 +229,7 @@ function getPlotColorFromPalette(plotIndex: number): string { return plotColorPalette[plotIndex === 0 ? 0 : plotIndex % (plotColorPalette.length - 1)]; } -function setLineData(title: string, data: number[]) { +function setLineData(title: NormalTextType, data: number[]) { const plotData = transformDataWithOutCategory(data); xyChartData.plots.push({ type: 'line', @@ -235,7 +240,7 @@ function setLineData(title: string, data: number[]) { plotIndex++; } -function setBarData(title: string, data: number[]) { +function setBarData(title: NormalTextType, data: number[]) { const plotData = transformDataWithOutCategory(data); xyChartData.plots.push({ type: 'bar',