From 652a42fe1aed7911a781a84716940a973b995639 Mon Sep 17 00:00:00 2001 From: ashishj Date: Thu, 19 Jan 2023 19:03:05 +0100 Subject: [PATCH] Add directive parsing functionality to timeline diagram --- cypress/platform/ashish2.html | 36 ++++---- packages/mermaid-timeline/src/mermaidUtils.ts | 10 ++- packages/mermaid-timeline/src/timelineDb.js | 13 ++- .../mermaid-timeline/src/timelineRenderer.ts | 3 +- packages/mermaid/src/config.type.ts | 1 + packages/mermaid/src/defaultConfig.ts | 3 + .../mermaid/src/diagram-api/diagramAPI.ts | 8 +- packages/mermaid/src/diagram-api/types.ts | 4 +- packages/mermaid/src/directiveUtils.ts | 84 +++++++++++++++++++ packages/mermaid/src/mermaidAPI.ts | 77 +---------------- 10 files changed, 136 insertions(+), 103 deletions(-) create mode 100644 packages/mermaid/src/directiveUtils.ts diff --git a/cypress/platform/ashish2.html b/cypress/platform/ashish2.html index f1ebaa827..f77f95606 100644 --- a/cypress/platform/ashish2.html +++ b/cypress/platform/ashish2.html @@ -55,7 +55,7 @@
Security check
-
+    
  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
     
-
+     
  timeline
         title England's History Timeline
         section Stone Age
@@ -85,21 +85,7 @@
 
     
- 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
-    
-
----
-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
     
+      %%{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
+    
+
  timeline
         title History of Social Media Platform
           2002 : LinkedIn
diff --git a/packages/mermaid-timeline/src/mermaidUtils.ts b/packages/mermaid-timeline/src/mermaidUtils.ts
index 1061f87cf..af3f97571 100644
--- a/packages/mermaid-timeline/src/mermaidUtils.ts
+++ b/packages/mermaid-timeline/src/mermaidUtils.ts
@@ -23,7 +23,10 @@ export const log: Record = {
 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;
 
 };
diff --git a/packages/mermaid-timeline/src/timelineDb.js b/packages/mermaid-timeline/src/timelineDb.js
index dda3a97cb..e5de2aee3 100644
--- a/packages/mermaid-timeline/src/timelineDb.js
+++ b/packages/mermaid-timeline/src/timelineDb.js
@@ -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
 };
 
diff --git a/packages/mermaid-timeline/src/timelineRenderer.ts b/packages/mermaid-timeline/src/timelineRenderer.ts
index 063d070a7..5ed6c554e 100644
--- a/packages/mermaid-timeline/src/timelineRenderer.ts
+++ b/packages/mermaid-timeline/src/timelineRenderer.ts
@@ -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();
 
diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts
index 63fe078fa..474075824 100644
--- a/packages/mermaid/src/config.type.ts
+++ b/packages/mermaid/src/config.type.ts
@@ -314,6 +314,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
   actorColours?: string[];
   sectionFills?: string[];
   sectionColours?: string[];
+  disableMulticolor?: boolean;
 }
 
 export interface GanttDiagramConfig extends BaseDiagramConfig {
diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts
index 5bb4a1bd8..cee89e4aa 100644
--- a/packages/mermaid/src/defaultConfig.ts
+++ b/packages/mermaid/src/defaultConfig.ts
@@ -984,6 +984,8 @@ const config: Partial = {
      */
     useMaxWidth: true,
 
+
+
     /**
      * | Parameter   | Description                       | Type | Required | Values      |
      * | ----------- | --------------------------------- | ---- | -------- | ----------- |
@@ -1009,6 +1011,7 @@ const config: Partial = {
 
     sectionFills: ['#191970', '#8B008B', '#4B0082', '#2F4F4F', '#800000', '#8B4513', '#00008B'],
     sectionColours: ['#fff'],
+    disableMulticolor: false,
   },
   class: {
     /**
diff --git a/packages/mermaid/src/diagram-api/diagramAPI.ts b/packages/mermaid/src/diagram-api/diagramAPI.ts
index ddb22df2c..574e72fbc 100644
--- a/packages/mermaid/src/diagram-api/diagramAPI.ts
+++ b/packages/mermaid/src/diagram-api/diagramAPI.ts
@@ -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 = {};
 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);
   }
 };
 
diff --git a/packages/mermaid/src/diagram-api/types.ts b/packages/mermaid/src/diagram-api/types.ts
index 22b4c1c8c..883cf3987 100644
--- a/packages/mermaid/src/diagram-api/types.ts
+++ b/packages/mermaid/src/diagram-api/types.ts
@@ -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;
 }
 
diff --git a/packages/mermaid/src/directiveUtils.ts b/packages/mermaid/src/directiveUtils.ts
new file mode 100644
index 000000000..79888daf9
--- /dev/null
+++ b/packages/mermaid/src/directiveUtils.ts
@@ -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;
+  }
+};
diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts
index 5bf11fad1..ed2f547e9 100644
--- a/packages/mermaid/src/mermaidAPI.ts
+++ b/packages/mermaid/src/mermaidAPI.ts
@@ -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