Textoole

Textoole это мощный язык разметки, немного похож на Markdown и Textile, некоторые идеи заимствованы из MarkedText.

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

В Textoole разметке нельзя использовать HTML, но при этом этом есть блоки с более коротким синтаксисом, что позволяет использовать семантическую вёрстку, а на выходе получить полностью безопасный HTML-код.

Основную вёрстку текста можно осуществлять из русской раскладки, не переключаясь в английскую, это сразу же заметите, если работали с Markdown или Wiki-разметкой.

Более правильная обработка переносов строк, списки и выделение речи не будут склеиваться в одну строку. Есть встроенный настраиваемый типограф, умеющий обрабатывать вложенные кавычки.

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

  1. Перенос строк и разделитель
  2. Заголовки и оглавление
  3. Строчная разметка
  4. Ссылки
  5. Картинки
  6. Якоря
  7. Фигуры
  8. Списки
  9. Цитаты
  10. Таблицы
  11. Код
  12. Формулы
  13. Классы
  14. Блоки
  15. Ссылки на источники
  16. Лицензия


Перенос строк и разделитель

Принудительный перенос строки <br> осуществляется вставкой пробела в начале текстовой строки.

Также принудительно завершаются вставкой <br> строки, начинающиеся с - (и более длинных и ), цифра или буква с закрывающей скобкой 1), знак больше >, то есть, такие строки не будут склеены.

html:
- Салют!
- Привет
всем
 моим друзьям!
> Ответ
1) Во-первых

<p>&ndash; Салют!<br>
&ndash; Привет всем<br>
моим друзьям!<br>
&gt; Ответ<br>
1) Во-первых</p>

Текст внутри блока %% %% выводится без обработки форматирования Textoole, но с обработкой типографа, переносы строк заменяются на <br>. Без всякой обработки можно вставить текст в блок {%% text}.

html:
%%//текст со слешами//%%
//текст со слешами//

При необходимости скрыть часть текста, можно обернуть его в комментарий {-- text --}. В отличие от HTML-комментариев, такие комментарии могут быть вложенными, и такой комментарий не попадает в итоговый HTML-код. Блоки ещё удобнее убирать, как бы зачеркнув их содержимое двойными минусами.

nohighlight:
Какой-то текст{-- со скрытым комментарием--}.
{--.row
{--.col-6 Колонка 1}
{.col-6 Колонка 2--}
{.col-6 Новая колонка 1}
{.col-6 Новая колонка 2}
--}

Разделитель <hr> вставляется тремя звёздочками ***, с обрамлением в виде пустых строк сверху и снизу.

html:

***

<hr>


Заголовки и оглавление

Строка с загловком начинается с символа =, количество символов указывают уровень заголовка (1-6), от текста отделяется пробелом.

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

Заголовок первого уровня <h1> в некоторых случаях будет запрещено использовать, например, если Textoole используется там, где уже есть такой заголовок, поэтому этот блок использован для <figcaption>, для создания блоков <figure> с подписью. Но если этот заголовок разрешён, то при выделении такого блока пустыми строками, он будет являться заголовком.

html:
= Заголовок

== Подзаголовок
=== Уровень 3
==== Уровень 4
===== Уровень 5
====== Уровень 6

<h1>Заголовок</h1>
<h2>Подзаголовок</h2>
<h3>Уровень 3</h3>
<h4>Уровень 4</h4>
<h5>Уровень 5</h5>
<h6>Уровень 6</h6>

Оглавление документа вставляется следущими наборами символов, обрамлённые пустыми строками, нумерованный через +==, маркированный через *==. Количество знаков равно показывает, с какого уровня создавать оглавление, при встрече заголовка старшего уровня, создание оглавления будет остановлено.

html:

*==

== Глава 1
...
== Глава 2
...
=== Глава 2.1

<ul>
  <li><a href="#ch-1">Глава 1</a></li>
  <li><a href="#ch-2">Глава 2</a></li>
  <ul>
    <li><a href="#ch-2-1">Глава 2.1</a></li>
  </ul>
</ul>
...
<a name="ch-1"></a><h2>Глава 1</h2>
...
<a name="ch-2"></a><h2>Глава 2</h2>
...
<a name="ch-2-1"></a><h3>Глава 2.1</h3>


Строчная разметка

html:
**жирный** //наклонный// --зачёркнутый-- ++подчёркнутый++
**strong** //emphasis// --delete-- ++insert++
<strong></strong> <em></em> <del></del> <ins></ins>

^^верх.индекс^^ __нижн.индекс__ !!маркировка!! ~~маленький~~
^^sup^^ __sub__ !!mark!! ~~small~~
<sup></sup> <sub></sub> <mark></mark> <small></small>

Остальные теги семантической разметки можно использовать в виде {tag text} или {tag text src|href}.

nohighlight:
{audio title src} {video title src}
{a text href}
{img text src}
{span text} {kbd text}
10{sup 2} 2{sub 1}
{br} {hr}
{i.fa-icon}


Ссылки

Ссылки обрамляются двойными скобками, сначала идёт текст ссылки, после последнего пробела сама ссылка, либо ссылка без текста.

html:
((Ссылка на Github https://github.com/))
<a href="https://github.com/">Ссылка на Github</a>

Пример ссылки без текста:

html:
((https://github.com/ibnteo/))
<a href="https://github.com/ibnteo/">github.com/ibnteo/</a>

((https://github.com/))
<a href="https://github.com/">github.com</a>

Адрес электронной почты автоматически отмечается mailto: протоколом.

html:
((ibnteo@gmail.com))
<a href="mailto:ibnteo@gmail.com">ibnteo@gmail.com</a>

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

html:
(((ссылка link)))
(<a href="link">ссылка</a>)

(((ссылка) link))
<a href="link">(ссылка)</a>


Картинки

Картинки обрамляются двойными знаками меньше и больше, аналогично ссылкам может быть текст описания, который будет размещён в атрибуте alt.

html:
<<Рисунок 1 img1.png>>
<img src="img1.png" alt="Рисунок 1">

Картинку можно вставлять внутрь ссылки вместо текста, при использовании скрипта для просмотра картинок, дополнительное описание можно разместить в атрибуте title:

html:
((<<Рис. 1 thumb.png>> title{Подпись к большой картинке} big.jpg))
<a href="big.jpg" title="Подпись к большой картинке"><img src="thumb.png" alt="Рис. 1"></a>

Картинки в начале строки с текстом будут автоматически помечаться классами .float-left.mr-1, в середине текста .mx-1, а в конце текста .float-right.ml-1.

html:
<<img1.png>> текст <<img2.png>> текст <<img3.png>>

<img src="img1.png" class="float-left mr-1">
текст
<img src="img2.png" class="mx-1">
текст
<img src="img2.png" class="float-right ml-1">


Якоря

При наличии ссылки вида #aname и наличии элемента с указанным id="aname", будет создана ссылка для якоря <a name="aname"></a> перед элементом с указанным id.

html:
((Рисунок 1 #pic1))
<<#pic1 Рис. 1 pic1.png>>

<a href="#pic1">Рисунок 1</a>
<a name="pic1"></a><img id="pic1" src="pic1.png" alt="Рис. 1">


Фигуры

Строка, начинающаяся с =, приклеенная сверху или снизу любых других блоков, обёртывает блок в <figure>, а сама становится <figcaption>.

html:
<<Чёрная кошка cat.png>>
= Это моя кошка
<figure>
  <img alt="Чёрная кошка" src="cat.png">
  <figcaption>Это моя кошка</figcaption>
</figure>

! Цена
  ! 100
= Таблица цен
<figure>
  <table><tr><td>Цена</td><td>100</td></tr></table>
  <figcaption>Таблица цен</figcaption>
</figure>

"" Цитата
= Автор
<figure>
  <blockquote>Цитата<blockquote>
  <figcaption>Автор</figcaption>
</figure>

Даже просто параграф.
= Подпись
= автора
<figure>
  <p>Даже просто параграф.</p>
  <figcaption>Подпись<br>автора</figcaption>
</figure>

= Таблица значений
! А это замена ""<caption>""
<figure>
  <figcaption>Таблица значений</figcaption>
  <table><tr><td><code>&lt;caption&gt;</code></td></tr></table>
</figure>


Списки

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

html:
* Элемент 1
  * Элемент 1.1
  * Элемент 1.2
* Элемент 2

<ul>
  <li>Элемент 1</li>
  <ul>
    <li>Элемент 1.1</li>
    <li>Элемент 1.2</li>
  </ul>
  <li>Элемент 2</li>
</ul>

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

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

html:
+ Элемент 1
2. Элемент 2
c. Элемент 3

<ol>
  <li>Элемент 1</li>
  <li>Элемент 2</li>
  <li type="a">Элемент 3</li>
</ol>
  1. Элемент 1
  2. Элемент 2
  3. Элемент 3

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

Для размещения других элементов внутри списка, перед ними необходимо указать слеш с пробелом.

html:
* Элемент 1
  * Элемент 1.2
  {.alert-danger Внимание!}
  * Элемент 1.2
  / "" Цитата

<ul>
  <li>Элемент 1</li>
  <ul>
    <li>Элемент 1.1</li>
    <div class="alert alert-danger">Внимание!</div> 
    <li>Элемент 1.2</li>
  </ul>
</ul>
html:
: Список
  Определений

<dl>
  <dt>Список</dt>
  <dd>Определений</dd>
</dl>


Цитаты

Цитаты начинаются с двух кавычек "". Уровни цитирования задаются теми же символами через пробел.

html:
"" Цитата
"" в несколько строк
<blockquote>Цитата<br>в несколько строк</blockquote>

"" "" Ответ
"" Цитата
многострочная

<blockquote>
  <blockquote>Ответ</blockquote>
  Цитата многострочная
</blockquote>


Таблицы

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

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

Несколько восклицательных знаков обозначают количество colspan этой ячейки.

html:
! Строка 1
  ! Ячейка 2
    ! Ячейка 3
! Строка 2
  !! Сразу две ячейки

<table>
  <tr>
    <td>Строка 1</td>
    <td>Ячейка 2</td>
    <td>Ячейка 3</td>
  </tr>
  <tr>
    <td>Строка 1</td>
    <td colspan="2">Сразу две ячейки</td>
  </tr>
</table>

Наличие нескольких потомков узла на одном уровне (братья) указывает на количество rowspan этого родительского узла.

Отсутствующие ячейки будут добавлены автоматически (пустые).

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

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

html:
! Сотни
  ! 100
    ! 200
  ! 300
! Тысячи
  !! 1000
  !! 2000
  // (примерно)

<table>
  <tr>
    <td rowspan="2">Сотни</td>
    <td>100</td>
    <td>200</td>
  </tr>
  <tr>
    <td>300</td>
    <td></td>
  </tr>
  <tr>
    <td rowspan="2">Тысячи</td>
    <td colspan="2">1000</td>
  </tr>
  <tr>
    <td colspan="2"><p>2000</p><p>(примерно)</p></td>
  </tr>
</table>

Также возможно использовать таблицы в блочном синтаксисе, и CSV таблицы:

{table.table
  {tr {th 1}{th 2}{th 3}}
  {tr {td 4}{td 5}{td 6}}
}

:csv ;
1;2;3
4;5;6


Код

Код вставляется в блок, обрамлённый двойными кавычками "", либо апострофами '', либо обратными апострофами ````. Вместо двойных кавычек можно использовать и большее их количество, чтобы было возможно отобразить любой код.

Для выделения удалённых или добавленных строк, нужные строки маркируются -- или ++.

html:
Код внутри текста: "".html <code class="html"></code>"".

Без подсветки кода: ""<code></code>"".

"".cpp
void main() int {
--  return 1;
++  return 1;
}
""
<pre><code class="cpp">
void main() int {
<del>   return 0;</del>
<ins>   return 1;</ins>
}
</pre></code>

"".html
<script>console.log(window);</script>
""
<pre><code class="html">
&lt;script&gt;console.log(window);&lt;/script&gt;
</pre></code>

Без указания класса, используемого для подсветки синтаксиса, форматированный текст выводится без тега <code>, лишь в теге <pre>.

nohighlight:
""
 |\__/,|   (`\
 |_ _  |.--.) )
 ( T   )     /
(((^_(((/(((_/
""

<pre> |\__/,|   (`\
 |_ _  |.--.) )
 ( T   )     /
(((^_(((/(((_/</pre>


Формулы

Формулы в формате Latex вводятся между двойными символами доллара $$, в итоговый текст вставляется картинка с ссылкой на внешний генератор SVG формул.

$$\int\limits_{-\infty}^{\infty}e^{-x^2} \, dx = \sqrt{\pi}$$

<img
  src="//i.upmath.me/svg/%5Cint%5Climits_%7B-%5Cinfty%7D%5E%7B%5Cinfty%7De%5E%7B-x%5E2%7D%20%5C%2C%20dx%20%3D%20%5Csqrt%7B%5Cpi%7D"
  alt="\int\limits_{-\infty}^{\infty}e^{-x^2} \, dx = \sqrt{\pi}"
>

\int\limits_{-\infty}^{\infty}e^{-x^2} \, dx = \sqrt{\pi}


Классы

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

Класс btn-* автоматически добавляет класс btn, поэтому его можно не писать.

html:
((.btn-primary Кнопка на главную страницу /))
<a href="/" class="btn btn-primary">Кнопка на главную страницу</a>

<<.rounded.border Закруглённая картинка в рамке img.jpg>>
<img src="img.jpg" class="rounded border" alt="Закруглённая картинка в рамке">

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

html:
..table-hover
! 100
! 200
<table class="table table-hover">
  <tr><td>100</td></tr>
  <tr><td>200</td></tr>
</table>

..mt-3
{.card-body Карточка с отступом }
<div class="card mt-3">
  <div class="card-body">Карточка с отступом</div>
</div>

Для задания классов во всех вложенных элементах, можно указать их через две точки после класса основного элемента.

html:
..list-inline..list-inline-item
* 1) Элемент 1
* 2) Элемент 2
<ul class="list-inline">
  <li class="list-inline-item">1) Элемент 1</li>
  <li class="list-inline-item">2) Элемент 2</li>
</ul>


Блоки

Блоки <div> создаются через фигурные скобки { }. Если блок идёт внутри текста, то это будет <span>.

Классы card-* автоматически обрамляют весь блок в <div class="card">...</div>, а классы col-* -- в <div class="row">...</div>, поэтому их можно не писать.

Атрибуты вставляются в формате attr{text} в любое место внутри блока, желательно до текста, в картинке и ссылке лучше после текста.

html:
{.card-body
  {.col-4 <<Логотип width{100%} logo.png>>}
  {.col-8 title{Пояснение} Описание}
}

<div class="card">
  <div class="card-body">
    <div class="row">
      <div class="col-4"><img src="logo.png" alt="Логотип" width="100%"></div>
      <div class="col-8" title="Пояснение">Описание</div>
    </div>
  </div>
</div>

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

html:
! {
Многострочные элементы.

Внутри ячейки таблицы.
}
<table>
  <tr>
    <td>
      <p>Многострочные элементы.</p>
      <p>Внутри ячейки таблицы.</p>
    </td>
  </tr>
</table>

+ {
Или внутри списка
}
<ol>
  <li>Или внутри списка</li>
</ol>

"" {
Главная проблема цитат в интернете в том, что люди сразу верят в их подлинность.

.> (c) Ленин
}
<blockquote>
<p>Главная проблема цитат в интернете в том, что люди сразу верят в их подлинность.</p>
<p class="text-right">&copy; Ленин</p>
</blockquote>


Ссылки на источники

Описание Textoole и исходные коды конвертеров: https://github.com/ibnteo/textoole/ (ещё в процессе создания).

Источники информации:

  1. Markdown: Syntax
  2. Textile markup language
  3. MarkedText — маркдаун здорового человека
  4. Texy: легко читаемый синтаксис
  5. txt2tags: ONE source, MULTI targets
  6. Стандартный синтаксис разметки reStructuredText
  7. BLOCKML: A markup language for scientific documents


Лицензия

MIT