# All files / utils getTextMetrics.ts

95.24% Statements 20/21
75% Branches 3/4
100% Functions 2/2
95% Lines 19/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52

    1x
    3x
    1x

    2x
    2x

    2x
    2x
    2x

    2x

    1x
    3x
    3x

    3x

    3x

    3x

    3x

    3x

    3x

    3x

     export interface TextMetrics {
      width: number
      height: number
    }

    const addPaddingToSampleText = (text: string): string => {
      if (typeof text !== 'string') {
        return text
      }

      const skinnyCharacters = ['-', '1', '|', 'i', 'l', 'I', 't']
      let sample = text

      for (let index = 0; index < text.length; index += 1) {
        const char = text.charAt(index)
        Iif (skinnyCharacters.includes(char)) {
          sample += char
        }
      }
      return sample
    }

    export const getTextMetrics = (font: string, text: string): TextMetrics => {
      const div = document.createElement('div')
      const span = document.createElement('span')

      div.appendChild(span)

      // Translate offscreen
      div.setAttribute(
        'style',
        `font: ${font}; display: inline; position: fixed; transform: translate(-9999px, -9999px);`
      )

      document.body.appendChild(div)

      // Text with the same number of characters:
      //   when it includes a skinny character (defined above), it tends to be skinnier than
      //   a positive number because the skinny character is not as wide as a single digit (most of the time).
      //   Add padding when text has a skinny character by making them twice as wide.
      span.innerText = addPaddingToSampleText(text)

      const metrics = {
        width: span.offsetWidth,
        height: span.offsetHeight,
      }

      document.body.removeChild(div)

      return metrics
    }