Pretext – biblioteca de layout em JS puro para medir a altura de texto sem DOM
(github.com/chenglou)Descobrir quantas linhas um texto ocupa no navegador é mais complicado do que parece. Normalmente usa-se getBoundingClientRect ou offsetHeight, mas esses métodos forçam o navegador a recalcular o layout. O chamado reflow de layout. Do ponto de vista do navegador, isso é uma tarefa bem pesada.
O Pretext resolve esse problema de outra forma. Com measureText() do Canvas, ele obtém diretamente do mecanismo de fontes a largura dos caracteres e, depois disso, o cálculo das linhas é feito apenas com operações aritméticas puras usando valores de largura em cache. Não acessa o DOM em nenhum momento.
const prepared = prepare('AGI 春天到了. بدأت الرحلة 🚀', '16px Inter')
const { height, lineCount } = layout(prepared, textWidth, 20)
O desempenho também impressiona. Com base no layout de 500 textos, prepare() leva cerca de 19 ms, e depois layout() fica na faixa de 0,09 ms.
Dois modos de uso
Se você só precisa da altura, a combinação prepare() + layout() resolve tudo. Pode ser usada para implementar listas virtualizadas, manter a posição de rolagem ou verificar se um texto gerado por IA ultrapassa os limites de um botão.
Se quiser controlar diretamente o layout linha a linha, dá para usar APIs como layoutWithLines(), walkLineRanges() e layoutNextLine(). Também pode ser integrado com Canvas, SVG, WebGL e renderização no servidor, além de lidar com layouts em que a largura varia por linha, como quando o texto contorna uma imagem.
Há suporte até para emojis, CJK e texto bidirecional como árabe. Um projeto de chenglou, criador do React e do Relay. ⭐ 7.1k
https://github.com/chenglou/pretext
3 comentários
No link do GitHub lá embaixo, parece que vários
%E2%80%8B(zero-width space) estão sendo anexados.js
.replace(/\u200b/g, '')Acho que a página https://chenglou.me/pretext/editorial-engine/ que está na demo é a que mostra isso melhor.
Não é algo que eu conheça e use bem, então peço compreensão desde já.
Pelo que entendi, ele recalcula com base no
measureTextdo canvas...Não consigo confiar nessa API.
Mais precisamente, não é que eu não confie na API em si,
mas, para renderizar o DOM da mesma forma, é preciso fazer os valores de condição coincidirem perfeitamente para que
a altura e a forma que você vê no navegador sejam idênticas também quando trazidas no formato da API.
Tenho um pesadelo arrepiante de não ter percebido isso e ficar me perguntando por que os valores saíam diferentes e surgiam bugs...