diff --git a/index.js b/index.js index bd02b01..d902591 100644 --- a/index.js +++ b/index.js @@ -26,6 +26,23 @@ const fontWeights = { }; const sp = ' '; const italicRE = /(italic|oblique)$/i; +const snakeCaseRE = /_/g; +const wordStartRE = /(^| )[a-z]/g; + +/** + * @param {string} font Font name, e.g. `'noto_sans_bold'` or `'Noto Sans Bold'`. + * @return {string} Font name with words separated by spaces, e.g. `'Noto Sans Bold'`. + */ +function toWords(font) { + if (font.indexOf('_') === -1) { + return font; + } + // Snake case names, e.g. from VersaTiles styles, are all lower case. + // Capitalized words match the family names that font services use. + return font + .replace(snakeCaseRE, sp) + .replace(wordStartRE, (wordStart) => wordStart.toUpperCase()); +} const fontCache = {}; @@ -46,7 +63,7 @@ export default function (fonts, size, lineHeight) { const fontFamilies = []; let haveWeight, haveStyle; for (let i = 0, ii = fonts.length; i < ii; ++i) { - const font = fonts[i]; + const font = toWords(fonts[i]); const parts = font.split(' '); let maybeWeight = parts[parts.length - 1].toLowerCase(); if ( diff --git a/test/index.test.js b/test/index.test.js index 6e66b51..d009296 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -15,6 +15,18 @@ describe('mapbox-to-css-font', function () { should(parseFont('Inter Semi Bold', 16)).eql('normal 600 16px Inter'); }); + it('handle snake case font names', function () { + should(parseFont('noto_sans_regular', 16)).eql( + 'normal 400 16px "Noto Sans"', + ); + should(parseFont('noto_sans_bold', 16)).eql( + 'normal 700 16px "Noto Sans"', + ); + should(parseFont('noto_sans_semibold_italic', 16)).eql( + 'italic 600 16px "Noto Sans"', + ); + }); + it('handle line-height', function () { should(parseFont('monospace', 16)).eql('normal 400 16px monospace'); should(parseFont('monospace', 16, 3.5)).eql(