Недавно мне понадобилась библиотека на Javascript для измерения ширины пикселя текста в Node.Js. Использовался бэкэнд-парсер, который каждую секунду сканирует сотни страниц и получает всю информацию о каждой странице. Получить ширину текста в пикселях может показаться очень простым делом, но это было немного сложнее из-за рендеринга DOM на бэкэнде.

Моя первая идея была:

Ну, у меня на бэкэнде стоит Javascript, так что проблем не возникает. Я собираюсь просто поместить текст в элемент span и измерить его ширину - точно так же, как во внешнем интерфейсе.

Напишем это на Node.Js!

ReferenceError: document is not defined

Хьюстон, у нас проблема - в Node.Js нет DOM и, следовательно, нет «документа», конечно.

Но, без проблем, мы можем эмулировать DOM (кстати, так же, как тестируются компоненты React) с помощью пакета jsdom. Давай попробуем!

window.document.getElementById('h1')
> HTMLSpanElement {Symbol(impl): HTMLSpanElementImpl}
window.document.getElementById('h1').offsetWidth
> undefined

О нет! Это всего лишь эмуляция DOM, поэтому на самом деле ничего не отображается, и поэтому нет даже свойства offsetWidth.

После некоторого поиска в Google я нашел решение, но оно не очень удобно. Текст можно отобразить на холсте, а затем измерить. Это не совсем то, что я хотел, но попробуем, например, с пакетом cairo. Умм, Каиру нужна еще одна сторонняя библиотека для рендеринга. Это не то простое решение, которое я искал. Есть несколько других вариантов, например PhantomJS, но они действительно большие обходные пути, и они не быстрые.

Как мы можем это решить?

Подходящее решение, работающее для меня:

  1. Нам нужна ширина для каждого символа. Это нужно сделать при компиляции пакета, и в конце концов будет использоваться только карта ширины символов. Итак, у нас есть ширина каждого печатаемого символа ASCII (шрифтом Arial).
  2. Непечатаемые символы (в основном управляющие символы в байтах от 0 до 31) будут удалены из ввода. Символы, отличные от ASCII, будут преобразованы в ASCII. Например: ‘déjà vu’ = ›‘ deja vu ’.
  3. Теперь это просто. Для каждого символа в этой строке ASCII будет найдена его ширина на карте, и в конце будут подсчитаны все значения ширины.

Так был создан пакет npm string-pixel-width и как он работает :) Теперь, с этим, измерение ширины любой строки в пикселях стало очень простым:

Вы знаете о еще лучшем решении? Не стесняйтесь писать мне комментарий!