Remove clone css style code
This commit is contained in:
parent
72493b7a8b
commit
d430019b44
|
@ -58,10 +58,6 @@ var config = {
|
||||||
* * fatal: 5
|
* * fatal: 5
|
||||||
*/
|
*/
|
||||||
logLevel: 5,
|
logLevel: 5,
|
||||||
/**
|
|
||||||
* **cloneCssStyles** - This options controls whether or not the css rules should be copied into the generated svg
|
|
||||||
*/
|
|
||||||
cloneCssStyles: true,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* **startOnLoad** - This options controls whether or mermaid starts when the page loads
|
* **startOnLoad** - This options controls whether or mermaid starts when the page loads
|
||||||
|
@ -213,7 +209,6 @@ var config = {
|
||||||
* **axisFormatter** - formatting of the axis, this might need adjustment to match your locale and preferences
|
* **axisFormatter** - formatting of the axis, this might need adjustment to match your locale and preferences
|
||||||
*/
|
*/
|
||||||
axisFormatter: [
|
axisFormatter: [
|
||||||
|
|
||||||
// Within a day
|
// Within a day
|
||||||
['%I:%M', function (d) {
|
['%I:%M', function (d) {
|
||||||
return d.getHours()
|
return d.getHours()
|
||||||
|
@ -390,7 +385,6 @@ var render = function (id, txt, cb, container) {
|
||||||
|
|
||||||
var element = d3.select('#d' + id).node()
|
var element = d3.select('#d' + id).node()
|
||||||
var graphType = utils.detectType(txt)
|
var graphType = utils.detectType(txt)
|
||||||
// var classes = {}
|
|
||||||
switch (graphType) {
|
switch (graphType) {
|
||||||
case 'gitGraph':
|
case 'gitGraph':
|
||||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||||
|
@ -401,59 +395,37 @@ var render = function (id, txt, cb, container) {
|
||||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||||
flowRenderer.setConf(config.flowchart)
|
flowRenderer.setConf(config.flowchart)
|
||||||
flowRenderer.draw(txt, id, false)
|
flowRenderer.draw(txt, id, false)
|
||||||
// if (config.cloneCssStyles) {
|
|
||||||
// classes = flowRenderer.getClasses(txt, false)
|
|
||||||
// utils.cloneCssStyles(element.firstChild, classes)
|
|
||||||
// }
|
|
||||||
break
|
break
|
||||||
case 'dotGraph':
|
case 'dotGraph':
|
||||||
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.flowchart.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||||
flowRenderer.setConf(config.flowchart)
|
flowRenderer.setConf(config.flowchart)
|
||||||
flowRenderer.draw(txt, id, true)
|
flowRenderer.draw(txt, id, true)
|
||||||
// if (config.cloneCssStyles) {
|
|
||||||
// classes = flowRenderer.getClasses(txt, true)
|
|
||||||
// utils.cloneCssStyles(element.firstChild, classes)
|
|
||||||
// }
|
|
||||||
break
|
break
|
||||||
case 'sequenceDiagram':
|
case 'sequenceDiagram':
|
||||||
config.sequenceDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.sequenceDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||||
seq.setConf(config.sequenceDiagram)
|
seq.setConf(config.sequenceDiagram)
|
||||||
seq.draw(txt, id)
|
seq.draw(txt, id)
|
||||||
// if (config.cloneCssStyles) {
|
|
||||||
// utils.cloneCssStyles(element.firstChild, [])
|
|
||||||
// }
|
|
||||||
break
|
break
|
||||||
case 'gantt':
|
case 'gantt':
|
||||||
config.gantt.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.gantt.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||||
gantt.setConf(config.gantt)
|
gantt.setConf(config.gantt)
|
||||||
gantt.draw(txt, id)
|
gantt.draw(txt, id)
|
||||||
// if (config.cloneCssStyles) {
|
|
||||||
// utils.cloneCssStyles(element.firstChild, [])
|
|
||||||
// }
|
|
||||||
break
|
break
|
||||||
case 'classDiagram':
|
case 'classDiagram':
|
||||||
config.classDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.classDiagram.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||||
classRenderer.setConf(config.classDiagram)
|
classRenderer.setConf(config.classDiagram)
|
||||||
classRenderer.draw(txt, id)
|
classRenderer.draw(txt, id)
|
||||||
// if (config.cloneCssStyles) {
|
|
||||||
// utils.cloneCssStyles(element.firstChild, [])
|
|
||||||
// }
|
|
||||||
break
|
break
|
||||||
case 'info':
|
case 'info':
|
||||||
config.info.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
config.info.arrowMarkerAbsolute = config.arrowMarkerAbsolute
|
||||||
info.draw(txt, id, version())
|
info.draw(txt, id, version())
|
||||||
// if (config.cloneCssStyles) {
|
|
||||||
// utils.cloneCssStyles(element.firstChild, [])
|
|
||||||
// }
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert inline style into svg
|
// insert inline style into svg
|
||||||
const svg = element.firstChild
|
const svg = element.firstChild
|
||||||
const s = document.createElement('style')
|
const s = document.createElement('style')
|
||||||
// s.innerHTML = '/* <![CDATA[ */\n'
|
|
||||||
s.innerHTML = forestStyle
|
s.innerHTML = forestStyle
|
||||||
// s.innerHTML += '/* ]]> */\n'
|
|
||||||
svg.insertBefore(s, svg.firstChild)
|
svg.insertBefore(s, svg.firstChild)
|
||||||
|
|
||||||
d3.select('#d' + id).selectAll('foreignobject div').attr('xmlns', 'http://www.w3.org/1999/xhtml')
|
d3.select('#d' + id).selectAll('foreignobject div').attr('xmlns', 'http://www.w3.org/1999/xhtml')
|
||||||
|
|
|
@ -33,7 +33,6 @@ describe('when using mermaidAPI and ', function () {
|
||||||
expect(config.testObject.test1).toBe(1)
|
expect(config.testObject.test1).toBe(1)
|
||||||
expect(config.testObject.test2).toBe(false)
|
expect(config.testObject.test2).toBe(false)
|
||||||
expect(config.testObject.test3).toBe(true)
|
expect(config.testObject.test3).toBe(true)
|
||||||
expect(config.cloneCssStyles).toBe(orgConfig.cloneCssStyles)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('checking validity of input ', function () {
|
describe('checking validity of input ', function () {
|
||||||
|
|
80
src/utils.js
80
src/utils.js
|
@ -47,85 +47,6 @@ export const detectType = function (text) {
|
||||||
return 'graph'
|
return 'graph'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies all relevant CSS content into the graph SVG.
|
|
||||||
* This allows the SVG to be copied as is while keeping class based styling
|
|
||||||
* @param {element} svg The root element of the SVG
|
|
||||||
* @param {object} Hash table of class definitions from the graph definition
|
|
||||||
*/
|
|
||||||
export const cloneCssStyles = function (svg, classes) {
|
|
||||||
let usedStyles = ''
|
|
||||||
const sheets = document.styleSheets
|
|
||||||
let rule
|
|
||||||
for (let i = 0; i < sheets.length; i++) {
|
|
||||||
// Avoid multiple inclusion on pages with multiple graphs
|
|
||||||
if (sheets[i].title !== 'mermaid-svg-internal-css') {
|
|
||||||
try {
|
|
||||||
const rules = sheets[i].cssRules
|
|
||||||
if (rules !== null) {
|
|
||||||
for (let j = 0; j < rules.length; j++) {
|
|
||||||
rule = rules[j]
|
|
||||||
if (typeof (rule.style) !== 'undefined') {
|
|
||||||
const elems = svg.querySelectorAll(rule.selectorText)
|
|
||||||
if (elems.length > 0) {
|
|
||||||
usedStyles += rule.selectorText + ' { ' + rule.style.cssText + '}\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
if (typeof (rule) !== 'undefined') {
|
|
||||||
logger.warn('Invalid CSS selector "' + rule.selectorText + '"', err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let defaultStyles = ''
|
|
||||||
let embeddedStyles = ''
|
|
||||||
for (const className in classes) {
|
|
||||||
if (classes.hasOwnProperty(className) && typeof (className) !== 'undefined') {
|
|
||||||
if (className === 'default') {
|
|
||||||
if (classes.default.styles instanceof Array) {
|
|
||||||
defaultStyles += '#' + svg.id.trim() + ' .node' + '>rect { ' + classes[className].styles.join('; ') + '; }\n'
|
|
||||||
}
|
|
||||||
if (classes.default.nodeLabelStyles instanceof Array) {
|
|
||||||
defaultStyles += '#' + svg.id.trim() + ' .node text ' + ' { ' + classes[className].nodeLabelStyles.join('; ') + '; }\n'
|
|
||||||
}
|
|
||||||
if (classes.default.edgeLabelStyles instanceof Array) {
|
|
||||||
defaultStyles += '#' + svg.id.trim() + ' .edgeLabel text ' + ' { ' + classes[className].edgeLabelStyles.join('; ') + '; }\n'
|
|
||||||
}
|
|
||||||
if (classes.default.clusterStyles instanceof Array) {
|
|
||||||
defaultStyles += '#' + svg.id.trim() + ' .cluster rect ' + ' { ' + classes[className].clusterStyles.join('; ') + '; }\n'
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (classes[className].styles instanceof Array) {
|
|
||||||
embeddedStyles += '#' + svg.id.trim() + ' .' + className + '>rect, .' + className + '>polygon, .' + className + '>circle, .' + className + '>ellipse { ' + classes[className].styles.join('; ') + '; }\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usedStyles !== '' || defaultStyles !== '' || embeddedStyles !== '') {
|
|
||||||
const s = document.createElement('style')
|
|
||||||
s.setAttribute('type', 'text/css')
|
|
||||||
s.setAttribute('title', 'mermaid-svg-internal-css')
|
|
||||||
s.innerHTML = '/* <![CDATA[ */\n'
|
|
||||||
// Make this CSS local to this SVG
|
|
||||||
if (defaultStyles !== '') {
|
|
||||||
s.innerHTML += defaultStyles
|
|
||||||
}
|
|
||||||
if (usedStyles !== '') {
|
|
||||||
s.innerHTML += usedStyles
|
|
||||||
}
|
|
||||||
if (embeddedStyles !== '') {
|
|
||||||
s.innerHTML += embeddedStyles
|
|
||||||
}
|
|
||||||
s.innerHTML += '/* ]]> */\n'
|
|
||||||
svg.insertBefore(s, svg.firstChild)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @function isSubstringInArray
|
* @function isSubstringInArray
|
||||||
* Detects whether a substring in present in a given array
|
* Detects whether a substring in present in a given array
|
||||||
|
@ -142,6 +63,5 @@ export const isSubstringInArray = function (str, arr) {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
detectType,
|
detectType,
|
||||||
cloneCssStyles,
|
|
||||||
isSubstringInArray
|
isSubstringInArray
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,162 +30,6 @@ describe('when detecting chart type ', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('when cloning CSS ', function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
document.body.innerHTML = ''
|
|
||||||
})
|
|
||||||
|
|
||||||
function stylesToArray (svg) {
|
|
||||||
var styleSheets = svg.getElementsByTagName('style')
|
|
||||||
expect(styleSheets.length).toBe(1)
|
|
||||||
var styleSheet = styleSheets[0]
|
|
||||||
|
|
||||||
var innerStyle = styleSheet.innerHTML
|
|
||||||
var styleArr = innerStyle.split('\n')
|
|
||||||
|
|
||||||
// Remove first and last two lines to remove the CDATA
|
|
||||||
expect(styleArr.length).toBeGreaterThan(2)
|
|
||||||
var styleArrTrim = styleArr.slice(1, -2)
|
|
||||||
|
|
||||||
// Remove all empty lines
|
|
||||||
for (var i = 0; i < styleArrTrim.length; i++) {
|
|
||||||
if (styleArrTrim[i].trim() === '') {
|
|
||||||
styleArrTrim.splice(i, 1)
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
styleArrTrim[i] = styleArrTrim[i].trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
return styleArrTrim
|
|
||||||
}
|
|
||||||
|
|
||||||
function addStyleToDocument () {
|
|
||||||
var s = document.createElement('style')
|
|
||||||
s.innerHTML = '.node { stroke:rgb(238, 238, 238); }\n.node-square { stroke:rgb(187, 187, 187); }\n'
|
|
||||||
document.body.appendChild(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
function addSecondStyleToDocument () {
|
|
||||||
var s = document.createElement('style')
|
|
||||||
s.innerHTML = '.node2 { stroke:rgb(238, 238, 238); }\n.node-square { stroke:#beb; }\n'
|
|
||||||
document.body.appendChild(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateSVG () {
|
|
||||||
var svg = document.createElement('svg')
|
|
||||||
svg.setAttribute('id', 'mermaid-01')
|
|
||||||
var g1 = document.createElement('g')
|
|
||||||
g1.setAttribute('class', 'node')
|
|
||||||
svg.appendChild(g1)
|
|
||||||
var g2 = document.createElement('g')
|
|
||||||
g2.setAttribute('class', 'node-square')
|
|
||||||
svg.appendChild(g2)
|
|
||||||
return svg
|
|
||||||
}
|
|
||||||
|
|
||||||
function addMermaidSVGwithStyleToDocument () {
|
|
||||||
var svg = document.createElement('svg')
|
|
||||||
svg.setAttribute('id', 'mermaid-03')
|
|
||||||
var s = document.createElement('style')
|
|
||||||
s.setAttribute('type', 'text/css')
|
|
||||||
s.setAttribute('title', 'mermaid-svg-internal-css')
|
|
||||||
s.innerHTML = '#mermaid-05 .node2 { stroke:#eee; }\n.node-square { stroke:#bfe; }\n'
|
|
||||||
s.title = 'mermaid-svg-internal-css'
|
|
||||||
svg.appendChild(s)
|
|
||||||
document.body.appendChild(svg)
|
|
||||||
}
|
|
||||||
|
|
||||||
it('should handle errors thrown when accessing CSS rules', function () {
|
|
||||||
var svg = document.createElement('svg')
|
|
||||||
svg.setAttribute('id', 'mermaid-01')
|
|
||||||
|
|
||||||
// Firefox throws a SecurityError when trying to access cssRules
|
|
||||||
document.styleSheets[document.styleSheets.length - 1] = {
|
|
||||||
get cssRules () { throw new Error('SecurityError') }
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(function () {
|
|
||||||
utils.cloneCssStyles(svg, {})
|
|
||||||
}).not.toThrow()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle an empty set of classes', function () {
|
|
||||||
var svg = document.createElement('svg')
|
|
||||||
svg.setAttribute('id', 'mermaid-01')
|
|
||||||
|
|
||||||
utils.cloneCssStyles(svg, {})
|
|
||||||
// Should not create style element if not needed
|
|
||||||
expect(svg.innerHTML).toBe('')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle a default class', function () {
|
|
||||||
var svg = document.createElement('svg')
|
|
||||||
svg.setAttribute('id', 'mermaid-01')
|
|
||||||
|
|
||||||
utils.cloneCssStyles(svg, { 'default': { 'styles': ['stroke:#fff', 'stroke-width:1.5px'] } })
|
|
||||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }'])
|
|
||||||
// Also verify the elements around the styling
|
|
||||||
expect(svg.innerHTML).toBe('<style type="text/css" title="mermaid-svg-internal-css">/* <![CDATA[ */\n#mermaid-01 .node>rect { stroke:#fff; stroke-width:1.5px; }\n/* ]]> */\n</style>')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle stylesheet in document with no classes in SVG', function () {
|
|
||||||
var svg = document.createElement('svg')
|
|
||||||
svg.setAttribute('id', 'mermaid-01')
|
|
||||||
|
|
||||||
addStyleToDocument('mermaid')
|
|
||||||
utils.cloneCssStyles(svg, {})
|
|
||||||
// Should not create style element if not needed
|
|
||||||
expect(svg.innerHTML).toBe('')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle stylesheet in document with classes in SVG', function () {
|
|
||||||
var svg = generateSVG()
|
|
||||||
addStyleToDocument()
|
|
||||||
utils.cloneCssStyles(svg, {})
|
|
||||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: rgb(238, 238, 238);}', '.node-square { stroke: rgb(187, 187, 187);}'])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle multiple stylesheets in document with classes in SVG', function () {
|
|
||||||
var svg = generateSVG()
|
|
||||||
addStyleToDocument()
|
|
||||||
addSecondStyleToDocument()
|
|
||||||
utils.cloneCssStyles(svg, {})
|
|
||||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: rgb(238, 238, 238);}', '.node-square { stroke: rgb(187, 187, 187);}', '.node-square { stroke: rgb(187, 238, 187);}'])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle multiple stylesheets + ignore styles in other mermaid SVG', function () {
|
|
||||||
var svg = generateSVG()
|
|
||||||
addStyleToDocument()
|
|
||||||
addSecondStyleToDocument()
|
|
||||||
addMermaidSVGwithStyleToDocument()
|
|
||||||
utils.cloneCssStyles(svg, {})
|
|
||||||
expect(stylesToArray(svg)).toEqual(['.node { stroke: rgb(238, 238, 238);}', '.node-square { stroke: rgb(187, 187, 187);}', '.node-square { stroke: rgb(187, 238, 187);}'])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle a default class together with stylesheet in document with classes in SVG', function () {
|
|
||||||
var svg = generateSVG()
|
|
||||||
addStyleToDocument()
|
|
||||||
utils.cloneCssStyles(svg, { 'default': { 'styles': ['stroke:#ffffff', 'stroke-width:1.5px'] } })
|
|
||||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#ffffff; stroke-width:1.5px; }', '.node { stroke: rgb(238, 238, 238);}', '.node-square { stroke: rgb(187, 187, 187);}'])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle a default class together with stylesheet in document and classDefs', function () {
|
|
||||||
var svg = generateSVG()
|
|
||||||
addStyleToDocument()
|
|
||||||
utils.cloneCssStyles(svg, {
|
|
||||||
'default': { 'styles': ['stroke:#ffffff', 'stroke-width:1.5px'] },
|
|
||||||
'node-square': { 'styles': ['fill:rgb(238, 238, 238)', 'stroke:#aaaaaa'] },
|
|
||||||
'node-circle': { 'styles': ['fill:#444444', 'stroke:#111111'] }
|
|
||||||
})
|
|
||||||
expect(stylesToArray(svg)).toEqual(['#mermaid-01 .node>rect { stroke:#ffffff; stroke-width:1.5px; }',
|
|
||||||
'.node { stroke: rgb(238, 238, 238);}',
|
|
||||||
'.node-square { stroke: rgb(187, 187, 187);}',
|
|
||||||
'#mermaid-01 .node-square>rect, .node-square>polygon, .node-square>circle, .node-square>ellipse { fill:rgb(238, 238, 238); stroke:#aaaaaa; }',
|
|
||||||
'#mermaid-01 .node-circle>rect, .node-circle>polygon, .node-circle>circle, .node-circle>ellipse { fill:#444444; stroke:#111111; }'
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('when finding substring in array ', function () {
|
describe('when finding substring in array ', function () {
|
||||||
it('should return the array index that contains the substring', function () {
|
it('should return the array index that contains the substring', function () {
|
||||||
var arr = ['stroke:val1', 'fill:val2']
|
var arr = ['stroke:val1', 'fill:val2']
|
||||||
|
|
Loading…
Reference in New Issue