diff --git a/README.md b/README.md index 9371c3d..3202085 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ result = typo_mixed_mode.process(text="Этот текст будет обраб двумя символами `\u228a\ufe00` и превратится в `⊊\ufe00`. Символ `\ufe00` — это невидимый символ, cелектор варианта начертания (Variant Selector), который изменяет начертание предыдущего символа и для него нет html-мнемоники. К счастью, в стандарте таких мнемоник (превращающихся в два символа) исчезающе мало и они крайне - редко применяются в тексте, поэтому это не должно вызывать проблем. + редко применляются в тексте, поэтому это не должно вызывать проблем. ### Переносы слов @@ -294,9 +294,9 @@ result = typo.process("100 км/ч") # Останется без ### Висячая типографика Висячая типографика — это приём из классической вёрстки, когда некоторые знаки препинания (кавычки, скобки, иногда -тире и маркеры списков) выносятся на левое (и иногда и по правому, при выравнивании текст по правому краю) поле текста. -Это создаёт идеально ровный край не по формальным границам знаков, а по оптическому краю — по первым буквам строк. -Текст выглядит гораздо аккуратнее и профессиональнее. +tире и маркеры списков) выносятся на левое (и иногда и по правому) поле текста. Это создаёт идеально ровный край не по +формальным границам знаков, а по оптическому краю — по первым буквам строк. Текст выглядит гораздо аккуратнее и +профессиональнее. Интернет публикации (да и бумажные издания) практически игнорируют висячую типографику. Но иногда это отличный инструмент для акцентной типографики: крупные заголовки, цитаты, выносы, подписи к иллюстрациям, оформленные с помощью @@ -306,9 +306,10 @@ Safari), поэтому на него полагаться нельзя. Поэ через оборачивание висячих символов в специальные HTML-теги с CSS-классами. Оборачивая "висячий" символ или слово в `` и применяя к нему, например, отрицательный `text-indent` или -`margin-left` (`«`). Важный нюанс: степень "вывешивания" у символов -разная. И не только потому, что кавычка, скобка или точка имеют разную ширину, но еще и потому, что кавычка, например, -может "висеть" на 100% своей ширины, а точка или запятая — только на 50-70%, чтобы не отрываться от слова совсем. +`margin-left` (`«`), мы можем сместить сам символ, но нужно ещё и +сохранить расстояние до соседнего слова. Поэтому типограф оборачивает не только сам висячий символ, но и ближайшее слово +(до пробела или границы узла), а также, при необходимости, окружающий пробел. Сама визуальная компенсация оформляется через +отрицательные `margin`/`padding` в CSS-классах — никаких `position:absolute`, чтобы не нарушать поток текста. По умолчанию эта функция висячей типографики **отключена**. Чтобы её включить, нужно задать параметр `hanging_punctuation` при конфигурировании типографа (по умолчанию `hanging_punctuation=None`): @@ -318,40 +319,74 @@ typo = etpgrf.Typographer(hanging_punctuation='left') ``` Параметр `hanging_punctuation` может принимать следующие значения: -* `None`или `False` — функция отключена (по умолчанию); -* `'left'` — включены только левые висячие символы (выравнивание по левому краю); -* `'right'` — включены только правые висячие символы (выравнивание по правому краю); -* `'both'` или `True` — включены и левые, и правые висячие символы. +* `None` или `False` — функция отключена (по умолчанию); +* `'left'` или `True` — включены только левые висячие символы (выравнивание по левому краю); +* `'right'` — включены только правые висячие символы (выравнивание по правому краю). -Так же через `hanging_punctuation` можно задать список тегов, внутри которых висячая типографика будет применяться -(всегда в режиме `'both'`). Это нерекомендованный способ (так как предполагает знание об исходном тексте, и не сработает -для сточных тегов, а поведение "блочных" и "строчных" может быть переназначено через CSS). Тем не менее управление -висячей пунктуацией на уровне тегов может быть полезно в некоторых, редких случаях: -```python -typo = etpgrf.Typographer(hanging_punctuation=['blockquote', 'h2', 'h3']) +Значения `'both'` **недоступно**, потому что совмещение левой и правой выверки одновременно приводит к конфликтам +с размещением пробелов и делает невозможным контролировать визуальное выравнивание (см. блок про `text-justify`). + +Также через `hanging_punctuation` можно задать список тегов, внутри которых висячая типографика будет применяться +(всегда в режиме `'both'`). Это нерекомендованный способ, потому что он предполагает знание структуры HTML и неизбежно +выпадает из общей логики вложенности и пробельных узлов. + +### Как работает оборачивание + +Процессор висячей типографики запускается после всех текстовых преобразований и работает с деревом BeautifulSoup. Он ищет +последовательности «пробел + висячий символ» для левого выравнивания и «слово + висячий символ + пробел» для правого, +чтобы обернуть нужные фрагменты в пары `` и не допустить «сиротства» символов. Порядок действий можно описать так: +* Для `hanging_punctuation='left'`: + * если символ стоит в начале текстового узла (без пробелов слева), оборачивается только сам символ и следующее + слово (`«АукЫон»`); + * если перед символом внутри узла есть пробел, то пробел оборачивается в ` `, а + символ вместе со словом — в `...`; + * если пробел оказалось в соседнем узле, то он тоже оборачивается в `etp-sp-*`, чтобы не нарушить последовательность; + * если компенсирующий пробел является "непереносимым пробелом" (или любым другим: шпацией, em-пробелом и т.п.), то тогда, для правильного выравнивания, оборачивается он, например: ` «АукЫон»`. +* Для `hanging_punctuation='right'`: + * слово с висячим символом оборачивается в соответствующий класс (`.etp-raquo`, `.etp-rpar` и т.д.); + * пробел сразу после символа получает класс `etp-sp-raquo`, `etp-sp-rpar` и т.д., чтобы сохранить переносную ширину и + аккуратно компенсировать смещение; + + +Пример вывода для `'left'`: + +```html +Завтра концерт группы «АукЫон» ``` -Рекомендуемый CSS для этих классов выглядит так (возможно, вам придется подкорректировать значения `em` в зависимости -от используемого шрифта, его толщины и начертания): +### CSS для висячих символов + +Предлагаемый CSS теперь работает только с `margin` и `padding`, без `position:absolute`. Пробелы получают собственные +классы, поэтому их компенсация контролируется отдельно, а не встроена в сам висячий символ. Убедитесь, что эти стили +подключены к странице и не конфликтуют с `text-justify`, который вытягивает пробелы по всей строке и разрушает аккуратное +выравнивание. ```css -/* --- ЛЕВЫЕ ВИСЯЧИЕ СИМВОЛЫ (выравнивание по левому краю) --- */ -.etp-laquo { margin-left: -0.44em; } /* « */ -.etp-ldquo, .etp-bdquo { margin-left: -0.4em; } /* “ „ */ -.etp-lsquo { margin-left: -0.22em; } /* ‘ */ -.etp-lpar, .etp-lsqb, .etp-lcub { margin-left: -0.25em; } /* ( [ { */ +/* --- ЛЕВЫЕ ВИСЯЧИЕ СИМВОЛЫ --- */ +.etp-laquo { margin-left: -0.44em; } +.etp-ldquo, .etp-bdquo { margin-left: -0.4em; } +.etp-lsquo { margin-left: -0.22em; } +.etp-lpar, .etp-lsqb, .etp-lcub { margin-left: -0.25em; } +/* компенсирующие пробелы для левых висячих символов */ +.etp-sp-laquo { padding-right: 0.44em; } +.etp-sp-ldquo, .etp-sp-bdquo { padding-right: 0.4em; } +.etp-sp-lsquo { padding-right: 0.22em; } +.etp-sp-lpar, .etp-sp-lsqb, .etp-sp-lcub { padding-right: 0.25em; } -/* --- ПРАВЫЕ ВИСЯЧИЕ СИМВОЛЫ (выравнивание по правому краю) --- */ -/* Общая механика: "вырываем" символ из потока для идеального выравнивания текста */ -[class^="etp-r"], [class*=" etp-r"] { position: absolute; } -/* Точечная настройка смещения для каждого символа */ -.etp-raquo { right: -0.44em; } /* » */ -.etp-rdquo { right: -0.4em; } /* ” */ -.etp-rsquo { right: -0.22em; } /* ’ */ -.etp-rpar, .etp-rsqb, .etp-rcub { right: -0.25em; } /* ) ] } */ -.etp-r-dot, .etp-r-comma, .etp-r-colon { right: -0.15em; } /* . , : */ +/* --- ПРАВЫЕ ВИСЯЧИЕ СИМВОЛЫ --- */ +.etp-raquo { padding-right: 0.44em; margin-left: -0.44em; } +.etp-rdquo { padding-right: 0.4em; margin-left: -0.4em; } +.etp-rsquo { padding-right: 0.22em; margin-left: -0.22em; } +.etp-rpar, .etp-rsqb, .etp-rcub { padding-right: 0.25em; margin-left: -0.25em; } +/* компенсирующие пробелы для правых висячих символов */ +.etp-sp-raquo { margin-left: -0.44em; } +.etp-sp-rdquo { margin-left: -0.4em; } +.etp-sp-rsquo { margin-left: -0.22em; } +.etp-sp-rpar, .etp-sp-rsqb, .etp-sp-rcub { margin-left: -0.25em; } ``` +*Комментарии:* Двухстороннее выравнивание текстового блока с помощью стиля `text-justify` в принципе плохо совместим концепцией типографики — он растягивает или сжимает пробелы по всей строке (а это пробелы между словами) и уже этими, переменными, пробелами, делает текст трудночитаемым. Если же вы используете `text-justify` для выравнивания текста по ширине, то, чтобы сохранить оптимальную читаемость текста, включать висячую типографику не рекомендуется. + ## Известные особенности и ограничения При обработке сложного HTML-кода типограф стремится сохранить структуру документа, но некоторые пограничные случаи могут обрабатываться не так, как ожидается. В частности: @@ -371,4 +406,4 @@ typo = etpgrf.Typographer(hanging_punctuation=['blockquote', 'h2', 'h3']) ## Credits **Разработка:** -Проект разработан Sergei Erjemin при активном участии Gemini Assistant (LLM) в роли pair-programmer. +Проект разработан Sergei Erjemin при активном участии различных LLM в роли pair-programmer.