3

Just wondering if anyone has a tried & tested regex to parse a css font string into its various pieces:

  • 12px arial
  • italic bold sans-serif
  • 12px/50px verdana
  • etc
1

3 Answers 3

8

Answering my own question:

/^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\"\sa-z]+?)\s*$/i

which separates to:

var       parts = rx.exec( str )
  , fontStyle   = parts[1] || 'normal'
  , fontVariant = parts[2] || 'normal'
  , fontWeight  = parts[3] || 'normal'
  , fontSize    = parts[4]
  , lineHeight  = parts[5]
  , fontFamily  = parts[6]
  ;

And yes, I realize that's insane

Sign up to request clarification or add additional context in comments.

8 Comments

I'm not writing that beast for you but I'd look into back references for stuff that repeats a lot like the size units to trim it down a bit.
@ErikReppen -- I don't think I can compress it much more than it already is :) The size-units can't be back-referenced because 12px/30em verdana is perfectly valid.
@ErikReppen -- scratch that, added back-references for the first 3 props :)
That's brilliant! A couple of quirky edge cases I found... You can specify, for example, italic three times for the three optional leading terms, and it won't complain. Haven't tried to see how browsers actually handle such a silly case. A more serious case is that special characters will break the font names section. In particular, a single quote ('), which is often used to enclose font names that have spaces. I'm not concerned about the other edge cases, but I am using a variant of your regex that also accepts a single quote inside the last group.
Isn't it supposed to support font-stretch after font-weight? developer.mozilla.org/en-US/docs/Web/CSS/…
|
3

you mean like this?

How to parse CSS font shorthand format

Alternatively, there is also JSCSSP, a JavaScript library for parsing CSS.

1 Comment

Can't use the accepted answer on that since this code runs in node.js sometimes so can't use dom-parsing. The answer further down might work, need to test it.
0

Just a little fix to support parsing fonts with numbers in the name, such as Font Awesome (ex. Font Awesome 5 Free).

This regex :

/^\s*(?=(?:(?:[-a-z]+\s*){0,2}(italic|oblique))?)(?=(?:(?:[-a-z]+\s*){0,2}(small-caps))?)(?=(?:(?:[-a-z]+\s*){0,2}(bold(?:er)?|lighter|[1-9]00))?)(?:(?:normal|\1|\2|\3)\s*){0,3}((?:xx?-)?(?:small|large)|medium|smaller|larger|[.\d]+(?:\%|in|[cem]m|ex|p[ctx]))(?:\s*\/\s*(normal|[.\d]+(?:\%|in|[cem]m|ex|p[ctx])))?\s*([-,\"\sa-z0-9]+?)\s*$/i

which separates to:

    var       parts = rx.exec( str )
  , fontStyle   = parts[1] || 'normal'
  , fontVariant = parts[2] || 'normal'
  , fontWeight  = parts[3] || 'normal'
  , fontSize    = parts[4]
  , lineHeight  = parts[5]
  , fontFamily  = parts[6]
  ;

just edit the block of fontFamily rules like ([-,"\sa-z0-9]+?)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.