Использование Maruku (часть №4)
-
09 октября 2008 00:10
-
Комментарии

Приближается к концу мой “эпос” посвящённый Maruku :)
В этой части, как и обещал, я расскажу о том как добавить свои собственные блочные элементы. Напомню, что про добавление span-элементов я рассказал в прошлом посте.
Начну я как и прежде с шаблона, который вы можете использовать при разработке своих блочных элементов:
StartTag = /^<регулярное выражение для начального тега>/
EndTag = /^<регулярное выражение для конечного тега>/
MaRuKu::In::Markdown::register_block_extension(
:regexp => StartTag,
:handler => lambda { |doc, src, context|
# Пропускаем первую строку с начальным тегом
src.shift_line
# Считываем строки которые находятся внутри блока
lines = []
while src.cur_line && !(src.cur_line =~ EndTag)
lines.push src.shift_line
end
# Пропускаем строку с конечным тегом
src.shift_line
# Здесь находиться ваш код который обрабатывает строки внутри блока
# и возвращает результат в переменной result
context.push result
true
}
)
Если вы читали мою предыдущую статью, то заметили что этот шаблон сильно похож на шаблон для span-элементов. Поэтому я не буду заново рассказывать обо всех аргументах, а лишь упомяну об отличиях.
Мы завели две переменные в которых хранятся регулярные выражения для начального и конечного тега. Как вы понимаете это связано с тем что блок имеет следующий формат:
<начальный тег>
...
<содержимое блока>
...
<конечный тег>
И с помощью этих регулярных выражений мы находим эти теги, а затем “выкусываем” содержимое которое находится между ними и обрабатываем его.
Хорошим тоном думаю будет строить такие регулярные выражения которые будут искать теги начиная с начала строки (я специально указал в шаблоне символ чайки ^) связано это с тем что обработчик не принимает аргумент :chars как было в обработчике для span-тегов, а вместо этого применяет ко всем строкам вашего документа регулярное выражение StartTag чтобы понять содержит ли строка открывающий тег. Думаю понятно что из-за этого могут возникнуть проблемы с производительностью, а символ ^ всего лишь небольшая страховка от этих проблем.
Следующий момент на который надо обратить внимание состоит в том что мы используем метод register_block_extension для регистрации обработчика. Плюс, как я упомянул выше, этот метод содержит на один аргумент меньше. В теле обработчика я привел небольшой фрагмент кода который собирает находящиеся внутри блока строки.
Теоретическая часть закончена, переходим к практике :) Создадим блочный элемент в который можно помещать код на Ruby, а на выходе получать результат выполнения этого кода :)
Вот что у меня получилось:
StartTag = /^!ruby/
EndTag = /^!/
MaRuKu::In::Markdown::register_block_extension(
:regexp => StartTag,
:handler => lambda { |doc, src, context|
# Пропускаем первую строку с начальным тегом
src.shift_line
# Считываем строки которые находятся внутри блока
lines = []
while src.cur_line && !(src.cur_line =~ EndTag)
lines.push src.shift_line
end
# Пропускаем строку с конечным тегом
src.shift_line
code = lines.join("\n")
result = get_result(code)
context.push doc.md_html("<pre><code>#{result}</code></pre>")
true
})
class StdOutCapturer
attr_reader :output
def initialize
@output = ""
end
def write(s)
@output += s
end
end
def get_result(code)
origin_stdout = $stdout
$stdout = StdOutCapturer.new
eval(code)
result = $stdout.output
$stdout = origin_stdout
result
end
И такой вот блок
!ruby
5.times { |i| puts "Hello World #{i}!!!" }
!
конвертируется в следующую разметку
<pre><code>Hello World 0!!!
Hello World 1!!!
Hello World 2!!!
Hello World 3!!!
Hello World 4!!!
</code></pre>
Что ж, я рассказал про все доступные способы расширения Markdown в Maruku. Код правда получился несколько громоздким, если видите способы исправить это - оставляйте комментарии :)
Следующий пост завершит цикл статей о Maruku, в нём я попробую выяснить насколько быстро работает Maruku.
в формате RSS. Присоединяйся!
Добавить новый комментарий
Вы можете использовать следующие BBCode теги в комментариях:
| BBCode тег | Результат |
|---|---|
| [b]Жирный текст[/b] | Жирный текст |
| [i]Курсив[/i] | Курсив |
| [u]Подчёркнутый текст[/u] | Подчёркнутый текст |
| [url]http://example.com[/url] | http://example.com |
| [url=http://example.com]Example[/url] | Example |
|
[code]for message in @messages puts message.name end[/code] |
|
|
[quote] IE6 must die! [/quote] |
IE6 must die! |

