Add directive parsing functionality to timeline diagram

This commit is contained in:
ashishj 2023-01-19 19:03:05 +01:00
parent 68609fd8d0
commit 652a42fe1a
10 changed files with 136 additions and 103 deletions

View File

@ -55,7 +55,7 @@
</head>
<body>
<div>Security check</div>
<pre id="diagram" class="mermaid">
<pre id="diagram" class="mermaid2">
timeline
title My day
section section with no tasks
@ -71,7 +71,7 @@
I am a big big big tasks
I am not so big tasks
</pre>
<pre id="diagram" class="mermaid">
<pre id="diagram" class="mermaid2">
timeline
title England's History Timeline
section Stone Age
@ -85,21 +85,7 @@
</pre>
<pre id="diagram" class="mermaid">
timeline
title History of Social Media Platform
section Rise of Social Media
2002 : LinkedIn
2004 : Facebook : Google : Pixar
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008s : Instagram
2010 : Pinterest
</pre>
<pre id="diagram" class="mermaid">
---
timeline:disableMulticolor: true
---
%%{init: { 'logLevel': 'debug', 'theme': 'default', 'timeline': {'disableMulticolor':false} } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
@ -111,6 +97,22 @@ timeline:disableMulticolor: true
2010 : Pinterest
</pre>
<pre id="diagram" class="mermaid">
%%{init: { 'logLevel': 'debug', 'theme': 'default', 'themeVariables': {
'cScale0': '#ffffff',
'cScale1': '#00ff00',
'cScale2': '#0000ff',
} } }%%
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google : Pixar
2005 : Youtube
2006 : Twitter
2007 : Tumblr
2008s : Instagram
2010 : Pinterest
</pre>
<pre id="diagram" class="mermaid2">
timeline
title History of Social Media Platform
2002 : LinkedIn

View File

@ -23,7 +23,10 @@ export const log: Record<keyof typeof LEVELS, typeof console.log> = {
export let setLogLevel: (level: keyof typeof LEVELS | number | string) => void;
export let getConfig: () => object;
export let sanitizeText: (str: string) => string;
export const getCommonDb=() => localCommonDb;
export const getCommonDb = () => localCommonDb;
export let parseDirective = (p: any, statement: string, context: string, type: string) => {
return;
}
/**
* Placeholder for the real function that will be injected by mermaid.
*/
@ -52,9 +55,11 @@ export const injectUtils = (
_getConfig: any,
_sanitizeText: any,
_setupGraphViewbox: any,
_commonDb: any
_commonDb: any,
_parseDirective: any
) => {
_log.info('Mermaid utils injected into timeline-diagram');
_log.info('123 ' , _parseDirective);
log.trace = _log.trace;
log.debug = _log.debug;
log.info = _log.info;
@ -66,5 +71,6 @@ export const injectUtils = (
sanitizeText = _sanitizeText;
setupGraphViewbox = _setupGraphViewbox;
localCommonDb = _commonDb;
parseDirective = _parseDirective;
};

View File

@ -1,4 +1,4 @@
import { getCommonDb as _getCommonDb,log } from './mermaidUtils';
import { getCommonDb as _getCommonDb, parseDirective as _parseDirective ,log } from './mermaidUtils';
let currentSection = '';
let currentTaskId = 0;
@ -9,6 +9,10 @@ const rawTasks = [];
export const getCommonDb = _getCommonDb;
export const parseDirective = ( statement, context, type) => {
_parseDirective(this, statement, context, type);
};
export const clear = function () {
sections.length = 0;
tasks.length = 0;
@ -79,14 +83,14 @@ const compileTasks = function () {
};
let allProcessed = true;
for (let i = 0; i < rawTasks.length; i++) {
for (const [i, rawTask] of rawTasks.entries()) {
compileTask(i);
allProcessed = allProcessed && rawTasks[i].processed;
allProcessed = allProcessed && rawTask.processed;
}
return allProcessed;
};
log.info('456 parseDirective',parseDirective);
export default {
clear,
getCommonDb,
@ -96,5 +100,6 @@ export default {
addTask,
addTaskOrg,
addEvent,
parseDirective
};

View File

@ -17,7 +17,8 @@ export const draw = function (text, id, version, diagObj) {
//1. Fetch the configuration
const conf = getConfig();
const LEFT_MARGIN = conf.leftMargin?conf.leftMargin:50;
//log conf
log.info('conf', conf);
//2. Clear the diagram db before parsing
diagObj.db.clear();

View File

@ -314,6 +314,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
actorColours?: string[];
sectionFills?: string[];
sectionColours?: string[];
disableMulticolor?: boolean;
}
export interface GanttDiagramConfig extends BaseDiagramConfig {

View File

@ -984,6 +984,8 @@ const config: Partial<MermaidConfig> = {
*/
useMaxWidth: true,
/**
* | Parameter | Description | Type | Required | Values |
* | ----------- | --------------------------------- | ---- | -------- | ----------- |
@ -1009,6 +1011,7 @@ const config: Partial<MermaidConfig> = {
sectionFills: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'],
sectionColours: ['#fff'],
disableMulticolor: false,
},
class: {
/**

View File

@ -5,7 +5,8 @@ import { sanitizeText as _sanitizeText } from '../diagrams/common/common';
import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox';
import { addStylesForDiagram } from '../styles';
import { DiagramDefinition, DiagramDetector } from './types';
import * as _commonDb from '../commonDb';
import * as _commonDb from '../commonDb';
import { parseDirective as _parseDirective} from '../directiveUtils';
/*
@ -19,6 +20,7 @@ export const getConfig = _getConfig;
export const sanitizeText = (text: string) => _sanitizeText(text, getConfig());
export const setupGraphViewbox = _setupGraphViewbox;
export const getCommonDb = () => { return _commonDb };
export const parseDirective = (p: any, statement: string, context: string, type: string)=>_parseDirective(p, statement, context, type);
const diagrams: Record<string, DiagramDefinition> = {};
export interface Detectors {
@ -49,7 +51,9 @@ export const registerDiagram = (
addStylesForDiagram(id, diagram.styles);
if (diagram.injectUtils) {
diagram.injectUtils(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox,getCommonDb());
console.log('parseDirective', parseDirective);
diagram.injectUtils(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox,getCommonDb(),parseDirective);
}
};

View File

@ -7,6 +7,7 @@ export interface InjectUtils {
_sanitizeText: any;
_setupGraphViewbox: any;
_commonDb: any;
_parseDirective: any;
}
/**
@ -31,7 +32,8 @@ export interface DiagramDefinition {
_getConfig: InjectUtils['_getConfig'],
_sanitizeText: InjectUtils['_sanitizeText'],
_setupGraphViewbox: InjectUtils['_setupGraphViewbox'],
_commonDb: InjectUtils['_commonDb']
_commonDb: InjectUtils['_commonDb'],
_parseDirective: InjectUtils['_parseDirective'],
) => void;
}

View File

@ -0,0 +1,84 @@
import * as configApi from './config';
import { log } from './logger';
import { directiveSanitizer } from './utils';
let currentDirective: { type?: string; args?: any } | undefined = {};
export const parseDirective = function (p: any, statement: string, context: string, type: string): void {
log.info('parseDirective is being called', statement, context, type);
try {
if (statement !== undefined) {
statement = statement.trim();
switch (context) {
case 'open_directive':
currentDirective = {};
break;
case 'type_directive':
if (!currentDirective) {
throw new Error('currentDirective is undefined');
}
currentDirective.type = statement.toLowerCase();
break;
case 'arg_directive':
if (!currentDirective) {
throw new Error('currentDirective is undefined');
}
currentDirective.args = JSON.parse(statement);
break;
case 'close_directive':
handleDirective(p, currentDirective, type);
currentDirective = undefined;
break;
}
}
} catch (error) {
log.error(
`Error while rendering sequenceDiagram directive: ${statement} jison context: ${context}`
);
// @ts-ignore: TODO Fix ts errors
log.error(error.message);
}
};
const handleDirective = function (p: any, directive: any, type: string): void {
log.info(`Directive type=${directive.type} with args:`, directive.args);
switch (directive.type) {
case 'init':
case 'initialize': {
['config'].forEach((prop) => {
if (directive.args[prop] !== undefined) {
if (type === 'flowchart-v2') {
type = 'flowchart';
}
directive.args[type] = directive.args[prop];
delete directive.args[prop];
}
});
log.info('sanitize in handleDirective', directive.args);
directiveSanitizer(directive.args);
log.info('sanitize in handleDirective (done)', directive.args);
configApi.addDirective(directive.args);
break;
}
case 'wrap':
case 'nowrap':
if (p && p['setWrap']) {
p.setWrap(directive.type === 'wrap');
}
break;
case 'themeCss':
log.warn('themeCss encountered');
break;
default:
log.warn(
`Unhandled directive: source: '%%{${directive.type}: ${JSON.stringify(
directive.args ? directive.args : {}
)}}%%`,
directive
);
break;
}
};

View File

@ -31,6 +31,7 @@ import { MermaidConfig } from './config.type';
import { evaluate } from './diagrams/common/common';
import isEmpty from 'lodash-es/isEmpty.js';
import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility';
import { parseDirective } from './directiveUtils';
// diagram names that support classDef statements
const CLASSDEF_DIAGRAMS = ['graph', 'flowchart', 'flowchart-v2', 'stateDiagram', 'stateDiagram-v2'];
@ -777,82 +778,6 @@ const renderAsync = async function (
return svgCode;
};
let currentDirective: { type?: string; args?: any } | undefined = {};
const parseDirective = function (p: any, statement: string, context: string, type: string): void {
try {
if (statement !== undefined) {
statement = statement.trim();
switch (context) {
case 'open_directive':
currentDirective = {};
break;
case 'type_directive':
if (!currentDirective) {
throw new Error('currentDirective is undefined');
}
currentDirective.type = statement.toLowerCase();
break;
case 'arg_directive':
if (!currentDirective) {
throw new Error('currentDirective is undefined');
}
currentDirective.args = JSON.parse(statement);
break;
case 'close_directive':
handleDirective(p, currentDirective, type);
currentDirective = undefined;
break;
}
}
} catch (error) {
log.error(
`Error while rendering sequenceDiagram directive: ${statement} jison context: ${context}`
);
// @ts-ignore: TODO Fix ts errors
log.error(error.message);
}
};
const handleDirective = function (p: any, directive: any, type: string): void {
log.debug(`Directive type=${directive.type} with args:`, directive.args);
switch (directive.type) {
case 'init':
case 'initialize': {
['config'].forEach((prop) => {
if (directive.args[prop] !== undefined) {
if (type === 'flowchart-v2') {
type = 'flowchart';
}
directive.args[type] = directive.args[prop];
delete directive.args[prop];
}
});
log.debug('sanitize in handleDirective', directive.args);
directiveSanitizer(directive.args);
log.debug('sanitize in handleDirective (done)', directive.args);
configApi.addDirective(directive.args);
break;
}
case 'wrap':
case 'nowrap':
if (p && p['setWrap']) {
p.setWrap(directive.type === 'wrap');
}
break;
case 'themeCss':
log.warn('themeCss encountered');
break;
default:
log.warn(
`Unhandled directive: source: '%%{${directive.type}: ${JSON.stringify(
directive.args ? directive.args : {}
)}}%%`,
directive
);
break;
}
};
/**
* @param options - Initial Mermaid options