Pull to refresh

Comments 16

Можно также улучшить читаемость текста с помощью CSS-свойства text-wrap: pretty; оно правда не устоявшееся.

Была статья на хабре https://habr.com/ru/articles/899194/

Видел, но, если не ошибаюсь, вопрос с "висячими" словами же не решает?

Да-да, text-wrap не решает задачу избавления от висячих предлогов

Решает. Другой момент, что именно вы называете висячим словом. Вижу у вас в массиве предлог "перед", это целых 5 букв. Не удивлюсь, если text-wrap: pretty не переносит слова подобных размеров и не должен

Автор этой статьи в самом начале определяет, что он имеет ввиду под "висячими словами"

> В типографике существует понятие “висячих слов” — это короткие слова (предлоги, союзы, местоимения), которые остаются в конце строки при переносе текста. Такие переносы нарушают удобочитаемость и эстетику текста. В русской типографике принято избегать переносов после коротких слов длиной 1-2 символа.

В самом коде все предлоги и союзы определяются в это понятие "висячего слова". Вот по такой формулировке text-wrap ничего не решает.

Бобо мертва. На круглые глаза

вид горизонта действует, как нож, но

тебя, Бобо, Кики или Заза

им не заменят. Это невозможно.

Вжух — и форматирование Бродского поехало)

Итого получаем:

  1. Перебор ВСЕГО дом-дерева в поисках указанных текстовых элементов;

  2. Перебор получившегося массива текстовых элементов с последующим перебором текстовых элементов внутри него, т.е. цикл в цикле;

  3. И внутри этого цикла у нас replace, внутри коллбэка которого ещё и includes по массиву, т.е. ещё несколько переборов внутри переборов.

В плане производительности получается дичь, даже с сотней-другой текстовых элементов небольшого текстового содержания. На большом проекте скорее всего может просто повесить вкладку)

Как можно сделать быстрее/лучше/проще:

  1. Вынести текст в константы, и уже по ним устроить перебор - как минимум не придётся перебирать DOM в поисках текстовых элементов, а в элементах искать текстовые узлы. Можно отдать в них уже форматированный текст, а не наоборот. Предлоги вынести в Set вместо массива, чтобы исключить ещё один перебор.

  2. Неразрывные пробелы нужны не во всех случаях. Я бы даже сказал что они нужны реже, чем не нужны) текстовый блок относительно короткий или нет в нём коротких предлогов. Соответственно и перебирать их просто нет нужды. Здесь можно, используя описанный выше подход, итерироваться не по всем текстовым константам, а только по тем, где вам неразрывный пробел необходим. Например собирать из них отдельный массив/объект. Но так как при таком подходе уже придётся что-то отделять самостоятельно, то:

  3. Самое простое - в тех же текстовых константах(или в разметке на месте) ставить неразрывный пробел руками. Это делается один раз при вставке с макета, глаз обычно уже намётан. На текущем месте так и делаем, никто не пострадал.

А ещё изредка бывает так, что для мобильной вёрстки в конкретном месте перед коротким предлогом НЕ НУЖЕН неразрывный пробел, чтобы текст встал красиво. И в таком случае автоматика тоже будет мешать

Ну без тестов нельзя утверждать. У меня подобная вещь работает на странице. Текст длинной около 19К обрабатывается примерно за 110 мс.

Браузер Хром, Проц i5 12100

На мозиле немного дольше - 150 мс.

Это вы попробовали внедрить скрипт из статьи?

Нет. Свой. Никаких массивов, все на регулярках.

Можете поделиться решением?

Там даже еще ставятся неразрывные пробелы нулевой длины между скобками и содержимым внутри, знаки минус или дефис между буквами заменяются на неразрывный дефис, ставится неразрывный пробел перед тире.

Благодарю за такой подробный коммент!
В самом низу статьи писал о том, что, да, бывает на мобильном переносит не так, как хотелось бы и может "уехать" за контейнер длинное слово. Скрипт не идеален, в будущем, может быть, опубликую вторую версию того, как решать вопрос с "висячими". Пока использую этот скрипт на сайтах, где это "можно позволить", на высоко-посещаемых ресурсах не внедряю.

Ну не знаю, какой длины слово должно быть. Или компоновка неудачная (несколько колонок на мобильном не делают). При минимальной ширине на мобильнике 360 (может и бывает меньше, но давно не встречались) И высоте шрифта 14px - в строке помещается 36-40 символов. Ну не знаю я таких слов. На мобильных обычно делается выравнивание по левому краю и разрешение переносов. Все более-менее получается. Лесенка, но это же смартфон. Большего от него требовать трудно.

Там у меня примерно такой код

const reprednbs = /((?<![^\s\(«'"])(с|со|см\.|в|во|вне|у|к|ко|на|не|ни|над|по|под|про|при|за|о|от|об|обо|до|для|и|из|им\.|без|а|или|\/\/)(\s+|$))/ig;
const rechastnbs = /\s+(же|ли|бы)(?=[\s\)\.,\:;»'"$])/ig;
const redefis = /([^\s\u2002])([\-\u{2010}\u{2011}\u{2012}\u{2013}\u{2014}])([^\s\u2002])/ug;
const retire = /(\s+)([-\u{2010}\u{2011}\u{2012}\u{2013}\u{2014}])(\s+)/ug;


let rep = false
let text = node.data; // node - текстовый узел

/* Ставим неразрывный пробел после предлогов и частиц*/
if (reprednbs.test(text)) {
	text = text.replaceAll(reprednbs, '$2\u00a0');
	rep = true;
}
/* Ставим неразрывный пробел перед частицами бы ли же*/
if (rechastnbs.test(text)) {
	text = text.replaceAll(rechastnbs, '\u00a0$1');
	rep = true;
}
/* Ставим неразрывный  дефис*/
if (redefis.test(text)) {
	text = text.replaceAll(redefis, '$1\u2011$3');
	rep = true;
}
/* Ставим тире и неразрывный пробел перед ним*/
if (retire.test(text)) {
	text = text.replaceAll(retire, '\u00a0\u2014 ');
	rep = true;
}
//.... Еще всякие варианты
if (rep) {
	node.data = text;
}

Как ни странно, с предварительной проверкой ( if (re.test()) ) работает хоть и немного (3-5%) но быстрее.

У нас там на страницах бывает много формул, которые обрабатываются МathJаx. Так он может работать 3-5 сек. Да и грузится он не быстро. Пока он грузится (async), все это успеет обработаться.

Про высокопосещаемые ресурсы - непонятно. Они дают нагрузку на сервер. А обработка идет в браузере. Ему то все равно высоко это посещаемый ресурс или нет.

  1. В моем случае, это было у заголовка формы (по стилю он размером как h1).

  2. На "высокопосещаемых" время на загрузку данных с сервера больше же идет

Sign up to leave a comment.

Articles