Всё для технического документирования
+7 (925) 328-76-00
Разработка технической документации
Курсы для технических писателей
Программное обеспечение

Алгоритмы: Отделение контента от форматирования

10.03.2016

01Статья входит в цикл «Понимание и применение структурированного писательства».

Марк Бейкер в своей серии статей переходит от описания общих принципов структурирования писательства к описанию алгоритмов. Очередная статья посвящена вопросам отделения контента от форматирования, что позволяет писателям сосредоточиться на контенте, меньше уделяя внимание форматированию, а в перспективе и поведению текста на различных устройствах.


На этой стадии этой серии статей я собираюсь начать рассматривать алгоритмы структурированного писательства. Алгоритм — это формализованный метод для выполнения задачи. Мы часто связываем алгоритмы с компьютерами, т.к. для того, чтобы заставить компьютер что-либо сделать, мы должны формализовать алгоритм и представить его в виде программы. Но люди так же могут исполнять алгоритмы. Это одна из причин, почему мы обращаемся к структурированному писательству, с тем, чтобы передать трудоёмкие и обременительные алгоритмы писательства и публикации машинам.

Но перед тем, как передать процесс машине, необходимо не только определить и запрограммировать алгоритм, необходимо структурировать и ограничить данные, чтобы программа могла применить к ним алгоритм. Во многом именно поэтому мы структурируем писательство. Здесь проявляется симметрия: структурированное писательство занимается выделением в контенте инвариантов. При публикации происходит вставка этих инвариантов обратно. Алгоритмы выделения инвариантов зеркальны по отношению к алгоритмам, возвращающих их на место.

 

02

 

Это не значит, что писатели каждый раз во время работы выносят контент из домена носителя в домен документа или домен объекта. Весь контент проходит из домена объекта через домен документа в домен носителя. Структурированное писательство занимается записью контента на более ранней стадии процесса. Поэтому правильно разработанная система структурированного писательства позволяет писателю записывать свой контент без необходимости думать о том, как он будет представлен в домене документа или отформатирован в домене носителя.

Алгоритм выделения инвариантов из контента поэтому в основном ложится на человека, который разрабатывает структуры, в которых пишут писатели. Очень распространённая ошибка заключается в том, что процесс разработки разметки рассматривается просто как создание модели, которая отражает структуру контента. Такой подход часто не может единообразно выделять инварианты в контенте и оставляет нас с форматом, в котором тяжело писать и который тяжело обрабатывать. Куда лучше думать в терминах алгоритма для выделения инвариантов в контенте и соответствующих алгоритмах для вставки их обратно.

В нескольких следующих статьях мы рассмотрим алгоритмы для перемещения контента в обоих направлениях. Начнём с размышления о том, что есть изначально алгоритм структурированного писательства: отделение контента от форматирования или, как иногда выражаются, выделение контента от представления. Как мы увидим, то, что в точности считается «форматированием» и «представлением», не так очевидно.

Выделение инструкций стилей

Начнём с простого отрывка контента, который включает в себя описание его формата. Это не настоящий формат файла, просто нечто, что я создал для того, чтобы проиллюстрировать этот вопрос. Я использую синтаксис CSS, чтобы описать формат и представить определённые символы их названиями в квадратных скобках, просто чтобы мы могли увидеть, как в точности всё происходит:

{font: 10pt «Open Sans»}Ящик содержит:

{font: 10pt «Open Sans»}[bullet][tab]Песок

{font: 10pt «Open Sans»}[bullet][tab]Яйца

{font: 10pt «Open Sans»}[bullet][tab]Золото

Этот файл содержит контент и форматирование, так что давайте их разделим. Конечно, когда мы удаляем форматирование из контента, нам необходимо добавить что-то на его место, чтобы мы смогли добавить обратно такое (или иное) форматирование позже. (Алгоритм должен на самом деле называться не «отделение контента от форматирования», а «отделение форматирования от контента и замена его на что-то другое»).

Проще всего заменить информацию о форматировании стилями:

{style: paragraph}Ящик содержит:

{style: paragraph}[bullet][tab]Песок

{style: paragraph}[bullet][tab]Яйца

{style: paragraph}[bullet][tab]Золото

Затем, конечно, нам необходимо записать информацию о форматировании в стилях (мы отделяем её, не уничтожаем полностью):

paragraph = {font: 10pt «Open Sans»}

Теперь, когда они отделены, мы можем применять различное форматирование, изменяя определение стиля вместо изменения контента:

paragraph = {font: 12pt «Century Schoolbook»}

Выделение символов форматирования

Здорово, но предположим, что нам нужно изменить стиль буллитов, используемых для списков. Стиль используемых буллитов — определённо часть того, что мы рассматриваем в качестве «форматирования», но буллиты являются текстовыми символами. Чтобы их изменить, необходимо не только изменить шрифт, применяемый к символам, необходимо изменить сами символы.

Таким образом, иногда символы в вашем тексте являются частью контента, а иногда — частью форматирования. Так что теперь нам нужно расширить идею о стилях, включив контент.

paragraph = {font: 12pt «Century Schoolbook»}

bullet-paragraph = {font: 12pt «Century Schoolbook»}[bullet]

Теперь наш контент выглядит таким образом:

{style: paragraph}Ящик содержит:

{style: bullet-paragraph}[tab]Песок

{style: bullet-paragraph}[tab]Яйца

{style: bullet-paragraph}[tab]Золото

Правда, теперь писатель будет начинать элементы списка с табуляции, что неудобно и, возможно, несколько неправильно, так что мы перенесём этот символ также в стили.

paragraph = {font: 12pt «Century Schoolbook»}

bullet-paragraph = {font: 12pt «Century Schoolbook»}[bullet][tab]

Теперь наш контент выглядит так:

{style: paragraph}Ящик содержит:

{style: bullet-paragraph}Песок

{style: bullet-paragraph}Яйца

{style: bullet-paragraph}Золото

И теперь вы можете изменить стиль буллитов:

bullet-paragraph = {font: 12pt «Century Schoolbook»}[em dash][tab]

И теперь мы можем понять, что “bullet-paragraph” — уже больше не лучшее имя, потому что стилем теперь является дефис, не буллит. Другими словами, мы обнаружили, что мы проделали не такую хорошую работу по отделению контента от форматирования, как думали, потому что контент всё ещё содержит информацию о форматировании в форме именованного стиля для определенной части форматирования.

Именуйте свои абстракции корректно

Когда мы отделяем форматирование от контента, мы должны вставить что-то на его место, и при этом имеет значение, что именно и как оно названо. Если мы назовём неправильно, это вызовет неверные ожидания, в итог авторы будут использовать его некорректно, и это будет означать, что мы не сможем отформатировать контент надёжно.

Так что первый урок об алгоритме отделения контента от форматирования заключается в следующем: имеет значение то, как вы называете вещи. Когда вы это делаете, вы создаёте абстракцию, и вам необходимо понять, что представляет из себя эта абстракция и назвать её подходящим образом.

Так что у нас здесь за абстракция? Конечно, это список. Промаркированные абзацы — это элементы списка. Так что давайте сделаем это:

{style: paragraph}Ящик содержит:

{style: list-item}[tab]Песок

{style: list-item}[tab]Яйца

{style: list-item}[tab]Золото

и

list-item = {font: 12pt «Century Schoolbook»}[em dash][tab]

Убедитесь, что у вас правильный набор абстракций

Но затем, конечно, мы столкнёмся с такой проблемой:

{style: paragraph}Чтобы помыть голову:

{style: list-item}Намыльте

{style: list-item}Смойте

{style: list-item}Повторите

Здесь наш список должен иметь номера, не дефисы или буллиты. Так что мы понимаем, что абстракция, которая нам нужна, не такая широкая, как «все элементы списка». Мы смотрим на различия между разными типами элементов списка, который используем, и пытаемся сгруппировать их в типы абстракций и подкрепляем именами для этих типов. Например, мы остановимся на “ordered-list-item” (упорядоченный список) и “unordered-list-item” (неупорядоченный список). Тогда получаем:

{style: paragraph}Ящик содержит:

{style: unordered-list-item}[tab]Песок

{style: unordered-list-item}[tab]Яйца

{style: unordered-list-item}[tab]Золото

и

{style: paragraph}Чтобы помыть голову:

{style: ordered-list-item}Намыльте

{style: ordered-list-item}Смойте

{style: ordered-list-item}Повторите

И стиль для элементов упорядоченного списка теперь выглядит примерно так:

ordered-list-item = {font: 12pt «Century Schoolbook»}<count>.[tab]

И тогда мы поймём, что нам нужен способ для возрастания числа и для сброса его на 1 для нового списка. Так что получим:

{style: paragraph}Чтобы помыть голову:

{style: first-ordered-list-item}Намыльте

{style: ordered-list-item}Смойте

{style: ordered-list-item}Повторите

и

first-ordered-list-item = {font: 12pt «Century Schoolbook»}<count=1>.[tab]

ordered-list-item = {font: 12pt «Century Schoolbook»}<++count>.[tab]

(++count здесь означает добавление единицы к числу и последующее его отображение).

И это очень похоже на то, как вы сегодня создаёте списки в FrameMaker, а также в других инструментах. Но причина такого детального рассмотрения этого момента в том, чтобы показать, как это сложно даже на уровне такого незначительного разделения. Мы начали с простого удаления команд форматирования, но затем начали удалять также символы, что заставило нас включить символы в определения стилей, а затем быть способными в самом деле вычислять символы в наших определениях стилей. И мы увидели, что при проведении этих разделений мы создали абстракции, и что было важно учесть все случаи, которые нам могут встретиться и создать подходящие абстракции, чтобы их учесть.

 

03

 

Создайте контейнеры для предоставления контента

Одна из проблем в этом подходе заключается в том, что писатель должен помнить о необходимости применять разные стили для первого элемента списка. Было бы лучше, если бы они могли использовать одинаковый стиль для каждого элемента списка, и нумерация просто бы работала. Но это сделать сложно, потому что в контенте нет ничего, что говорило бы, где заканчивается один нумерованный список и начинается следующий. Для этого нам нужна новая абстракция. До настоящего времени у нас были абстракции двух видов элементов списков: элементы упорядоченных и неупорядоченных списков. Но у нас нет абстракции для самих списков.

До настоящего времени мы отделяли контент от форматирования исключительно в домене носителя. Мы заменяли прямые определения форматирования на непрямые определения через стили. Единственная вещь, которая абстрагирует всё это за пределами домена носителя — имена, которые мы даём стилям, которые создали. Но теперь мы рискуем отправиться в домен документа, создавая абстрактную идею списка и вставляя эту абстрактную идею в наш контент.

paragraph: Чтобы помыть голову:

list:

ordered-list-item:Намыльте

ordered-list-item:Смойте

ordered-list-item:Повторите

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

Создавая идею списка, мы имеем возможность дополнительно отделить форматирование списка от контента списка, потому что теперь алгоритм, тот, который я назову алгоритмом форматирования, может распознать его как список и может создать решения по форматированию, основанные на этом знании.

Вторая важная вещь, которая произошла, — контент больше не содержит ссылок на имена стилей. Вместо этого у нас есть структуры. Список, абзац и элемент нумерованного списка — всё это структуры.

Мы заменили стили структурами, потому что одна структура может дать разные стили в зависимости от того, где находится в документе. Алгоритм форматирования отвечает за определение, является ли такой-то элемент упорядоченного списка первым в списке, и форматирует его соответствующим образом. (Точно так же, как работает форматирование списков в CSS).

Теперь авторы больше не применяют стили к контенту, даже если они имеют абстрактные имена. Вместо этого они помещают контент в структуры и позволяют алгоритму форматирования применять структуры соответствующим образом. Результат: контент отделён от форматирования ещё сильнее.

Переместите абстракции в контейнеры

Но здесь возникает очевидная проблема. Что если автор невнимательно сделает это:

paragraph: Чтобы помыть голову:

list:

ordered-list-item: Намыльте

unordered-list-item: Смойте

ordered-list-item: Повторите

Чтобы этого избежать, мы переместим абстракцию наружу. Вместо элементов упорядоченного и неупорядоченного списка мы создадим упорядоченный и неупорядоченный списки:

paragraph: Чтобы помыть голову:

ordered-list:

list-item: Намыльте

list-item: Смойте

list-item: Повторите

и

paragraph: Ящик содержит:

unordered-list:

list-item: Песок

list-item: Яйца

list-item: Золото

И конечно, структуры элемента списка могут использоваться как в неупорядоченном списке, так и в упорядоченном, потому что это элемент списка для любого случая, и алгоритм форматирования может рассказать об отличиях на основе того, какому типу списка он принадлежит. Имя структуры “list-item” определяет его роль в документе (в своём контексте в документе), потому как он полностью отделён от того, каким образом будет стилизован.

Перемещение абстракции за пределы контейнера — важная часть алгоритма отделения контента от форматирования. Он сохраняет вещи связными и снижает число вещей, которые авторы должны помнить.

Создание контейнеров и абстрагирование отличий между их содержимым — важная часть отделения контента от форматирования. Например, HTML и Markdown оба предоставляют шесть различных уровней заголовков. Но контент под заголовком H2 или H5 не находится в каком-либо контейнере. Контент просто идёт после заголовка. Это означает, что весьма возможно и допустимо в этих языках размещать различные элементы заголовков в любой необходимой последовательности. Писатели должны уделять внимание тому, какой уровень заголовков они создают и как это соотносится с иерархией документа, который они создают.

Кроме того, писатели понимают, что чем больше номер элемента заголовка (H1 – H6), тем большим размером шрифта он отобразится при выводе. Они не знают, какой это шрифт будет или насколько большим он будет, но больше/меньше — это всё ещё различия в форматировании. Форматирование отделено от контента не полностью.

В качестве контраста в DocBook у нас есть элемент section. Как и список, секция — часть интерпретации писателей того, что они создают в документе, но она только обособляет, не проявляется в форматировании. Создавая элемент секции, DocBook создаёт концепт секции. И раз у нас есть экземпляр секции, нам нет необходимости в шести уровнях заголовков. У нас может быть один элемент с названием title. Секции могут быть вложены в другие секции, и алгоритм форматирования может применять к заголовку правильный стиль в зависимости от контекста:

section:

title:

paragraph:

section:

title:

Это исключает неправильный выбор заголовка, давая уверенность в том, что заголовки на выходе последовательно отражают структуры секций и подсекций документа.

(Здесь необходимо сказать, что необязательно каждый разделяет мнение, что заголовки в тексте отражают или должны отражать иерархию секций. Иногда они могут быть просто указателями на пути, и как любой указатель, размер знака отражает размер города, не строго иерархию размеров знака. Так что если вы смотрите на структуры документа таким образом, то должны выбрать другой способ отделения контента от форматирования в вашем контенте).

Выделение абстрактного форматирования

 

04

 

Мы отметили, что в случае упорядоченных и неупорядоченных списков отделение контента от форматирования на самом деле связано также некоторым образом с выделением контента. Или вернее, это связано с выделением некоторых символов. Другими словами, отличие между тем, что отображается в документе с помощью символьных кодов и тем, что представляется в других структурах данных — не обязательно одно и то же, так как существует логическое отличие между контентом и отформатированной формой с точки зрения структурированного писательства.

Рассмотрим структуру, которую можно назвать маркированным списком:

Улица: 123 Elm Street

Город: Smallville

Страна: USA

Индекс: 12345

Универсальная структура маркированного списка может выглядеть так:

labeled-list:

list-item:

label: Street

content: 123 Elm Street

Но что, если у вас сотни адресов, все с одинаковыми маркерами? В этом случае маркеры действительно являются контентом или же они будут форматированием? Раз они не меняются от одного списка к другому, мы могли бы рассматривать их как часть того, как представляется контент вместо того, чтобы рассматривать как часть самого контента. Так что мы ищем способ отделить их от контента.

Как всегда, когда мы отделяем что-то от контента, мы должны заменить его на что-то ещё, и этим чем-то обычно является подходящим образом названная структура. Так что это приводит нас к подобной структуре:

address:

street: 123 Elm Street

town: Smallville

country: USA

code: 12345

Теперь, конечно, мы переместили наш контент в домен объекта. Обратите внимание, что в наших предыдущих попытках отделения мы выделяли форматирование списка и заменяли его на абстрактную форму списка. Это определённо выделяет некоторую часть форматирования, но всё ещё оставляет нам списки. И решение перечислять элементы в документе — это всё ещё решение по форматированию/представлению.

Перемещение контента из домена носителя в домен документа действительно выделяет информацию о стилях, но всё ещё оставляет множество основного форматирования и решений по представлению, например, решение использовать списки или таблицы крепко связано с контентом. Отделение стилей от контента полезно со многих сторон, но оно не достигает полного отделения контента от форматирования.

Однако в примере домене объекта мы перемещаем наш домен за пределы маркированного списка и переносим его в абстрактную запись. Мы могли бы теперь получить алгоритм, преобразовывающий эту запись в несколько структур документа. Этот алгоритм, который я назову алгоритмом «представления», мог бы переводить это в маркированный список, таблицу, абзац (с полями, разделёнными запятыми) или строки адреса для конверта.

В домене объекта, где контент полностью отделён от форматирования, мы также достигаем возможности запрашивать и реорганизовывать контент множеством интересных и полезных способов (которые мы исследуем в будущих статьях).

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

Конечно, мы осветили далеко не всё, что можно было сказать об отделении контента. Фраза «отделение контента от форматирования» восходит к временам, когда в качестве носителя была только бумага. У современных электронных носителей есть не только форматирование, у них есть поведение. Отделение контента от поведения совершенно так же важно, как и отделение контента от форматирования. Мы рассмотрим, как его осуществлять, в будущих статьях.

Источник: Algorithms: Separating Content from Formatting

Тэги: , , , ,

< Вернуться к списку публикаций

Облако тегов