123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- 'use strict'
- /**
- * Font RegExp helpers.
- */
- const weights = 'bold|bolder|lighter|[1-9]00'
- const styles = 'italic|oblique'
- const variants = 'small-caps'
- const stretches = 'ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded'
- const units = 'px|pt|pc|in|cm|mm|%|em|ex|ch|rem|q'
- const string = '\'([^\']+)\'|"([^"]+)"|[\\w\\s-]+'
- // [ [ <‘font-style’> || <font-variant-css21> || <‘font-weight’> || <‘font-stretch’> ]?
- // <‘font-size’> [ / <‘line-height’> ]? <‘font-family’> ]
- // https://drafts.csswg.org/css-fonts-3/#font-prop
- const weightRe = new RegExp(`(${weights}) +`, 'i')
- const styleRe = new RegExp(`(${styles}) +`, 'i')
- const variantRe = new RegExp(`(${variants}) +`, 'i')
- const stretchRe = new RegExp(`(${stretches}) +`, 'i')
- const sizeFamilyRe = new RegExp(
- `([\\d\\.]+)(${units}) *((?:${string})( *, *(?:${string}))*)`)
- /**
- * Cache font parsing.
- */
- const cache = {}
- const defaultHeight = 16 // pt, common browser default
- /**
- * Parse font `str`.
- *
- * @param {String} str
- * @return {Object} Parsed font. `size` is in device units. `unit` is the unit
- * appearing in the input string.
- * @api private
- */
- module.exports = str => {
- // Cached
- if (cache[str]) return cache[str]
- // Try for required properties first.
- const sizeFamily = sizeFamilyRe.exec(str)
- if (!sizeFamily) return // invalid
- // Default values and required properties
- const font = {
- weight: 'normal',
- style: 'normal',
- stretch: 'normal',
- variant: 'normal',
- size: parseFloat(sizeFamily[1]),
- unit: sizeFamily[2],
- family: sizeFamily[3].replace(/["']/g, '').replace(/ *, */g, ',')
- }
- // Optional, unordered properties.
- let weight, style, variant, stretch
- // Stop search at `sizeFamily.index`
- const substr = str.substring(0, sizeFamily.index)
- if ((weight = weightRe.exec(substr))) font.weight = weight[1]
- if ((style = styleRe.exec(substr))) font.style = style[1]
- if ((variant = variantRe.exec(substr))) font.variant = variant[1]
- if ((stretch = stretchRe.exec(substr))) font.stretch = stretch[1]
- // Convert to device units. (`font.unit` is the original unit)
- // TODO: ch, ex
- switch (font.unit) {
- case 'pt':
- font.size /= 0.75
- break
- case 'pc':
- font.size *= 16
- break
- case 'in':
- font.size *= 96
- break
- case 'cm':
- font.size *= 96.0 / 2.54
- break
- case 'mm':
- font.size *= 96.0 / 25.4
- break
- case '%':
- // TODO disabled because existing unit tests assume 100
- // font.size *= defaultHeight / 100 / 0.75
- break
- case 'em':
- case 'rem':
- font.size *= defaultHeight / 0.75
- break
- case 'q':
- font.size *= 96 / 25.4 / 4
- break
- }
- return (cache[str] = font)
- }
|