mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-09-17 22:39:56 +02:00
Now jison can parse xAxis and yAxis
This commit is contained in:
@@ -12,6 +12,15 @@
|
|||||||
%x acc_title
|
%x acc_title
|
||||||
%x acc_descr
|
%x acc_descr
|
||||||
%x acc_descr_multiline
|
%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 axis_data_band_str
|
||||||
%%
|
%%
|
||||||
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
\%\%\{ { this.begin('open_directive'); return 'open_directive'; }
|
||||||
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
<open_directive>((?:(?!\}\%\%)[^:.])*) { this.begin('type_directive'); return 'type_directive'; }
|
||||||
@@ -34,6 +43,34 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
|||||||
<acc_descr_multiline>[\}] { this.popState(); }
|
<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';}
|
||||||
|
|
||||||
|
"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>[,]" "* {this.begin("axis_data_band_capture")}
|
||||||
|
<axis_data_band_capture>["] {this.begin("axis_data_band_str");}
|
||||||
|
<axis_data_band_str>[^"]+ {return "AXIS_BAND_DATA";}
|
||||||
|
<axis_data_band_str>["]" "* {this.popState(); this.popState();}
|
||||||
|
<axis_data_band_capture>[^\s]+" "* {this.popState(); return "AXIS_BAND_DATA"}
|
||||||
|
<axis_data_band>[\]]" "* {this.popState(); return "AXIS_BAND_DATA_END"}
|
||||||
|
|
||||||
|
|
||||||
|
<axis_data>[\r\n]+ {this.popState(); this.popState();}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
["][`] { this.begin("md_string");}
|
["][`] { this.begin("md_string");}
|
||||||
<md_string>[^`"]+ { return "MD_STR";}
|
<md_string>[^`"]+ { return "MD_STR";}
|
||||||
@@ -42,8 +79,6 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
|||||||
<string>["] this.popState();
|
<string>["] this.popState();
|
||||||
<string>[^"]* return "STR";
|
<string>[^"]* return "STR";
|
||||||
|
|
||||||
" "*"xychart"" "* return 'XYCHART';
|
|
||||||
|
|
||||||
[A-Za-z]+ return 'ALPHA';
|
[A-Za-z]+ return 'ALPHA';
|
||||||
":" return 'COLON';
|
":" return 'COLON';
|
||||||
\+ return 'PLUS';
|
\+ return 'PLUS';
|
||||||
@@ -72,9 +107,14 @@ start
|
|||||||
: eol start
|
: eol start
|
||||||
| SPACE start
|
| SPACE start
|
||||||
| directive start
|
| directive start
|
||||||
| XYCHART document
|
| XYCHART chartConfig CHART_CONFIG_END document
|
||||||
|
| XYCHART CHART_CONFIG_END document
|
||||||
;
|
;
|
||||||
|
|
||||||
|
chartConfig
|
||||||
|
: chart_orientation {yy.setOrientation($1.trim());}
|
||||||
|
;
|
||||||
|
|
||||||
document
|
document
|
||||||
: /* empty */
|
: /* empty */
|
||||||
| document line
|
| document line
|
||||||
@@ -88,8 +128,25 @@ statement
|
|||||||
:
|
:
|
||||||
| SPACE statement
|
| SPACE statement
|
||||||
| directive
|
| directive
|
||||||
|
| X_AXIS parseXAxis
|
||||||
|
| Y_AXIS parseYAxis
|
||||||
;
|
;
|
||||||
|
|
||||||
|
parseXAxis
|
||||||
|
: AXIS_TITLE {yy.setXAxisTitle($1.trim());}
|
||||||
|
| AXIS_TITLE xAxisBandData {yy.setXAxisTitle($1.trim());}
|
||||||
|
| AXIS_TITLE AXIS_RANGE_DATA {yy.setXAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setXAxisRangeData(Number($$[0]), Number($$[1]));}
|
||||||
|
;
|
||||||
|
|
||||||
|
xAxisBandData
|
||||||
|
: AXIS_BAND_DATA xAxisBandData {yy.addXAxisBand($1.trim());}
|
||||||
|
| AXIS_BAND_DATA_END
|
||||||
|
;
|
||||||
|
|
||||||
|
parseYAxis
|
||||||
|
: AXIS_TITLE {yy.setYAxisTitle($1.trim());}
|
||||||
|
| AXIS_TITLE AXIS_RANGE_DATA {yy.setYAxisTitle($1.trim()); $$ = $2.split("-->"); yy.setYAxisRangeData(Number($$[0]), Number($$[1]));}
|
||||||
|
;
|
||||||
|
|
||||||
directive
|
directive
|
||||||
: openDirective typeDirective closeDirective
|
: openDirective typeDirective closeDirective
|
||||||
@@ -115,7 +172,7 @@ argDirective
|
|||||||
;
|
;
|
||||||
|
|
||||||
closeDirective
|
closeDirective
|
||||||
: close_directive { yy.parseDirective('}%%', 'close_directive', 'quadrantChart'); }
|
: close_directive { yy.parseDirective('}%%', 'close_directive', 'xychart'); }
|
||||||
;
|
;
|
||||||
|
|
||||||
text: alphaNumToken
|
text: alphaNumToken
|
||||||
|
@@ -0,0 +1,140 @@
|
|||||||
|
// @ts-ignore: TODO Fix ts errors
|
||||||
|
import { parser } from './xychart.jison';
|
||||||
|
import { Mock, vi } from 'vitest';
|
||||||
|
|
||||||
|
const parserFnConstructor = (str: string) => {
|
||||||
|
return () => {
|
||||||
|
parser.parse(str);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockDB: Record<string, Mock<any, any>> = {
|
||||||
|
parseDirective: vi.fn(),
|
||||||
|
setOrientation: vi.fn(),
|
||||||
|
setXAxisTitle: vi.fn(),
|
||||||
|
setXAxisRangeData: vi.fn(),
|
||||||
|
addXAxisBand: vi.fn(),
|
||||||
|
setYAxisTitle: vi.fn(),
|
||||||
|
setYAxisRangeData: vi.fn(),
|
||||||
|
addYAxisBand: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
function clearMocks() {
|
||||||
|
for (const key in mockDB) {
|
||||||
|
mockDB[key].mockRestore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('Testing xychart jison file', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
parser.yy = mockDB;
|
||||||
|
clearMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error if xychart-beta text is not there', () => {
|
||||||
|
const str = 'xychart-beta-1';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw error if only xychart is there', () => {
|
||||||
|
const str = 'xychart-beta';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to parse directive', () => {
|
||||||
|
const str =
|
||||||
|
'%%{init: {"xychart": {"chartWidth": 600, "chartHeight": 600} } }%% \n xychart-beta';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.parseDirective.mock.calls[0]).toEqual(['%%{', 'open_directive']);
|
||||||
|
expect(mockDB.parseDirective.mock.calls[1]).toEqual(['init', 'type_directive']);
|
||||||
|
expect(mockDB.parseDirective.mock.calls[2]).toEqual([
|
||||||
|
'{"xychart": {"chartWidth": 600, "chartHeight": 600} }',
|
||||||
|
'arg_directive',
|
||||||
|
]);
|
||||||
|
expect(mockDB.parseDirective.mock.calls[3]).toEqual(['}%%', 'close_directive', 'xychart']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parse chart orientation', () => {
|
||||||
|
let str = 'xychart-beta vertical';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setOrientation).toHaveBeenCalledWith('vertical');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta horizontal ';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setOrientation).toHaveBeenCalledWith('horizontal');
|
||||||
|
|
||||||
|
str = 'xychart-beta abc';
|
||||||
|
expect(parserFnConstructor(str)).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('parse x-axis', () => {
|
||||||
|
let str = 'xychart-beta \nx-axis xAxisName\n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \nx-axis xAxisName \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \n x-axis "xAxisName has space"\n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName has space');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \n x-axis " xAxisName has space " \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName has space');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
str = 'xychart-beta \nx-axis xAxisName 45.5 --> 33 \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
|
expect(mockDB.setXAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \nx-axis xAxisName [ "cat1" , cat2 ] \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setXAxisTitle).toHaveBeenCalledWith('xAxisName');
|
||||||
|
expect(mockDB.addXAxisBand).toHaveBeenCalledTimes(2);
|
||||||
|
expect(mockDB.addXAxisBand).toHaveBeenNthCalledWith(1, "cat2");
|
||||||
|
expect(mockDB.addXAxisBand).toHaveBeenNthCalledWith(2, "cat1");
|
||||||
|
});
|
||||||
|
it('parse y-axis', () => {
|
||||||
|
let str = 'xychart-beta \ny-axis yAxisName\n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \ny-axis yAxisName \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \n y-axis "yAxisName has space"\n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName has space');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
|
||||||
|
str = 'xychart-beta \n y-axis " yAxisName has space " \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName has space');
|
||||||
|
|
||||||
|
clearMocks();
|
||||||
|
str = 'xychart-beta \ny-axis yAxisName 45.5 --> 33 \n';
|
||||||
|
expect(parserFnConstructor(str)).not.toThrow();
|
||||||
|
expect(mockDB.setYAxisTitle).toHaveBeenCalledWith('yAxisName');
|
||||||
|
expect(mockDB.setYAxisRangeData).toHaveBeenCalledWith(45.5, 33);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user