Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse style string and number font size values from configuration inputs #3993

Merged
merged 2 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 9 additions & 7 deletions packages/mermaid/src/diagrams/sequence/svgDraw.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import common from '../common/common';
import { addFunction } from '../../interactionDb';
import { parseFontSize } from '../../utils';
import { sanitizeUrl } from '@braintree/sanitize-url';

export const drawRect = function (elem, rectData) {
Expand Down Expand Up @@ -156,6 +157,8 @@ export const drawText = function (elem, textData) {
textHeight = 0;
const lines = textData.text.split(common.lineBreakRegex);

const [_textFontSize, _textFontSizePx] = parseFontSize(textData.fontSize);

let textElems = [];
let dy = 0;
let yfunc = () => textData.y;
Expand Down Expand Up @@ -218,9 +221,9 @@ export const drawText = function (elem, textData) {
if (
textData.textMargin !== undefined &&
textData.textMargin === 0 &&
textData.fontSize !== undefined
_textFontSize !== undefined
) {
dy = i * textData.fontSize;
dy = i * _textFontSize;
}

const textElem = elem.append('text');
Expand All @@ -235,8 +238,8 @@ export const drawText = function (elem, textData) {
if (textData.fontFamily !== undefined) {
textElem.style('font-family', textData.fontFamily);
}
if (textData.fontSize !== undefined) {
textElem.style('font-size', textData.fontSize);
if (_textFontSizePx !== undefined) {
textElem.style('font-size', _textFontSizePx);
}
if (textData.fontWeight !== undefined) {
textElem.style('font-weight', textData.fontWeight);
Expand Down Expand Up @@ -840,8 +843,7 @@ const _drawTextCandidateFunc = (function () {
function byTspan(content, g, x, y, width, height, textAttrs, conf) {
const { actorFontSize, actorFontFamily, actorFontWeight } = conf;

let _actorFontSize =
actorFontSize && actorFontSize.replace ? actorFontSize.replace('px', '') : actorFontSize;
const [_actorFontSize, _actorFontSizePx] = parseFontSize(actorFontSize);

const lines = content.split(common.lineBreakRegex);
for (let i = 0; i < lines.length; i++) {
Expand All @@ -851,7 +853,7 @@ const _drawTextCandidateFunc = (function () {
.attr('x', x + width / 2)
.attr('y', y)
.style('text-anchor', 'middle')
.style('font-size', actorFontSize)
.style('font-size', _actorFontSizePx)
.style('font-weight', actorFontWeight)
.style('font-family', actorFontFamily);
text
Expand Down
24 changes: 24 additions & 0 deletions packages/mermaid/src/diagrams/sequence/svgDraw.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,30 @@ describe('svgDraw', function () {
expect(text3.attr).toHaveBeenCalledWith('y', 10);
expect(text3.text).toHaveBeenCalledWith('fine lines');
});
it('should work with numeral font sizes', function () {
const svg = MockD3('svg');
svgDraw.drawText(svg, {
x: 10,
y: 10,
dy: '1em',
text: 'One fine text message',
class: 'noteText',
fontFamily: 'courier',
fontSize: 10,
fontWeight: '500',
});
expect(svg.__children.length).toBe(1);
const text = svg.__children[0];
expect(text.__name).toBe('text');
expect(text.attr).toHaveBeenCalledWith('x', 10);
expect(text.attr).toHaveBeenCalledWith('y', 10);
expect(text.attr).toHaveBeenCalledWith('dy', '1em');
expect(text.attr).toHaveBeenCalledWith('class', 'noteText');
expect(text.text).toHaveBeenCalledWith('One fine text message');
expect(text.style).toHaveBeenCalledWith('font-family', 'courier');
expect(text.style).toHaveBeenCalledWith('font-size', '10px');
expect(text.style).toHaveBeenCalledWith('font-weight', '500');
});
});
describe('drawBackgroundRect', function () {
it('should append a rect before the previous element within a given bound', function () {
Expand Down
26 changes: 26 additions & 0 deletions packages/mermaid/src/utils.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,29 @@ describe('when inserting titles', function () {
expect(titleAttrSpy).toHaveBeenCalledWith('class', 'testClass');
});
});

describe('when parsing font sizes', function () {
it('parses number inputs', function () {
expect(utils.parseFontSize(14)).toEqual([14, '14px']);
});

it('parses string em inputs', function () {
expect(utils.parseFontSize('14em')).toEqual([14, '14em']);
});

it('parses string px inputs', function () {
expect(utils.parseFontSize('14px')).toEqual([14, '14px']);
});

it('parses string inputs without units', function () {
expect(utils.parseFontSize('14')).toEqual([14, '14px']);
});

it('handles undefined input', function () {
expect(utils.parseFontSize(undefined)).toEqual([undefined, undefined]);
});

it('handles unparseable input', function () {
expect(utils.parseFontSize({ fontSize: 14 })).toEqual([undefined, undefined]);
});
});
35 changes: 33 additions & 2 deletions packages/mermaid/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -543,12 +543,14 @@ export const drawSimpleText = function (
// Remove and ignore br:s
const nText = textData.text.replace(common.lineBreakRegex, ' ');

const [, _fontSizePx] = parseFontSize(textData.fontSize);

const textElem = elem.append('text');
textElem.attr('x', textData.x);
textElem.attr('y', textData.y);
textElem.style('text-anchor', textData.anchor);
textElem.style('font-family', textData.fontFamily);
textElem.style('font-size', textData.fontSize);
textElem.style('font-size', _fontSizePx);
textElem.style('font-weight', textData.fontWeight);
textElem.attr('fill', textData.fill);
if (textData.class !== undefined) {
Expand Down Expand Up @@ -722,6 +724,8 @@ export const calculateTextDimensions: (
return { width: 0, height: 0 };
}

const [, _fontSizePx] = parseFontSize(fontSize);

// We can't really know if the user supplied font family will render on the user agent;
// thus, we'll take the max width between the user supplied font family, and a default
// of sans-serif.
Expand All @@ -745,7 +749,7 @@ export const calculateTextDimensions: (
const textObj = getTextObj();
textObj.text = line;
const textElem = drawSimpleText(g, textObj)
.style('font-size', fontSize)
.style('font-size', _fontSizePx)
.style('font-weight', fontWeight)
.style('font-family', fontFamily);

Expand Down Expand Up @@ -941,6 +945,32 @@ export const insertTitle = (
.attr('class', cssClass);
};

/**
* Parses a raw fontSize configuration value into a number and string value.
*
* @param fontSize - a string or number font size configuration value
*
* @returns parsed number and string style font size values, or nulls if a number value can't
* be parsed from an input string.
*/
export const parseFontSize = (fontSize: string | number | undefined): [number?, string?] => {
// if the font size is a number, assume a px string representation
if (typeof fontSize === 'number') {
return [fontSize, fontSize + 'px'];
}

const fontSizeNumber = parseInt(fontSize, 10);
if (Number.isNaN(fontSizeNumber)) {
// if a number value can't be parsed, return null for both values
return [undefined, undefined];
} else if (fontSize === String(fontSizeNumber)) {
// if a string input doesn't contain any units, assume px units
return [fontSizeNumber, fontSize + 'px'];
} else {
return [fontSizeNumber, fontSize];
}
};

export default {
assignWithDepth,
wrapLabel,
Expand All @@ -964,4 +994,5 @@ export default {
directiveSanitizer,
sanitizeCss,
insertTitle,
parseFontSize,
};