markdown в sublime text
Посмотрим как добавить в sublime text функциональность md редактора.
Однозначно существует множество классных инструментов позволяющих работать с форматом markdown, к примеру, десктопный ReText или онлайн сервис dillinger.io, однако я бы хотел иметь один универсальный редактор, и на мой взгляд, лучше всего на эту роль подходит Sublime Text.
Чтобы конвертировать markdown в html на лету, воспользуемся nodejs модулем markmon. Этот модуль поднимает сервер, получает на вход markdown разметку, конвертирует её и выводит в браузер. Для установки нужен штатный nodejs менеджер пакетов npm (установка nodejs и npm).
После установки npm инсталлируем пакет markmon:
npm install -g markmon
Флаг -g означает, что пакет будет установлен как системный (возможно понадобятся права администратора для установки)
Далее необходимо установить sublime text модуль markmon real-time markdown preview. Этот модуль предоставляет мост между sublime text и node js модулем markmon.
По умолчанию markmon использует библиотеку pandoc для конвертации markdown, чего для большинства случаев должно вполне хватать.
Лично у меня возникла небольшая проблема с использованием pandoc:
Видимо у pandoc более строгие требования к синтаксису чем у bitbucket'а. С одной стороны это правильно, и приучает к правильному оформлению, с другой стороны, я хочу видеть конечный результат - как документ будет выглядеть при просмотре репозитория.
Кастомный конвертер markdown
К счастью, авторы markmon не залочили свою программу на один md конвертор, а предоставили возможность указать свой через параметр command, поэтому можно подключить практически любой другой конвертер.
Перепробовав несколько вариантов, я остановился на реализации под ruby от авторов github'а. Для установки потребуется менеджер пакетов ruby - gem.
К сожалению, на прямую подружить его с markmon не удалось, поэтому я набросал простой скрипт:
require 'github/markdown'
puts GitHub::Markdown.render(ARGF.read)
Скрипт читает стандартный ввод (ARGF.read), конвертирует с помощью GH Markdown и печатает готовый html.
Теперь для подключения нужно в настройках st модуля прописать параметр command. Лезем Preferences -> Package Settings -> Markmon -> Settings - User и прописываем настройки:
{
"command" : "ruby <ПУТЬ К СКРИПТУ>/github_md.rb"
}
Останавливаем markmon (ctrl + P -> Markmon exit) и запускаем его заново (ctrl + K, m). Если все сделано верно то наш markdown отобразится в окне браузера:
Кастомное оформление
Согласитесь, вывод в браузере не очень то привлекателен. Для кастомизации предусмотрен параметр stylesheet принимающий путь к css файлу с оформлением. Лично я, как человек ленивый, нашел уже готовый вариант оформления markdown – gist от andyferra.
{
"command" : "ruby <ПУТЬ К СКРИПТУ>/github_md.rb",
"stylesheet" : "<ПУТЬ К СКРИПТУ>/css/github.css"
}
В результате получаем довольно симпатичное превью:
Подсветка синтаксиса
Реализовать подсветку синтаксиса мне удалось далеко не сразу, т.к. все инструменты ruby, которые я пробовал работали медленнее моих ожиданий, поэтому я решил использовать для раскрашивания кода утилиту GNU Source-highlight от Lorenzo Bettini.
GNU Source-highlight представляет собой офигенную (как и всё что сделано в FSF) консольную утилиту принимающую исходник на стандартный ввод (по умолчанию), настройки и формат вывода, и выводящую результат в стандартный вывод.
Для использования этой утилиты из ruby кода хорошо подойдет функция popen — с помощью неё можно запустить команду как внутренний подпроцесс, с возможностью управления его стандартными вводом и выводом.
Перед тем как передавать код в Source-highlight, необходимо получить из md разметки блоки кода и информацию об используемом языке. Регулярное выражение (тест на rebular) дробит текст на четыре группы - открывающие апострофы, язык, текст, закрывающие апострофы. Таким образом получаем такой код:
md = ARGF.read
# processing ``` blocks
md.gsub! /(?<beg>[`]{3})(?:\n\#\!)?(?<lang>\w+)(?<code>((?!^[`]{3})[\s\S])*)(?<ending>[`]{3})/im do
beg, lang, body, ending = $~.captures
# pass body to source-highlight
IO.popen('source-highlight -s' + lang + ' --tab=4', 'r+') do | pipe |
pipe.puts(body.strip)
pipe.close_write
new_body = pipe.read()
if new_body.empty?
body = '<pre>' + body + '</pre>'
else
body = new_body
end
end
# unwrap <tt> tag
body.gsub! /\<tt\>(?!\<\/tt\>)*/, "\1"
body
end
# convert to html with GitHub markdown
puts GitHub::Markdown.render(md)
Посмотрим что у нас получилось:
Вот таким нехитрым способом (лол) можно превратить sublime text в полноценный markdown редактор.
Спасибо за внимание!
Репозиторий с исходниками - здесь.