diff --git a/cypress/helpers/util.ts b/cypress/helpers/util.ts index 9e49d965e..3ffba697a 100644 --- a/cypress/helpers/util.ts +++ b/cypress/helpers/util.ts @@ -54,11 +54,11 @@ export const imgSnapshotTest = ( ): void => { const options: CypressMermaidConfig = { ..._options, - fontFamily: _options.fontFamily || 'courier', + fontFamily: _options.fontFamily ?? 'courier', // @ts-ignore TODO: Fix type of fontSize - fontSize: _options.fontSize || '16px', + fontSize: _options.fontSize ?? '16px', sequence: { - ...(_options.sequence || {}), + ...(_options.sequence ?? {}), actorFontFamily: 'courier', noteFontFamily: _options.sequence?.noteFontFamily ? _options.sequence.noteFontFamily @@ -94,7 +94,7 @@ export const openURLAndVerifyRendering = ( options: CypressMermaidConfig, validation?: any ): void => { - const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); + const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); cy.visit(url); cy.window().should('have.property', 'rendered', true); diff --git a/eslint.config.js b/eslint.config.js index 8b4807bc5..ed703ea71 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -109,7 +109,6 @@ export default tseslint.config( '@typescript-eslint/no-unsafe-member-access': 'off', '@typescript-eslint/no-unsafe-return': 'off', '@typescript-eslint/only-throw-error': 'warn', - '@typescript-eslint/prefer-nullish-coalescing': 'warn', '@typescript-eslint/prefer-promise-reject-errors': 'warn', // END 'json/*': ['error', 'allowComments'], diff --git a/packages/mermaid/scripts/docs.mts b/packages/mermaid/scripts/docs.mts index 06cea376d..374e78870 100644 --- a/packages/mermaid/scripts/docs.mts +++ b/packages/mermaid/scripts/docs.mts @@ -181,10 +181,10 @@ export const transformToBlockQuote = ( ) => { if (vitepress) { const vitepressType = type === 'note' ? 'info' : type; - return `::: ${vitepressType} ${customTitle || ''}\n${content}\n:::`; + return `::: ${vitepressType} ${customTitle ?? ''}\n${content}\n:::`; } else { - const icon = blockIcons[type] || ''; - const title = `${icon}${customTitle || capitalize(type)}`; + const icon = blockIcons[type] ?? ''; + const title = `${icon}${customTitle ?? capitalize(type)}`; return `> **${title}** \n> ${content.replace(/\n/g, '\n> ')}`; } }; diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts index edd8a9c50..d6e35ed15 100644 --- a/packages/mermaid/src/diagrams/block/blockDB.ts +++ b/packages/mermaid/src/diagrams/block/blockDB.ts @@ -101,7 +101,7 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { continue; } if (block.type === 'applyClass') { - setCssClass(block.id, block?.styleClass || ''); + setCssClass(block.id, block?.styleClass ?? ''); continue; } if (block.type === 'applyStyles') { @@ -111,7 +111,7 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { continue; } if (block.type === 'column-setting') { - parent.columns = block.columns || -1; + parent.columns = block.columns ?? -1; } else if (block.type === 'edge') { const count = (edgeCount.get(block.id) ?? 0) + 1; edgeCount.set(block.id, count); @@ -145,7 +145,7 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { } if (block.type === 'space') { // log.debug('abc95 space', block); - const w = block.width || 1; + const w = block.width ?? 1; for (let j = 0; j < w; j++) { const newBlock = clone(block); newBlock.id = newBlock.id + '-' + j; diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts index 4dfd0b0d6..7f44a5f19 100644 --- a/packages/mermaid/src/diagrams/block/layout.ts +++ b/packages/mermaid/src/diagrams/block/layout.ts @@ -2,7 +2,8 @@ import type { BlockDB } from './blockDB.js'; import type { Block } from './blockTypes.js'; import { log } from '../../logger.js'; import { getConfig } from '../../diagram-api/diagramAPI.js'; -const padding = getConfig()?.block?.padding || 8; +// TODO: This means the number we provide in diagram's config will never be used. Should fix. +const padding = getConfig()?.block?.padding ?? 8; interface BlockPosition { px: number; @@ -42,7 +43,7 @@ const getMaxChildSize = (block: Block) => { // find max width of children // log.debug('getMaxChildSize abc95 (start) parent:', block.id); for (const child of block.children) { - const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 }; + const { width, height, x, y } = child.size ?? { width: 0, height: 0, x: 0, y: 0 }; log.debug( 'getMaxChildSize abc95 child:', child.id, @@ -60,7 +61,7 @@ const getMaxChildSize = (block: Block) => { continue; } if (width > maxWidth) { - maxWidth = width / (block.widthInColumns || 1); + maxWidth = width / (block.widthInColumns ?? 1); } if (height > maxHeight) { maxHeight = height; @@ -107,7 +108,7 @@ function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeigh `abc95 Setting size of children of ${block.id} id=${child.id} ${maxWidth} ${maxHeight} ${JSON.stringify(child.size)}` ); child.size.width = - maxWidth * (child.widthInColumns || 1) + padding * ((child.widthInColumns || 1) - 1); + maxWidth * (child.widthInColumns ?? 1) + padding * ((child.widthInColumns ?? 1) - 1); child.size.height = maxHeight; child.size.x = 0; child.size.y = 0; @@ -121,10 +122,10 @@ function setBlockSizes(block: Block, db: BlockDB, siblingWidth = 0, siblingHeigh setBlockSizes(child, db, maxWidth, maxHeight); } - const columns = block.columns || -1; + const columns = block.columns ?? -1; let numItems = 0; for (const child of block.children) { - numItems += child.widthInColumns || 1; + numItems += child.widthInColumns ?? 1; } // The width and height in number blocks @@ -204,13 +205,13 @@ function layoutBlocks(block: Block, db: BlockDB) { log.debug( `abc85 layout blocks (=>layoutBlocks) ${block.id} x: ${block?.size?.x} y: ${block?.size?.y} width: ${block?.size?.width}` ); - const columns = block.columns || -1; + const columns = block.columns ?? -1; log.debug('layoutBlocks columns abc95', block.id, '=>', columns, block); if ( block.children && // find max width of children block.children.length > 0 ) { - const width = block?.children[0]?.size?.width || 0; + const width = block?.children[0]?.size?.width ?? 0; const widthOfChildren = block.children.length * width + (block.children.length - 1) * padding; log.debug('widthOfChildren 88', widthOfChildren, 'posX'); @@ -249,7 +250,7 @@ function layoutBlocks(block: Block, db: BlockDB) { } ${halfWidth} padding=${padding} width=${width} halfWidth=${halfWidth} => x:${ child.size.x } y:${child.size.y} ${child.widthInColumns} (width * (child?.w || 1)) / 2 ${ - (width * (child?.widthInColumns || 1)) / 2 + (width * (child?.widthInColumns ?? 1)) / 2 }` ); @@ -263,15 +264,13 @@ function layoutBlocks(block: Block, db: BlockDB) { child.id }startingPosX${startingPosX}${padding}${halfWidth}=>x:${child.size.x}y:${child.size.y}${ child.widthInColumns - }(width * (child?.w || 1)) / 2${(width * (child?.widthInColumns || 1)) / 2}` + }(width * (child?.w || 1)) / 2${(width * (child?.widthInColumns ?? 1)) / 2}` ); } - - // posY += height + padding; if (child.children) { layoutBlocks(child, db); } - columnPos += child?.widthInColumns || 1; + columnPos += child?.widthInColumns ?? 1; log.debug('abc88 columnsPos', child, columnPos); } } diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts index 9dffafd76..97eca4074 100644 --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts @@ -11,7 +11,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { let classStr = 'default'; if ((vertex?.classes?.length || 0) > 0) { - classStr = (vertex?.classes || []).join(' '); + classStr = (vertex?.classes ?? []).join(' '); } classStr = classStr + ' flowchart-label'; @@ -85,12 +85,12 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { shape = 'rect'; } - const styles = getStylesFromArray(vertex?.styles || []); + const styles = getStylesFromArray(vertex?.styles ?? []); // Use vertex id as text in the box if no text is provided by the graph definition const vertexText = vertex.label; - const bounds = vertex.size || { width: 0, height: 0, x: 0, y: 0 }; + const bounds = vertex.size ?? { width: 0, height: 0, x: 0, y: 0 }; // Add the node const node = { labelStyle: styles.labelStyle, @@ -109,7 +109,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { positioned, intersect: undefined, type: vertex.type, - padding: padding ?? (getConfig()?.block?.padding || 0), + padding: padding ?? getConfig()?.block?.padding ?? 0, }; return node; } diff --git a/packages/mermaid/src/diagrams/common/common.ts b/packages/mermaid/src/diagrams/common/common.ts index c3e36d087..e24c8e85c 100644 --- a/packages/mermaid/src/diagrams/common/common.ts +++ b/packages/mermaid/src/diagrams/common/common.ts @@ -34,13 +34,13 @@ function setupDompurifyHooks() { DOMPurify.addHook('beforeSanitizeAttributes', (node: Element) => { if (node.tagName === 'A' && node.hasAttribute('target')) { - node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') || ''); + node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') ?? ''); } }); DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => { if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) { - node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) || ''); + node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) ?? ''); node.removeAttribute(TEMPORARY_ATTRIBUTE); if (node.getAttribute('target') === '_blank') { node.setAttribute('rel', 'noopener'); diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index 985f5db46..d03f1d989 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -503,7 +503,7 @@ export const addSubGraph = function ( } } - id = id || 'subGraph' + subCount; + id = id ?? 'subGraph' + subCount; title = title || ''; title = sanitizeText(title); subCount = subCount + 1; diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js index d291f31d6..1dce1391e 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js @@ -366,8 +366,8 @@ export const draw = async function (text, id, _version, diagObj) { } const { securityLevel, flowchart: conf } = getConfig(); - const nodeSpacing = conf.nodeSpacing || 50; - const rankSpacing = conf.rankSpacing || 50; + const nodeSpacing = conf.nodeSpacing ?? 50; + const rankSpacing = conf.rankSpacing ?? 50; // Handle root and document for when rendering in sandbox mode let sandboxElement; diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer.js index 8b261e66c..314c6aa52 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer.js +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer.js @@ -301,8 +301,8 @@ export const draw = async function (text, id, _version, diagObj) { if (dir === undefined) { dir = 'TD'; } - const nodeSpacing = conf.nodeSpacing || 50; - const rankSpacing = conf.rankSpacing || 50; + const nodeSpacing = conf.nodeSpacing ?? 50; + const rankSpacing = conf.rankSpacing ?? 50; // Create the input mermaid.graph const g = new graphlib.Graph({ diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts index 567465c78..c7d478ed1 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantBuilder.ts @@ -493,8 +493,8 @@ export class QuadrantBuilder { const props: QuadrantPointType = { x: xAxis(point.x), y: yAxis(point.y), - fill: point.color || this.themeConfig.quadrantPointFill, - radius: point.radius || this.config.pointRadius, + fill: point.color ?? this.themeConfig.quadrantPointFill, + radius: point.radius ?? this.config.pointRadius, text: { text: point.text, fill: this.themeConfig.quadrantPointTextFill, @@ -505,8 +505,8 @@ export class QuadrantBuilder { fontSize: this.config.pointLabelFontSize, rotation: 0, }, - strokeColor: point.strokeColor || this.themeConfig.quadrantPointFill, - strokeWidth: point.strokeWidth || '0px', + strokeColor: point.strokeColor ?? this.themeConfig.quadrantPointFill, + strokeWidth: point.strokeWidth ?? '0px', }; return props; }); diff --git a/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts b/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts index c2295da4d..6d2435cd4 100644 --- a/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts +++ b/packages/mermaid/src/diagrams/quadrant-chart/quadrantRenderer.ts @@ -46,10 +46,10 @@ export const draw = (txt: string, id: string, _version: string, diagObj: Diagram const group = svg.append('g').attr('class', 'main'); - const width = conf.quadrantChart?.chartWidth || 500; - const height = conf.quadrantChart?.chartHeight || 500; + const width = conf.quadrantChart?.chartWidth ?? 500; + const height = conf.quadrantChart?.chartHeight ?? 500; - configureSvgSize(svg, height, width, conf.quadrantChart?.useMaxWidth || true); + configureSvgSize(svg, height, width, conf.quadrantChart?.useMaxWidth ?? true); svg.attr('viewBox', '0 0 ' + width + ' ' + height); diff --git a/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts index c72eaf7b6..a981a346e 100644 --- a/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts +++ b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts @@ -5,7 +5,6 @@ import { scaleOrdinal as d3scaleOrdinal, schemeTableau10 as d3schemeTableau10, } from 'd3'; - import type { SankeyNode as d3SankeyNode } from 'd3-sankey'; import { sankey as d3Sankey, @@ -160,7 +159,7 @@ export const draw = function (text: string, id: string, _version: string, diagOb .attr('class', 'link') .style('mix-blend-mode', 'multiply'); - const linkColor = conf?.linkColor || 'gradient'; + const linkColor = conf?.linkColor ?? 'gradient'; if (linkColor === 'gradient') { const gradient = link diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts index 988db7f92..a0181d411 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDb.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceDb.ts @@ -46,7 +46,7 @@ const state = new ImperativeState(() => ({ export const addBox = function (data: { text: string; color: string; wrap: boolean }) { state.records.boxes.push({ name: data.text, - wrap: (data.wrap === undefined && autoWrap()) || !!data.wrap, + wrap: (data.wrap === undefined && autoWrap()) ?? !!data.wrap, fill: data.color, actorKeys: [], }); @@ -91,7 +91,7 @@ export const addActor = function ( box: assignedBox, name: name, description: description.text, - wrap: (description.wrap === undefined && autoWrap()) || !!description.wrap, + wrap: (description.wrap === undefined && autoWrap()) ?? !!description.wrap, prevActor: state.records.prevActor, links: {}, properties: {}, @@ -145,7 +145,7 @@ export const addMessage = function ( from: idFrom, to: idTo, message: message.text, - wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap, + wrap: (message.wrap === undefined && autoWrap()) ?? !!message.wrap, answer: answer, }); }; @@ -158,7 +158,7 @@ export const addSignal = function ( activate = false ) { if (messageType === LINETYPE.ACTIVE_END) { - const cnt = activationCount(idFrom || ''); + const cnt = activationCount(idFrom ?? ''); if (cnt < 1) { // Bail out as there is an activation signal from an inactive participant const error = new Error('Trying to inactivate an inactive participant (' + idFrom + ')'); @@ -178,7 +178,7 @@ export const addSignal = function ( from: idFrom, to: idTo, message: message?.text ?? '', - wrap: (message?.wrap === undefined && autoWrap()) || !!message?.wrap, + wrap: (message?.wrap === undefined && autoWrap()) ?? !!message?.wrap, type: messageType, activate, }); @@ -352,7 +352,7 @@ export const addNote = function ( actor: actor, placement: placement, message: message.text, - wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap, + wrap: (message.wrap === undefined && autoWrap()) ?? !!message.wrap, }; //@ts-ignore: Coerce actor into a [to, from, ...] array @@ -363,7 +363,7 @@ export const addNote = function ( from: actors[0], to: actors[1], message: message.text, - wrap: (message.wrap === undefined && autoWrap()) || !!message.wrap, + wrap: (message.wrap === undefined && autoWrap()) ?? !!message.wrap, type: LINETYPE.NOTE, placement: placement, }); diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/bandAxis.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/bandAxis.ts index 864ef1316..98eb31235 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/bandAxis.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/bandAxis.ts @@ -40,6 +40,6 @@ export class BandAxis extends BaseAxis { } getScaleValue(value: string): number { - return this.scale(value) || this.getRange()[0]; + return this.scale(value) ?? this.getRange()[0]; } } diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index ffd7d4bea..7bca4d995 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -128,7 +128,7 @@ export const createCssStyles = ( // classDefs defined in the diagram text if (classDefs instanceof Map) { - const htmlLabels = config.htmlLabels || config.flowchart?.htmlLabels; // TODO why specifically check the Flowchart diagram config? + const htmlLabels = config.htmlLabels ?? config.flowchart?.htmlLabels; // TODO why specifically check the Flowchart diagram config? const cssHtmlElements = ['> *', 'span']; // TODO make a constant const cssShapeElements = ['rect', 'polygon', 'ellipse', 'circle', 'path']; // TODO make a constant