diff --git a/cypress/integration/rendering/theme.spec.js b/cypress/integration/rendering/theme.spec.js
index f42dd0c2f..30a7efb7f 100644
--- a/cypress/integration/rendering/theme.spec.js
+++ b/cypress/integration/rendering/theme.spec.js
@@ -1,5 +1,30 @@
import { imgSnapshotTest } from '../../helpers/util.js';
+describe('themeCSS balancing, it', () => {
+ it('should not allow unbalanced CSS definitions', () => {
+ imgSnapshotTest(
+ `
+ %%{init: { 'themeCSS': '} * { background: red }' } }%%
+ flowchart TD
+ a --> b
+ `,
+ {}
+ );
+ cy.get('svg');
+ });
+ it('should not allow unbalanced CSS definitions 2', () => {
+ imgSnapshotTest(
+ `
+ %%{init: { 'themeCSS': '\u007D * { background: red }' } }%%
+ flowchart TD
+ a2 --> b2
+ `,
+ {}
+ );
+ cy.get('svg');
+ });
+});
+
describe('Pie Chart', () => {
// beforeEach(()=>{
// cy.clock((new Date('2014-06-09')).getTime());
diff --git a/cypress/platform/css1.html b/cypress/platform/css1.html
new file mode 100644
index 000000000..f02892123
--- /dev/null
+++ b/cypress/platform/css1.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+ Mermaid Quick Test Page
+
+
+
+
+
+ %%{init: { 'themeCSS': '} * { background: lightblue }' } }%%
+ flowchart TD
+ a --> b
+
+
+ %%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
+ flowchart LR
+ subgraph A
+ a --> b
+ end
+ subgraph B
+ i -->f
+ end
+ A --> B
+
+
+
+
+
diff --git a/src/defaultConfig.js b/src/defaultConfig.js
index 92d8b5771..305ba0867 100644
--- a/src/defaultConfig.js
+++ b/src/defaultConfig.js
@@ -37,6 +37,7 @@ const config = {
themeCSS: undefined,
/* **maxTextSize** - The maximum allowed size of the users text diamgram */
maxTextSize: 50000,
+ darkMode: false,
/**
* | Parameter | Description | Type | Required | Values |
diff --git a/src/mermaidAPI.js b/src/mermaidAPI.js
index 0e73b3032..e51f22468 100755
--- a/src/mermaidAPI.js
+++ b/src/mermaidAPI.js
@@ -60,7 +60,7 @@ import { attachFunctions } from './interactionDb';
import { log, setLogLevel } from './logger';
import getStyles from './styles';
import theme from './themes';
-import utils, { directiveSanitizer, assignWithDepth } from './utils';
+import utils, { directiveSanitizer, assignWithDepth, sanitizeCss } from './utils';
/**
* @param text
@@ -223,6 +223,7 @@ const render = function (id, _txt, cb, container) {
let txt = _txt;
const graphInit = utils.detectInit(txt);
if (graphInit) {
+ directiveSanitizer(graphInit);
configApi.addDirective(graphInit);
}
let cnf = configApi.getConfig();
@@ -533,6 +534,9 @@ const handleDirective = function (p, directive, type) {
p.setWrap(directive.type === 'wrap');
}
break;
+ case 'themeCss':
+ log.warn('themeCss encountered');
+ break;
default:
log.warn(
`Unhandled directive: source: '%%{${directive.type}: ${JSON.stringify(
diff --git a/src/utils.js b/src/utils.js
index 90a087f9f..012fb98d3 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -974,6 +974,11 @@ export const directiveSanitizer = (args) => {
log.debug('sanitize deleting constr option', key);
delete args[key];
}
+
+ if (key.indexOf('themeCSS') >= 0) {
+ log.debug('sanitizing themeCss option');
+ args[key] = sanitizeCss(args[key]);
+ }
if (configKeys.indexOf(key) < 0) {
log.debug('sanitize deleting option', key);
delete args[key];
@@ -987,6 +992,16 @@ export const directiveSanitizer = (args) => {
}
}
};
+export const sanitizeCss = (str) => {
+ const stringsearch = 'o';
+ const startCnt = (str.match(/\{/g) || []).length;
+ const endCnt = (str.match(/\}/g) || []).length;
+ if (startCnt !== endCnt) {
+ return '{ /* ERROR: Unbalanced CSS */ }';
+ }
+ // Todo add more checks here
+ return str;
+};
export default {
assignWithDepth,
@@ -1013,4 +1028,5 @@ export default {
entityDecode,
initIdGeneratior,
directiveSanitizer,
+ sanitizeCss,
};