{"version":3,"file":"text-metrics.mjs","sources":["../src/utils.js","../src/index.js"],"sourcesContent":["/*\n B2\tBreak Opportunity Before and After\tEm dash\tProvide a line break opportunity before and after the character\n BA\tBreak After\tSpaces, hyphens\tGenerally provide a line break opportunity after the character\n BB\tBreak Before\tPunctuation used in dictionaries\tGenerally provide a line break opportunity before the character\n HY\tHyphen\tHYPHEN-MINUS\tProvide a line break opportunity after the character, except in numeric context\n CB\tContingent Break Opportunity\tInline objects\tProvide a line break opportunity contingent on additional information\n */\n\n// B2 Break Opportunity Before and After - http://www.unicode.org/reports/tr14/#B2\nconst B2 = new Set(['\\u2014']);\n\nconst SHY = new Set([\n  // Soft hyphen\n  '\\u00AD',\n]);\n\n// BA: Break After (remove on break) - http://www.unicode.org/reports/tr14/#BA\nconst BAI = new Set([\n  // Spaces\n  '\\u0020',\n  '\\u1680',\n  '\\u2000',\n  '\\u2001',\n  '\\u2002',\n  '\\u2003',\n  '\\u2004',\n  '\\u2005',\n  '\\u2006',\n  '\\u2008',\n  '\\u2009',\n  '\\u200A',\n  '\\u205F',\n  '\\u3000',\n  // Tab\n  '\\u0009',\n  // ZW Zero Width Space - http://www.unicode.org/reports/tr14/#ZW\n  '\\u200B',\n  // Mandatory breaks not interpreted by html\n  '\\u2028',\n  '\\u2029',\n]);\n\nconst BA = new Set([\n  // Hyphen\n  '\\u058A',\n  '\\u2010',\n  '\\u2012',\n  '\\u2013',\n  // Visible Word Dividers\n  '\\u05BE',\n  '\\u0F0B',\n  '\\u1361',\n  '\\u17D8',\n  '\\u17DA',\n  '\\u2027',\n  '\\u007C',\n  // Historic Word Separators\n  '\\u16EB',\n  '\\u16EC',\n  '\\u16ED',\n  '\\u2056',\n  '\\u2058',\n  '\\u2059',\n  '\\u205A',\n  '\\u205B',\n  '\\u205D',\n  '\\u205E',\n  '\\u2E19',\n  '\\u2E2A',\n  '\\u2E2B',\n  '\\u2E2C',\n  '\\u2E2D',\n  '\\u2E30',\n  '\\u10100',\n  '\\u10101',\n  '\\u10102',\n  '\\u1039F',\n  '\\u103D0',\n  '\\u1091F',\n  '\\u12470',\n]);\n\n// BB: Break Before - http://www.unicode.org/reports/tr14/#BB\nconst BB = new Set(['\\u00B4', '\\u1FFD']);\n\n// BK: Mandatory Break (A) (Non-tailorable) - http://www.unicode.org/reports/tr14/#BK\nconst BK = new Set(['\\u000A']);\n\n/* eslint-env es6, browser */\nconst DEFAULTS = {\n  'font-size': '16px',\n  'font-weight': '400',\n  'font-family': 'Helvetica, Arial, sans-serif',\n};\n\n/**\n * We only support rem/em/pt conversion\n * @param val\n * @param options\n * @return {*}\n */\nfunction pxValue(value_, options) {\n  if (!options) {\n    options = {};\n  }\n\n  const baseFontSize = Number.parseInt(prop(options, 'base-font-size', 16), 10);\n\n  const value = Number.parseFloat(value_);\n  const unit = value_.replace(value, '');\n  // eslint-disable-next-line default-case\n  switch (unit) {\n    case 'rem':\n    case 'em': {\n      return value * baseFontSize;\n    }\n\n    case 'pt': {\n      return value * (96 / 72);\n    }\n\n    case 'px': {\n      return value;\n    }\n  }\n\n  throw new Error('The unit ' + unit + ' is not supported');\n}\n\n/**\n * Get computed word- and letter spacing for text\n * @param ws\n * @param ls\n * @return {function(*)}\n */\nexport function addWordAndLetterSpacing(ws, ls) {\n  const denyList = new Set(['inherit', 'initial', 'unset', 'normal']);\n\n  let wordAddon = 0;\n  if (ws && !denyList.has(ws)) {\n    wordAddon = pxValue(ws);\n  }\n\n  let letterAddon = 0;\n  if (ls && !denyList.has(ls)) {\n    letterAddon = pxValue(ls);\n  }\n\n  return (text) => {\n    const words = text.trim().replace(/\\s+/gi, ' ').split(' ').length - 1;\n    const chars = text.length;\n\n    return words * wordAddon + chars * letterAddon;\n  };\n}\n\n/**\n * Map css styles to canvas font property\n *\n * font: font-style font-variant font-weight font-size/line-height font-family;\n * http://www.w3schools.com/tags/canvas_font.asp\n *\n * @param {CSSStyleDeclaration} style\n * @param {object} options\n * @returns {string}\n */\nexport function getFont(style, options) {\n  const font = [];\n\n  const fontWeight = prop(options, 'font-weight', style.getPropertyValue('font-weight')) || DEFAULTS['font-weight'];\n  if (\n    ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900'].includes(\n      fontWeight.toString()\n    )\n  ) {\n    font.push(fontWeight);\n  }\n\n  const fontStyle = prop(options, 'font-style', style.getPropertyValue('font-style'));\n  if (['normal', 'italic', 'oblique'].includes(fontStyle)) {\n    font.push(fontStyle);\n  }\n\n  const fontVariant = prop(options, 'font-variant', style.getPropertyValue('font-variant'));\n  if (['normal', 'small-caps'].includes(fontVariant)) {\n    font.push(fontVariant);\n  }\n\n  const fontSize = prop(options, 'font-size', style.getPropertyValue('font-size')) || DEFAULTS['font-size'];\n  const fontSizeValue = pxValue(fontSize);\n  font.push(fontSizeValue + 'px');\n\n  const fontFamily = prop(options, 'font-family', style.getPropertyValue('font-family')) || DEFAULTS['font-family'];\n  font.push(fontFamily);\n\n  return font.join(' ');\n}\n\n/**\n * Check for CSSStyleDeclaration\n *\n * @param val\n * @returns {bool}\n */\nexport function isCSSStyleDeclaration(value) {\n  return value && typeof value.getPropertyValue === 'function';\n}\n\n/**\n * Check wether we can get computed style\n *\n * @param el\n * @returns {bool}\n */\nexport function canGetComputedStyle(element) {\n  return (\n    isElement(element) &&\n    element.style &&\n    typeof window !== 'undefined' &&\n    typeof window.getComputedStyle === 'function'\n  );\n}\n\n/**\n * Check for DOM element\n *\n * @param el\n * @retutns {bool}\n */\nexport function isElement(element) {\n  return typeof HTMLElement === 'object'\n    ? element instanceof HTMLElement\n    : Boolean(\n        element &&\n          typeof element === 'object' &&\n          element !== null &&\n          element.nodeType === 1 &&\n          typeof element.nodeName === 'string'\n      );\n}\n\n/**\n * Check if argument is object\n * @param obj\n * @returns {boolean}\n */\nexport function isObject(object) {\n  return typeof object === 'object' && object !== null && !Array.isArray(object);\n}\n\n/**\n * Get style declaration if available\n *\n * @returns {CSSStyleDeclaration}\n */\nexport function getStyle(element, options) {\n  const options_ = {...options};\n  const {style} = options_;\n  if (!options) {\n    options = {};\n  }\n\n  if (isCSSStyleDeclaration(style)) {\n    return style;\n  }\n\n  if (canGetComputedStyle(element)) {\n    return window.getComputedStyle(element, prop(options, 'pseudoElt', null));\n  }\n\n  return {\n    getPropertyValue: (key) => prop(options, key),\n  };\n}\n\n/**\n * Normalize whitespace\n * https://developer.mozilla.org/de/docs/Web/CSS/white-space\n *\n * @param {string} text\n * @param {string} ws whitespace value\n * @returns {string}\n */\nexport function normalizeWhitespace(text, ws) {\n  switch (ws) {\n    case 'pre': {\n      return text;\n    }\n\n    case 'pre-wrap': {\n      return text;\n    }\n\n    case 'pre-line': {\n      return (text || '').replace(/\\s+/gm, ' ').trim();\n    }\n\n    default: {\n      return (text || '')\n        .replace(/[\\r\\n]/gm, ' ')\n        .replace(/\\s+/gm, ' ')\n        .trim();\n    }\n  }\n}\n\n/**\n * Get styled text\n *\n * @param {string} text\n * @param {CSSStyleDeclaration} style\n * @returns {string}\n */\nexport function getStyledText(text, style) {\n  switch (style.getPropertyValue('text-transform')) {\n    case 'uppercase': {\n      return text.toUpperCase();\n    }\n\n    case 'lowercase': {\n      return text.toLowerCase();\n    }\n\n    default: {\n      return text;\n    }\n  }\n}\n\n/**\n * Trim text and repace some breaking htmlentities for convenience\n * Point user to https://mths.be/he for real htmlentity decode\n * @param text\n * @returns {string}\n */\nexport function prepareText(text) {\n  // Convert to unicode\n  text = (text || '')\n    .replace(/<wbr>/gi, '\\u200B')\n    .replace(/<br\\s*\\/?>/gi, '\\u000A')\n    .replace(/&shy;/gi, '\\u00AD')\n    .replace(/&mdash;/gi, '\\u2014');\n\n  if (/&#(\\d+)(;?)|&#[xX]([a-fA-F\\d]+)(;?)|&([\\da-zA-Z]+);/g.test(text) && console) {\n    console.error(\n      'text-metrics: Found encoded htmlenties. You may want to use https://mths.be/he to decode your text first.'\n    );\n  }\n\n  return text;\n}\n\n/**\n * Get textcontent from element\n * Try innerText first\n * @param el\n */\nexport function getText(element) {\n  if (!element) {\n    return '';\n  }\n\n  const text = element.textContent || element.textContent || '';\n\n  return text;\n}\n\n/**\n * Get property from src\n *\n * @param src\n * @param attr\n * @param defaultValue\n * @returns {*}\n */\nexport function prop(src, attr, defaultValue) {\n  return (src && src[attr] !== undefined && src[attr]) || defaultValue;\n}\n\n/**\n * Normalize options\n *\n * @param options\n * @returns {*}\n */\nexport function normalizeOptions(options) {\n  const options_ = {};\n\n  // Normalize keys (fontSize => font-size)\n  for (const key of Object.keys(options || {})) {\n    const dashedKey = key.replace(/([A-Z])/g, ($1) => '-' + $1.toLowerCase());\n    options_[dashedKey] = options[key];\n  }\n\n  return options_;\n}\n\n/**\n * Get Canvas\n * @param font\n * @throws {Error}\n * @return {Context2d}\n */\nexport function getContext2d(font) {\n  try {\n    const ctx = document.createElement('canvas').getContext('2d');\n    const dpr = window.devicePixelRatio || 1;\n    const bsr =\n      ctx.webkitBackingStorePixelRatio ||\n      ctx.mozBackingStorePixelRatio ||\n      ctx.msBackingStorePixelRatio ||\n      ctx.oBackingStorePixelRatio ||\n      ctx.backingStorePixelRatio ||\n      1;\n    ctx.font = font;\n    ctx.setTransform(dpr / bsr, 0, 0, dpr / bsr, 0, 0);\n    return ctx;\n  } catch (error) {\n    throw new Error('Canvas support required' + error.message);\n  }\n}\n\n/**\n * Check breaking character\n * http://www.unicode.org/reports/tr14/#Table1\n *\n * @param chr\n */\nfunction checkBreak(chr) {\n  return (\n    (B2.has(chr) && 'B2') ||\n    (BAI.has(chr) && 'BAI') ||\n    (SHY.has(chr) && 'SHY') ||\n    (BA.has(chr) && 'BA') ||\n    (BB.has(chr) && 'BB') ||\n    (BK.has(chr) && 'BK')\n  );\n}\n\nexport function computeLinesDefault({ctx, text, max, wordSpacing, letterSpacing}) {\n  const addSpacing = addWordAndLetterSpacing(wordSpacing, letterSpacing);\n  const lines = [];\n  const parts = [];\n  const breakpoints = [];\n  let line = '';\n  let part = '';\n\n  if (!text) {\n    return [];\n  }\n\n  // Compute array of breakpoints\n  for (const chr of text) {\n    const type = checkBreak(chr);\n    if (part === '' && type === 'BAI') {\n      continue;\n    }\n\n    if (type) {\n      breakpoints.push({chr, type});\n\n      parts.push(part);\n      part = '';\n    } else {\n      part += chr;\n    }\n  }\n\n  if (part) {\n    parts.push(part);\n  }\n\n  // Loop over text parts and compute the lines\n  for (const [i, part] of parts.entries()) {\n    if (i === 0) {\n      line = part;\n      continue;\n    }\n\n    const breakpoint = breakpoints[i - 1];\n    // Special treatment as we only render the soft hyphen if we need to split\n    const chr = breakpoint.type === 'SHY' ? '' : breakpoint.chr;\n    if (breakpoint.type === 'BK') {\n      lines.push(line);\n      line = part;\n      continue;\n    }\n\n    // Measure width\n    const rawWidth = ctx.measureText(line + chr + part).width + addSpacing(line + chr + part);\n    const width = Math.round(rawWidth);\n\n    // Still fits in line\n    if (width <= max) {\n      line += chr + part;\n      continue;\n    }\n\n    // Line is to long, we split at the breakpoint\n    switch (breakpoint.type) {\n      case 'SHY': {\n        lines.push(line + '-');\n        line = part;\n        break;\n      }\n\n      case 'BA': {\n        lines.push(line + chr);\n        line = part;\n        break;\n      }\n\n      case 'BAI': {\n        lines.push(line);\n        line = part;\n        break;\n      }\n\n      case 'BB': {\n        lines.push(line);\n        line = chr + part;\n        break;\n      }\n\n      case 'B2': {\n        if (Number.parseInt(ctx.measureText(line + chr).width + addSpacing(line + chr), 10) <= max) {\n          lines.push(line + chr);\n          line = part;\n        } else if (Number.parseInt(ctx.measureText(chr + part).width + addSpacing(chr + part), 10) <= max) {\n          lines.push(line);\n          line = chr + part;\n        } else {\n          lines.push(line, chr);\n          line = part;\n        }\n\n        break;\n      }\n\n      default: {\n        throw new Error('Undefoined break');\n      }\n    }\n  }\n\n  if ([...line].length > 0) {\n    lines.push(line);\n  }\n\n  return lines;\n}\n\nexport function computeLinesBreakAll({ctx, text, max, wordSpacing, letterSpacing}) {\n  const addSpacing = addWordAndLetterSpacing(wordSpacing, letterSpacing);\n  const lines = [];\n  let line = '';\n  let index = 0;\n\n  if (!text) {\n    return [];\n  }\n\n  for (const chr of text) {\n    const type = checkBreak(chr);\n    // Mandatory break found (br's converted to \\u000A and innerText keeps br's as \\u000A\n    if (type === 'BK') {\n      lines.push(line);\n      line = '';\n      continue;\n    }\n\n    const lineLength = line.length;\n    if (BAI.has(chr) && (lineLength === 0 || BAI.has(line[lineLength - 1]))) {\n      continue;\n    }\n\n    // Measure width\n    let rawWidth = ctx.measureText(line + chr).width + addSpacing(line + chr);\n    let width = Math.ceil(rawWidth);\n\n    // Check if we can put char behind the shy\n    if (type === 'SHY') {\n      const next = text[index + 1] || '';\n      rawWidth = ctx.measureText(line + chr + next).width + addSpacing(line + chr + next);\n      width = Math.ceil(rawWidth);\n    }\n\n    // Needs at least one character\n    if (width > max && [...line].length > 0) {\n      switch (type) {\n        case 'SHY': {\n          lines.push(line + '-');\n          line = '';\n          break;\n        }\n\n        case 'BA': {\n          lines.push(line + chr);\n          line = '';\n          break;\n        }\n\n        case 'BAI': {\n          lines.push(line);\n          line = '';\n          break;\n        }\n\n        default: {\n          lines.push(line);\n          line = chr;\n          break;\n        }\n      }\n    } else if (chr !== '\\u00AD') {\n      line += chr;\n    }\n\n    index++;\n  }\n\n  if ([...line].length > 0) {\n    lines.push(line);\n  }\n\n  return lines;\n}\n","/* eslint-env es6, browser */\nimport * as _ from './utils.js';\n\nclass TextMetrics {\n  constructor(element, overwrites = {}) {\n    if (!_.isElement(element) && _.isObject(element)) {\n      this.el = undefined;\n      this.overwrites = _.normalizeOptions(element);\n    } else {\n      this.el = element;\n      this.overwrites = _.normalizeOptions(overwrites);\n    }\n\n    this.style = _.getStyle(this.el, this.overwrites);\n    this.font = _.prop(overwrites, 'font', null) || _.getFont(this.style, this.overwrites);\n  }\n\n  padding() {\n    return this.el\n      ? Number.parseInt(this.style.paddingLeft || 0, 10) + Number.parseInt(this.style.paddingRight || 0, 10)\n      : 0;\n  }\n\n  parseArgs(text, options = {}, overwrites = {}) {\n    if (typeof text === 'object' && text) {\n      overwrites = options;\n      options = text || {};\n      text = undefined;\n    }\n\n    const styles = {...this.overwrites, ..._.normalizeOptions(overwrites)};\n    const ws = _.prop(styles, 'white-space') || this.style.getPropertyValue('white-space');\n\n    if (!options) {\n      options = {};\n    }\n\n    if (!overwrites) {\n      options = {};\n    }\n\n    text =\n      !text && this.el ? _.normalizeWhitespace(_.getText(this.el), ws) : _.prepareText(_.normalizeWhitespace(text, ws));\n\n    return {text, options, overwrites, styles};\n  }\n\n  /**\n   * Compute Text Metrics based for given text\n   *\n   * @param {string} text\n   * @param {object} options\n   * @param {object} overwrites\n   * @returns {function}\n   */\n  width(...args) {\n    const {text, options, overwrites, styles} = this.parseArgs(...args);\n\n    if (!text) {\n      return 0;\n    }\n\n    const font = _.getFont(this.style, styles);\n    const letterSpacing = _.prop(styles, 'letter-spacing') || this.style.getPropertyValue('letter-spacing');\n    const wordSpacing = _.prop(styles, 'word-spacing') || this.style.getPropertyValue('word-spacing');\n    const addSpacing = _.addWordAndLetterSpacing(wordSpacing, letterSpacing);\n    const ctx = _.getContext2d(font);\n    const styledText = _.getStyledText(text, this.style);\n\n    if (options.multiline) {\n      // eslint-disable-next-line unicorn/no-array-reduce\n      return this.lines(styledText, options, overwrites).reduce((result, text) => {\n        const w = ctx.measureText(text).width + addSpacing(text);\n\n        return Math.max(result, w);\n      }, 0);\n    }\n\n    return ctx.measureText(styledText).width + addSpacing(styledText);\n  }\n\n  /**\n   * Compute height from textbox\n   *\n   * @param {string} text\n   * @param {object} options\n   * @param {object} overwrites\n   * @returns {number}\n   */\n  height(...args) {\n    const {text, options, styles} = this.parseArgs(...args);\n\n    const lineHeight = Number.parseFloat(_.prop(styles, 'line-height') || this.style.getPropertyValue('line-height'));\n\n    return Math.ceil(this.lines(text, options, styles).length * lineHeight || 0);\n  }\n\n  /**\n   * Compute lines of text with automatic word wraparound\n   * element styles\n   *\n   * @param {string} text\n   * @param {object} options\n   * @param {object} overwrites\n   * @returns {*}\n   */\n  lines(...args) {\n    const {text, options, overwrites, styles} = this.parseArgs(...args);\n\n    const font = _.getFont(this.style, styles);\n\n    // Get max width\n    let max =\n      Number.parseInt(_.prop(options, 'width') || _.prop(overwrites, 'width'), 10) ||\n      _.prop(this.el, 'offsetWidth', 0) ||\n      Number.parseInt(_.prop(styles, 'width', 0), 10) ||\n      Number.parseInt(this.style.width, 10);\n\n    max -= this.padding();\n\n    const wordBreak = _.prop(styles, 'word-break') || this.style.getPropertyValue('word-break');\n    const letterSpacing = _.prop(styles, 'letter-spacing') || this.style.getPropertyValue('letter-spacing');\n    const wordSpacing = _.prop(styles, 'word-spacing') || this.style.getPropertyValue('word-spacing');\n    const ctx = _.getContext2d(font);\n    const styledText = _.getStyledText(text, this.style);\n\n    // Different scenario when break-word is allowed\n    if (wordBreak === 'break-all') {\n      return _.computeLinesBreakAll({\n        ctx,\n        text: styledText,\n        max,\n        wordSpacing,\n        letterSpacing,\n      });\n    }\n\n    return _.computeLinesDefault({\n      ctx,\n      text: styledText,\n      max,\n      wordSpacing,\n      letterSpacing,\n    });\n  }\n\n  /**\n   * Compute Text Metrics based for given text\n   *\n   * @param {string} text\n   * @param {object} options\n   * @param {object} overwrites\n   * @returns {string} Pixelvalue e.g. 14px\n   */\n  maxFontSize(...args) {\n    const {text, options, overwrites, styles} = this.parseArgs(...args);\n\n    // Simple compute function which adds the size and computes the with\n    const compute = (size) => {\n      return Math.ceil(\n        this.width(text, options, {\n          ...styles,\n          'font-size': size + 'px',\n        })\n      );\n    };\n\n    // Get max width\n    let max =\n      Number.parseInt(_.prop(options, 'width') || _.prop(overwrites, 'width'), 10) ||\n      _.prop(this.el, 'offsetWidth', 0) ||\n      Number.parseInt(_.prop(styles, 'width', 0), 10) ||\n      Number.parseInt(this.style.width, 10);\n\n    max -= this.padding();\n\n    // Start with half the max size\n    let size = Math.floor(max / 2);\n    let cur = compute(size);\n\n    // Compute next result based on first result\n    size = Math.floor((size / cur) * max);\n    cur = compute(size);\n\n    // Happy cause we got it already\n    if (Math.ceil(cur) === max) {\n      return size ? size + 'px' : undefined;\n    }\n\n    // Go on by increase/decrease pixels\n    const greater = cur > max && size > 0;\n    while (cur > max && size > 0) {\n      size -= 1;\n      cur = compute(size);\n    }\n\n    if (!greater) {\n      while (cur < max) {\n        cur = compute(size + 1);\n        if (cur > max) {\n          return size ? size + 'px' : undefined;\n        }\n\n        size += 1;\n      }\n    }\n\n    return size ? size + 'px' : undefined;\n  }\n}\n\nexport const init = (element, overwrites) => new TextMetrics(element, overwrites);\n\nexport const utils = {..._};\n"],"names":["B2","Set","SHY","BAI","BA","BB","BK","pxValue","value_","options","baseFontSize","Number","parseInt","prop","value","parseFloat","unit","replace","Error","addWordAndLetterSpacing","ws","ls","denyList","wordAddon","has","letterAddon","text","trim","split","length","getFont","style","font","fontWeight","getPropertyValue","includes","toString","push","fontStyle","fontVariant","fontSizeValue","fontFamily","join","isCSSStyleDeclaration","canGetComputedStyle","element","isElement","window","getComputedStyle","HTMLElement","Boolean","nodeType","nodeName","isObject","object","Array","isArray","getStyle","options_","_objectSpread","key","normalizeWhitespace","getStyledText","toUpperCase","toLowerCase","prepareText","test","console","error","getText","textContent","src","attr","defaultValue","undefined","normalizeOptions","Object","keys","$1","getContext2d","ctx","document","createElement","getContext","dpr","devicePixelRatio","bsr","webkitBackingStorePixelRatio","mozBackingStorePixelRatio","msBackingStorePixelRatio","oBackingStorePixelRatio","backingStorePixelRatio","setTransform","message","checkBreak","chr","computeLinesDefault","max","wordSpacing","letterSpacing","addSpacing","lines","parts","breakpoints","line","part","type","i","entries","breakpoint","rawWidth","measureText","width","Math","round","computeLinesBreakAll","index","lineLength","ceil","next","TextMetrics","constructor","overwrites","_","this","el","padding","paddingLeft","paddingRight","parseArgs","styles","slice","call","arguments","styledText","multiline","reduce","result","w","height","lineHeight","wordBreak","maxFontSize","compute","size","floor","cur","greater","init","utils"],"mappings":"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"}