import _ from 'lodash'; import React, {Children} from 'react'; import TSpan from '../../elements/TSpan'; const fontRegExp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?[ptexm%])*(?:\s*\/.*?)?\s+)?\s*"?([^"]*)/i; const fontFamilyPrefix = /^[\s"']*/; const fontFamilySuffix = /[\s"']*$/; const spaceReg = /\s+/; const commaReg = /,/g; const cachedFontObjectsFromString = {}; function extractSingleFontFamily(fontFamilyString) { // SVG on the web allows for multiple font-families to be specified. // For compatibility, we extract the first font-family, hoping // we'll get a match. return fontFamilyString ? fontFamilyString.split(commaReg)[0] .replace(fontFamilyPrefix, '') .replace(fontFamilySuffix, '') : null; } function parseFontString(font) { if (cachedFontObjectsFromString.hasOwnProperty(font)) { return cachedFontObjectsFromString[font]; } const match = fontRegExp.exec(font); if (!match) { return null; } const fontFamily = extractSingleFontFamily(match[3]); const fontSize = match[2] || "12"; const isBold = /bold/.exec(match[1]); const isItalic = /italic/.exec(match[1]); const fontWeight = isBold ? 'bold' : 'normal'; const fontStyle = isItalic ? 'italic' : 'normal'; cachedFontObjectsFromString[font] = { fontSize, fontFamily, fontWeight, fontStyle, }; return cachedFontObjectsFromString[font]; } export function extractFont(props) { const { letterSpacing, wordSpacing, fontWeight, fontStyle, kerning, textAnchor, textDecoration, } = props; let { font, fontSize, fontFamily, } = props; fontFamily = extractSingleFontFamily(fontFamily); fontSize = fontSize ? '' + fontSize : null; const ownedFont = _.pickBy({ fontFamily, letterSpacing, wordSpacing, fontWeight, fontStyle, fontSize, kerning, textAnchor, textDecoration, }, prop => !_.isNil(prop)); if (typeof font === 'string') { font = parseFontString(font); } return _.defaults(ownedFont, font); } function parseSVGLengthList(delta) { if (typeof delta === 'string') { return delta.trim().replace(commaReg, ' ').split(spaceReg); } else if (typeof delta === 'number') { return [delta.toString()]; } else if (delta && typeof delta.map === 'function') { return delta.map(d => `${d}`); } else { return []; } } export default function(props, container) { const { x, y, dx, dy, method, spacing, } = props; let { rotate, children, startOffset } = props; const positionX = parseSVGLengthList(x); const positionY = parseSVGLengthList(y); const deltaX = parseSVGLengthList(dx); const deltaY = parseSVGLengthList(dy); rotate = parseSVGLengthList(rotate); let content = null; if (typeof children === 'string' || typeof children === 'number') { const childrenString = children.toString(); if (container) { children = {childrenString}; } else { content = childrenString; children = null; } } else if (Children.count(children) > 1 || Array.isArray(children)) { children = Children.map(children, child => { if (typeof child === 'string' || typeof child === 'number') { return {child.toString()}; } else { return child; } }); } const font = extractFont(props); startOffset = (startOffset || 0).toString(); return { font, children, content, positionX, positionY, rotate, deltaX, deltaY, method, spacing, startOffset, }; }