View source for Разметка

Имеется также ((/Doc/Deutsch/Markup Deutsch)), ((/Doc/Español/Markup Español)) и ((/Doc/English/Markup English))

Эта довольно длинная статья о том, как появилась "вака-разметка", и почему она такая, какая она сейчас есть. Если вы не знаете, что такое "вака-разметка" и, тем более, что такое "вики", вам стоит подробнее ознакомиться с сайтом проекта WackoWiki и прочитать тут пару статей ((/Doc/Русский документации)), в особенности статью про ((WikiКонцепции вики-концепции)).

{{toc numerate=1}}

=== О вака-разметке ===
Если коротко, то вака-разметка -- это особый способ форматирования текста, который позволяет при минимуме спецсимволов и минимальном визуальном искажении "исходного текста" получать после программного преобразования красивый HTML.

Возможностей вака-разметки хватает для полноценного оформления документов, больших и маленьких. Кроме традиционных модификаторов "курсива", "полужирного", "подчёркнутого" и "перечёркнутого" текста, здесь есть и разметка списков (в том числе и многоуровневых), заголовков, таблиц, картинок, выделение цитат и многое.

Вака-разметка используется в вики-движке WackoWiki и в других проектах разных разработчиков. Для того, чтобы внедрить вака-разметку в вашем проекте, вам достаточно скачать и встроить в ваш проект следующие компоненты:
  * ((/Dev/Projects/WackoFormatter вака-форматтер)), php-класс, превращающий вака-разметку в HTML;
  * ((/Dev/Projects/WikiEdit визуальный редактор)) для вики-текстов. Это необязательное, но чрезвычайно удобное дополнение к вака-форматтеру.

Исходный текст этой статьи написан в формате вака-разметки и ((!/source доступен для просмотра)).


=== Принципы, положенные в основу ===
Хотя вака-разметка изначально досталась (?нам Нам -- авторам, разработчикам WackoWiki (прим. авторов, разработчиков WackoWiki)?) в наследство от проекта ((/Doc/Русский/WakkaWiki WakkaWiki)) (ранее размещавшегося по адресу ~http://wakkawiki.de, но сейчас недоступного), в её основе были чёткие принципы, которые и определили её дальнейший успех.

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

Принципы были придуманы для того, чтобы достичь следующих целей:
  * снизить вероятность "случайного срабатывания" (т.е. когда обычный текст воспринимается как какая-то часть разметки);
  * добиться "интуитивной" и легко запоминаемой разметки;
  * защитить окружение форматированного текста от возможных опечаток автора.

==== Семантика должна передаваться через синтаксис ====
В основе любой вики-разметки лежит принцип (?WYTIWYG What You Think Is What You Get?), поэтому каждое правило вака-разметки старается своим оформлением (синтаксисом) отражать смысл (семантику). Поскольку в вака-разметке всё оформление делается средствами простого текста -- символами, которые можно набрать с клавиатуры, то мы старались подобрать такие комбинации, которые бы отражали смысл:
  * ##""**жирный**""## -- звёздочки для жирного текста, который **выделяется** из общей массы;
  * ##""//курсив//""## -- курсив оформляется //скошенными же линиями//;
  * ##""--зачёркивание--""## и ##""__подчёркивание__""## соответственно;
  * списки выглядят так же, как мы привыкли писать подобные списки в текстовых полях ввода.
Здесь мы сразу отошли от ((http://c2.com/cgi/wiki?TextFormattingExamples классической)) вики-разметки с её "всего 5 апострофов с каждой стороны".

==== Парные символы ====
Как вы заметили, все приведённые выше примеры вака-разметки содержат парные символы. Благодаря этому принципу текст "просто вставленный из какого-нибудь другого редактора" не требует специальной предварительной обработки -- маловероятно, что в нём встретятся таким образом "спаренные" символы.

В разметке есть случаи, когда используются тройные, четверные символы (и даже последовательности из 5-6 подряд идущих символов) -- они используются для выделения заголовков разного уровня. Чем больше символов, тем "глубже" уровень заголовка.

==== Разметка соприкасается с внутренним текстом ====
Не исключено, что вы из тех людей, что всегда пишут тире как "два минуса" (вот так: ##-~-##). Во всяком случае, авторы явно из числа этих людей. И более того, существует великое множество текстов, содержащих двойной минус как в качестве тире, так и в других качествах.

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

Т.е. ##""--вот так--""## будет работать, а если ## ""--"" мы сделаем так--## -- то текст не зачёркнётся.

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


==== Перевод строки -- завершение некоторого фрагмента текста ====
В отличие от, скажем, разметки OpenWiki, перевод строки в "исходном тексте" вака-разметки воспринимается буквально -- как перевод строки (два перевода начнут новый абзац). Таким образом, мы принимаем, что перевод строки -- это завершение некоторого законченного фрагмента текста, например, предложения или даже абзаца.

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

==== "Сломанная" разметка не должна ломать HTML вокруг текста ====
Вышеизложенные принципы позволяют добиться решения одной очень важной задачи -- "защиты" HTML вокруг отформатированного текста от возможных ошибок форматирования. Благодаря правилу "прилипания" мы почти всегда можем определить какая часть разметки является "началом", а какая "концом", а также вставлять сразу оба HTML-тега (или не вставлять ни одного). Для тех правил вака-разметки, которые не имеют столь легко достижимой "парности" должны быть предприняты все усилия, чтобы добиться "герметичности" результата. И, как мы видим, это удалось.

==== Должен быть способ написать в точности то, что я хочу написать ====
Любую разметку нужно уметь "экранировать" -- т.е. делать так, чтобы при разборе правила разметки игнорировались и фрагмент текста проходил через форматирование неизменным. Эта статья -- пример того, когда подобное "экранирование" необходимо.

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

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

Таким образом, исходный синтаксис ссылок ##""[[WikiLink Textual description]]""## обрёл своего двойника ##""((ВикиСсылка Текст на ссылке))""##, которого можно использовать как на английской, так и на русской раскладке. Очень многие правила вики-разметки обладают этим ценным свойством.


=== Правила формирования разметки ===
Применяя эти принципы, мы развивали и совершенствовали изначальный набор правил, внимательно изучая разные вики-движки. Если бы я посмел хвастаться, я бы сказал, что итоговая вака-разметка вобрала в себя всё самое лучшее из разных правил разметки, оставшись стройной и простой. Хотя, чёрт возьми! В итоге нашей работы вака-разметка вобрала в себя всё самое лучшее из разных правил разметки, оставшись стройной и простой.

В этой главе бегло рассказывается о том, как мы пришли к наиболее ключевым правилам разметки.

==== Однострочная разметка ====
Однострочной разметкой стали все те правила, которые использовали символы, часто употребляемые в "простых текстах", и которые касались какого-то "местного" оформления текста:
  * **жирный**, //курсив//, __подчёркивание__
  * ++мелкий++ и ##моноширинный## текст
  * заголовки (просто не имеющие смысла при разбиении на строки)
  * ссылки (тексту которых тоже лучше оставаться "короткими")
  * возведение в ^^степень^^ и vvиндексыvv (которые работают лишь в пределах одного слова)


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

<[Это, например, --зачёркивание.
Или-- цитирование, которое захватывает весь абзац.]>

==== Экранирование разметки ====
Экранирование реализуется двумя способами:
  * экранирование блока с помощью "парных символов" ##~""##;
  * escaping (введение специального символа перед экранируемой последовательностью) с помощью символа ##~~## (тильда).
Первый способ позволяет сравнительно легко "запретить" разметку большого куска текста, а второй удобно применять, когда нужно экранировать лишь одно-два слова или даже один "парный символ". Кроме того, экранирование тильдой позволяет нам отображать и парные двойные кавычки, как это сделано в примере выше.

Если вы откроете ((!/source исходный текст)) статьи, то обнаружите, что экранирование разметки встречается там очень часто -- иначе мы бы не смогли привести ни одного примера разметки в своём непреобразованном виде.

==== Ссылки и изображения ====
Вака-разметка, обнаружив в тексте URL, автоматически превращает его в ссылку. Если понятно, что URL указывает на "картинку" (например, заканчивается на ##.jpg## или ##.gif##) -- в отформатированный текст вставляется изображение с помощью тега ##<img>##. Это удобно, потому что позволяет, не особенно задумываясь, вставлять ссылки из буфера обмена, получая вполне качественный результат.

Для установки ссылки с подписью есть два тега, имеющие несколько вариантов использования:
  * ##""((URL Текстовое описание))""##
  * ##""[[URL Текстовое описание]]""## -- то же, только менее удобно
  * ##""((Вики Ссылка C Пробелами == Текстовое описание))""## -- позволяет вставлять пробелы в "левую часть" вики-ссылки (так же работает и на квадратных скобках)

((/Doc/Русский/ВикиИмя Концепция вики-ссылок)) позволяет вставлять ссылки "внутри сайта" более просто и вака-разметка это тоже учитывает. Все ссылки, которые не являются "внутренними", сразу оформляются как "внешние", то же происходит и с email-адресами.

Подписи к картинкам расставляются очень похоже на подписи к ссылкам:
  * ##""((picture.jpg Подпись))""## -- способ задания title картинки
  * ##""((URL small_picture.jpg))""## -- способ поставить ссылку с картинки


==== Списковые структуры ====
Как наиболее естественно для человека писать списки, нумерованные и ненумерованные, а так же вложенные?
#||
||%%(php)**Наверное, как-то так:**
  * элемент списка-1
  * элемент списка-2
  * Подсписок
    * элемент подсписка-1
    * элемент подсписка-2
  * продолжение списка
  
  1. Нумерованный список раз
  2. Второй элемент
    1. так же и с вложенным
    6. нумерация может и сбиться
%%|

**Что хочется получить:**
  * элемент списка-1
  * элемент списка-2
  * Подсписок
    * элемент подсписка-1
    * элемент подсписка-2
  * продолжение списка
  
  1. Нумерованный список раз
  2. Второй элемент
    1. так же и с вложенным
    6. нумерация может и сбиться
|| ||#
Именно так и устроены правила разметки списков в вака-разметке. Пример хорошо иллюстрирует, почему все буллиты списка изначально сдвинуты вправо на пару символов -- это позволяет избежать путаницы с **полужирным** текстом.

Отступ выбран равным в два символа исходя из принципа "парных символов", которые в обычных текстах почти не встречаются. Некоторые другие вики-форматы используют пять-шесть пробелов -- можно представить себе, как будет выглядеть третий уровень вложенности в ##<textarea>##!

Оригинальная разметка с c2.com использует символ табуляции, что представляется нам очень непродуманным: в большинстве интерфейсов Tab выполняет функции навигации, а в некоторых браузерах символ табуляции ввести в поле ввода вообще невозможно.

Нумерация в нумерованных списках проставляется автоматически, что позволяет спокойно удалять пункты, добавлять новые и переносить их в иерархии. Если вам нужен нумерованный список, начинающийся с тройки, начните его ##1.#3 Вот так##.
  1.#3 Именно так.

==== Разметка таблиц ====
Таблицы -- одно из самых больных мест любой разметки. Наилучшим решением оказался набор правил, разметка которого имитирует вертикальные линии сетки таблицы. Это легче, чем рисовать дефисами, плюсами и вертикальными линиями всю сетку, и одновременно даёт вполне читаемую в "исходном тексте" таблицу. Подробнее о разметке таблиц можно прочитать в ((/Doc/Русский/WackoСинтаксис синтаксисе вака-разметки)). Там же есть и примеры.

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

=== Развитие разметки ===
Во-первых, выше рассмотрены далеко не все правила вака-разметки, а лишь самые основные. Если вам чего-то не хватает -- посмотрите сперва ((/Doc/Русский/WackoСинтаксис более полную документацию)). Если же становится ясно, что существующих правил не хватает -- разметку стоит расширять. Так появилось большинство правил нашей разметки.

==== Когда стоит изменять существующую разметку? ====
Никогда.

Именно так, если речь идёт не о введении новых правил, а о изменении существующих. Изменение поведения разметки, которое кажется полезным вам, может существенно помешать остальным людям, привыкшим работать с такой разметкой. Представьте, если бы на некоторых сайтах ##""<b>""## стало работать как ##""<a>""## и наоборот.

Конечно, если в рамках вашего конкретного проекта какое-то правило существенно мешает -- тогда можно подумать о его замене. Заменяя/удаляя правило, задумайтесь о том, как это воспримут все те, кто привыкли к стандартной вака-разметке!

==== Когда стоит вводить новые сущности разметки? ====
Как можно реже.

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

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

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

=== Сложные преобразования и сервис-функции ===
Идея вака-разметки, заимствованная из ~WakkaWiki и расширенная авторами, предусматривает два способа существенного расширения возможностей разметки и внедрения в документы разной сложной функциональности.

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

==== Концепция форматтеров-хайлайтеров (highlighters) ====
**Highlighters** -- это концепция, позволяющая разработчику реализовать сложную логику преобразования какого-то блока текста, а пользователю -- легко передать этот блок текста на оформление.

В теле вака-разметки использование хайлайтера выглядит так ##""%%(html)<div class="test">testdiv</div>...%%""## -- т.е. используется "парный символ" ##""%%""## с указанием в круглых скобках, какой функции-хайлайтеру передать то, что внутри.

Разработчик же пишет эти самые функции, принимающие текстовую переменную, совершающие с ней какие-то преобразования и затем возвращающие результат.

Как правило, этот синтаксис используется для разнообразной "расцветки" текста -- для подсветки синтаксиса, оформления ICQ-логов и email, вставки каких-то произвольных блоков текста.

Эта концепция -- способ легко расширить разметку, при этом:
  * не задействуя дополнительных "парных символов";
  * не разбираясь в деталях работы вака-форматтера.

==== Концепция акшнов-действий (actions) ====
**Actions** -- это концепция, позволяющая разработчику реализовать какую-то сложную функциональность (возможно, даже требующую диалога с пользователем), а пользователю -- легко обеспечить в нужном месте документа доступ к этой функциональности.

В теле вака-разметки использование "действия" выглядит так ##""{{changes page="/Dev"}}""## -- используется "парный символ" ##""{{""## с указанием имени "действия" и дополнительных параметров.

Разработчик пишет эти функции точно так же, как он пишет и "хайлайтеры".

Именно через "действия" в WackoWiki реализована значительная часть функциональности по работе с документами (построение каталога, списков последних изменений/комментариев, поиск).

Эта концепция -- способ "встроить" в документ какую-то сложную функциональность, при этом так же не влезая в детали работы вака-форматтера.

==== Interwiki -- модификация разметки ссылок ====
Существует также способ расширить синтаксис разметки ссылок, введя в него дополнительные правила вида ##""((repository:address))""## или ##""((repository:address Текст на ссылке))""##. Адрес в таком случае указывается как два фрагмента "хранилище" и "имя в этом хранилище". Например, для ((http://livejournal.com LiveJournal)) адреса будут выглядеть как-то так: ##""((lj:mendokusee))""##, а для ссылки на перевод английского слова можно будет писать ##""((lingvo:fascinating))""##.

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

Тем не менее, есть и другие способы реализации аналогичной модификации. На разных сайтах используются следующие форматы разметки:
  * ##""[[ljuser romochka]]""## ([[http://ilyabirman.ru/meanwhile/wikihelp источник]])
  * ##""[[xpointUser280 Владимир Палант]]""## ([[http://xpoint.ru/help/formatting.xhtml источник]])
  * ##""[[php ereg_replace]]""## ссылка на документацию ([[http://xpoint.ru/help/formatting.xhtml источник]])

Вариант interwiki (ссылки через двоеточие) кажется нам более правильным хотя бы потому, что используется во множестве систем и является стандартом де-факто. Кроме того interwiki не вызывает конфликта с обычной разметкой ##""[[Link Description]]""##.

=== Технические детали ===
Эта статья -- не то место, где вы сможете в деталях разобраться, как работает ((/Dev/Projects/WackoFormatter вака-форматтер)), однако, некоторые основные моменты стоит назвать.

Во-первых, сам по себе форматтер построен на "регулярных выражениях" (а именно Perl Compatible Regular Expressions) и работает по принципу "рекурсивного разбора". Это означает, что он старается разбить текст на "самые крупные" фрагменты разметки, а потом использует себя же для разбора внутри них. Это, в свою очередь, значит, что нельзя вкладывать одинаковые правила разметки: например, вот так -- ##""**пример **вложенной** разметки**""## работать не будет. Но, согласитесь, это и не нужно.

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

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

Если вам интересны более глубокие аспекты функционирования форматтера -- добро пожаловать в ((/Dev/Projects/WackoFormatter код форматтера)).

=== Вместо заключения ===
Эта статья была написана для того, чтобы рассказать о том, как и почему были придуманы правила вака-разметки, откуда взялись те или иные "парные символы" и почему нам хочется надеяться на то, что новые проекты, использующие в качестве формата редактирования вака-разметку, будут следовать тем принципам, что лежат в её основе.

Если у вас возникли вопросы -- не стесняйтесь задавать их в комментариях или лично авторам статьи.

С уважением, ((/Org/Team команда WackoWiki)) и авторы статьи:
  * ((user:KusoMendokusee Кусо Мендокуси));
  * ((user:RomanIvanov Роман Иванов)).

=== Ссылки ===
  1. ((http://wackowiki.org The WackoWiki Project))
  2. ((/Dev/Projects/WackoFormatter Форматтер)) для описываемой разметки
  3. ((/Dev/Projects/WikiEdit Визуальный редактор)) для описываемой разметки
  4. ((https://web.archive.org/web/20050211022800/http://www.wakkawiki.de/WakkaWiki WakkaWiki)) -- исторические корни WackoWiki
  5. ((https://web.archive.org/web/20060202001402/http://openwiki.com/ OpenWiki)) -- ещё одни исторические корни вака-разметки
  6. ((/Doc/Русский/WikiКонцепции Описание вики-концепций))
  7. ((/Doc/Русский/WackoСинтаксис Синтаксис вака-разметки))
  8. ((https://c2.com/cgi/wiki?TextFormattingExamples Примеры классической разметки)) на c2.com
  9. ((/Doc/Русский/ВикиИмя Что такое ВикиИмя)) -- концепция вики-ссылок