parse-font.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. 'use strict'
  2. /**
  3. * Font RegExp helpers.
  4. */
  5. var weights = 'bold|bolder|lighter|[1-9]00'
  6. , styles = 'italic|oblique'
  7. , variants = 'small-caps'
  8. , stretches = 'ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded'
  9. , units = 'px|pt|pc|in|cm|mm|%|em|ex|ch|rem|q'
  10. , string = '\'([^\']+)\'|"([^"]+)"|[\\w-]+'
  11. // [ [ <‘font-style’> || <font-variant-css21> || <‘font-weight’> || <‘font-stretch’> ]?
  12. // <‘font-size’> [ / <‘line-height’> ]? <‘font-family’> ]
  13. // https://drafts.csswg.org/css-fonts-3/#font-prop
  14. var weightRe = new RegExp('(' + weights + ') +', 'i')
  15. var styleRe = new RegExp('(' + styles + ') +', 'i')
  16. var variantRe = new RegExp('(' + variants + ') +', 'i')
  17. var stretchRe = new RegExp('(' + stretches + ') +', 'i')
  18. var sizeFamilyRe = new RegExp(
  19. '([\\d\\.]+)(' + units + ') *'
  20. + '((?:' + string + ')( *, *(?:' + string + '))*)')
  21. /**
  22. * Cache font parsing.
  23. */
  24. var cache = {}
  25. var defaultHeight = 16 // pt, common browser default
  26. /**
  27. * Parse font `str`.
  28. *
  29. * @param {String} str
  30. * @return {Object} Parsed font. `size` is in device units. `unit` is the unit
  31. * appearing in the input string.
  32. * @api private
  33. */
  34. module.exports = function (str) {
  35. // Cached
  36. if (cache[str]) return cache[str]
  37. // Try for required properties first.
  38. var sizeFamily = sizeFamilyRe.exec(str)
  39. if (!sizeFamily) return // invalid
  40. // Default values and required properties
  41. var font = {
  42. weight: 'normal',
  43. style: 'normal',
  44. stretch: 'normal',
  45. variant: 'normal',
  46. size: parseFloat(sizeFamily[1]),
  47. unit: sizeFamily[2],
  48. family: sizeFamily[3].replace(/["']/g, '').replace(/ *, */g, ',')
  49. }
  50. // Optional, unordered properties.
  51. var weight, style, variant, stretch
  52. // Stop search at `sizeFamily.index`
  53. var substr = str.substring(0, sizeFamily.index)
  54. if ((weight = weightRe.exec(substr))) font.weight = weight[1]
  55. if ((style = styleRe.exec(substr))) font.style = style[1]
  56. if ((variant = variantRe.exec(substr))) font.variant = variant[1]
  57. if ((stretch = stretchRe.exec(substr))) font.stretch = stretch[1]
  58. // Convert to device units. (`font.unit` is the original unit)
  59. // TODO: ch, ex
  60. switch (font.unit) {
  61. case 'pt':
  62. font.size /= 0.75
  63. break
  64. case 'pc':
  65. font.size *= 16
  66. break
  67. case 'in':
  68. font.size *= 96
  69. break
  70. case 'cm':
  71. font.size *= 96.0 / 2.54
  72. break
  73. case 'mm':
  74. font.size *= 96.0 / 25.4
  75. break
  76. case '%':
  77. // TODO disabled because existing unit tests assume 100
  78. // font.size *= defaultHeight / 100 / 0.75
  79. break
  80. case 'em':
  81. case 'rem':
  82. font.size *= defaultHeight / 0.75
  83. break
  84. case 'q':
  85. font.size *= 96 / 25.4 / 4
  86. break
  87. }
  88. return (cache[str] = font)
  89. }