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

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

Мне давно хотелось написать web-приложение на Python, поэтому выбор пал на этот язык. Под катом исходный код и описание, а также ссылка на репозиторий.

Суть этого приложения заключается в следующем: есть директория с md файлами, их удобно писать и удобно использовать помимо этого приложения, если файл называется test.md, то по адресу localhost:8000/test откроется содержимого этого файла в html отображении.

Сначала создадим шаблон отображения для джинджи:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='normalize.css') }}">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='codehilite.css') }}">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
    <table>
        <tr>
            <td valign="top" class="side">
                <h1 class="logo">
                    <a href="/">{{ title }}</a>
                </h1>
                {{ side|safe }}
            </td>
            <td valign="top">
                {{ content|safe }}
            </td>
        </tr>
    </table>
</body>
</html>

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

Теперь необходимо сделать файл с конфигурацией:

# Файл конфигурации
[app_setting]
# Стартовая страница
start_page=start
# Страница бокового меню
side_bar=sidebar
# Директория с md файлами
pages_folder=pages
# Порт для запуска приложения
port=8000
# Текст при ненайденной странице
not_found_text=Запрашиваемая страница не найдена
# Заголовок приложения
main_title=Заметки

И распарсить его:

class ConfigProvider:
    config_file_name = 'config.ini'
    start_page = 'start'
    side_bar = 'sidebar'
    pages_folder = 'pages'
    port = '8080'
    not_found_text = 'Page Not Found'
    main_title = u'Записная книжка'

    def __init__(self):
        # Если существует файл с конфигурацией
        if function.check_found_file(self.config_file_name):
            config = ConfigParser.RawConfigParser()
            config.read(self.config_file_name)
            # Перезапись значений по умолчанию
            self.start_page = config.get('app_setting', 'start_page').decode('utf8')
            self.side_bar = config.get('app_setting', 'side_bar').decode('utf8')
            self.pages_folder = config.get('app_setting', 'pages_folder').decode('utf8')
            self.port = config.getint('app_setting', 'port')
            self.not_found_text = config.get('app_setting', 'not_found_text').decode('utf8')
            self.main_title = config.get('app_setting', 'main_title').decode('utf8')


check_found_file(), используемая в последнем блоке кода показывает существует ли запрашиваемый файл:

def check_found_file(filename):
    """
    Проверка существования файла
    """
    try:
        file = open(filename)
    except IOError as e:
        return False
    else:
        with file:
            return True


Самая главная функция в данном приложении — преобразование markdown в html:

def markdown_to_html(filename):
    """
    Преобразование markdown файла в html код
    """
    f = open(config.pages_folder + '/' + filename + '.md', 'r')
    all_file = ''
    for st in f.readlines():
        all_file += st
    html = markdown.markdown(all_file.decode('utf8'), extensions=['codehilite'])
    return html


Теперь осталось получить содержимое страницы:

# Получение содержимого страницы
def get_page(name):
    # Если страница существует
    if function.check_found_file(config.pages_folder + '/' + name + '.md'):
        page = function.markdown_to_html(name)
    else:
        page = config.not_found_text
    return page


И показать в браузере
@app.route('/')
def hello():
    return render_template(
        'page.html',
        title=config.main_title,
        side=get_page(config.side_bar),
        content=get_page(config.start_page)
    )


@app.route('/<name>')
def page(name):
    return render_template(
        'page.html',
        title=config.main_title,
        side=get_page(config.side_bar),
        content=get_page(name)
    )


if __name__ == '__main__':
    app.run(port=config.port)


Вот и всё. Заметки создаются и редактируются в любимом редакторе, а читаются в браузере.

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

Надеюсь, это приложение поможет разложить свои заметки и записи «по полочкам» и, может быть, познакомиться и подружиться с таким прекрасным языком, как python.

Полезные ссылки


Репозиторий проекта на GitHub
Синтаксис Markdown (официальная документация)
Синтаксис Markdown (статья на русском языке)
Официальный сайт Flask
Поделиться с друзьями
-->

Комментарии (22)


  1. Delphinum
    08.08.2016 11:21
    +1

    DokuWiki + в репу data/pages = довольно удобно как с точки зрения пользователя, так и с точки зрения писателя.


  1. KvanTTT
    08.08.2016 11:51

    Рассматривали https://gist.github.com? Там тоже поддерживается markdown.


    1. s493599
      08.08.2016 12:21

      В связи с передвижениями по стране не всегда есть возможность доступа к интернету, а тут всё локально.


  1. atomheart
    08.08.2016 12:04

    Была аналогичная идея, реализовал на Django, т.к. в случае дальнейшего развития идеи в Flask пришлось бы расширять модулями то, что в Django уже есть из коробки и хорошо работает (работа с БД, пользователи с ролями и очень много чего еще).

    Ну и немного мыслей из разряда «что не хватает»:
    1) Поиск
    2) Версионность (можно реализовать любой VCS-системой)
    3) Веб-редактор (особенно актуально для редактирования таблиц и вставки картинок, т.к. через текст неудобно)


    1. iMrDron
      08.08.2016 12:20

      То же кстати была идея на Django сделать что-то подобное. Но пока руки не дошли. Вы в открытый доступ не вылаживали ваш проект? Дадите ссылочку?


      1. s493599
        08.08.2016 12:20

        Ссылка была в конце статьи, специально для вас
        https://github.com/s493599/PyNotes


        1. s493599
          08.08.2016 12:24

          Извиняюсь, не так понял вопрос, не заметил ветку.


        1. iMrDron
          08.08.2016 12:24

          Спасибо, эту ссылку я видел. Я спрашивал у atomheart.


      1. atomheart
        08.08.2016 13:06
        +2

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

        Для начала я долго искал подходящий веб-редактор, и не нашел того, что мне нужно — а именно работу с таблицами и изображениями в одном флаконе. В итоге я продолжаю редактировать через Sublime, т.к. там есть прекрасный плагин Table Editor, позволяющий удобно работать с таблицами (что для меня критичным оказалось) и подсветка синтаксиса для вставок блоков кода. А для отображения в вебе при необходимости использую тот же Sublime с плагином Markdown Preview, который генерит на выходе вполне себе читаемый и приятный глазу HTML (single-file, т.е. все стили вшиты).

        Поэтому пришел к выводу, что если и делать редактор для веба, то самый прямой путь — конвертировать html (с таблицами и картинками) в markdown, чтобы можно было при желании отредактировать то, что напечатано в markdown синтаксисе. А из этого вывода напрашиваются другие — а зачем тогда в markdown, если есть прекрасный чистый html? и как (и зачем) содержать две версии верстки одного документа? и т.д.

        Все таки чистый markdown — сам по себе ограничен и подходит для сопутствующей документации, а не для полноценного документирования. А т.к. целью у меня было сделать подходящую замену блокноту Mars Notebook (переставшему развиваться и с отсутствующей синхронизацией), то применение wiki на базе markdown себя не оправдывало.

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


        1. Toshiro
          10.08.2016 12:10

          А что, если не секрет, вам нужно такого, чего нет в markdown разметке?


          1. atomheart
            10.08.2016 14:26

            В разметке markdown мне всего хватает. Не хватает удобного инструмента для работы с этой разметкой.


        1. iMrDron
          15.08.2016 13:28

          Я вот тоже как-то болел вопросом где хранить заметки. Думал что буду писать на django своё что-то. Но сейчас вроде определился. Для разной инфы и записей юзаю Evernote. Для ведения проектов trello, для to do google keep, ну и для сниппетов кода и инструкций github gists. В принципе, вполне удобно. Разнобразие сервисов не мешает. Каждый для своего очень хорошо сделан. На этом я и остановился. Свой велосипед на джанго я думаю не смог сделать столь удобным для всех этих вариантов использования.


  1. atomheart
    08.08.2016 13:56

    Позволю еще себе некоторые комментарии к реализации проекта (на правах «imho»):

    1. Метод hello() не нужен, т.к. он полностью дублирует функцию метода page() с пустым параметром. Лучше добавить условие в обработку параметра или задавать сразу значение по-умолчанию из конфига.
    2. Оптимизировав таким образом наше приложение до одной вьюхи, можно с уверенностью избавляться от остальных функций (проверка на наличие файла, конвертация в html и объединяющая их функция получения контента), т.к. все эти функции вызываются ровно один раз и логика в одном фрагменте будет прозрачнее, нежели разбросанная по функциям.
    3. И еще я бы конфиг занес в код приложения (в шапку) и избавился таким образом еще от одной функции разбора конфига.

    В итоге от проекта можно оставить 2 файла — файл приложения с одной вьюхой и параметрами и файл шаблона.


  1. kvaps
    08.08.2016 19:08

    Тоже давно искал то, что вы ищите. Остановил свой выбор на Turtl.
    Тоже OpenSource, умеет markdown, шифрование и selfhosted, имеет стильный дизайн и собственное приложение. Поддерживаются все основные ОС.
    Давно хочу написать о нем, да все руки никак не доходят...


  1. realcnbs
    08.08.2016 19:18

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


  1. EvgeniyKirov
    09.08.2016 03:22

    Оооо, а ещё можно приятных стилей прицепить, и засунуть всё это дело в Electron. Правда, серверную часть в таком случае имеет смысл на JS реализовать.


  1. stopbreath
    09.08.2016 09:23

    Не рассматривалиlektor?


  1. KomandirskieWTF
    09.08.2016 09:23
    +1

    Zim Desktop Wiki


  1. classx
    09.08.2016 09:28

    http://www.mkdocs.org/


  1. vovochka404
    09.08.2016 10:32

    А еще есть raneto
    Вроде ничего так :)


  1. shushu
    13.08.2016 16:45

    В свое время искал облачное решение для заметок с образцами исходных кодов, с поиском и тегами.
    В итоге сделал свой велосипед.
    Js tree не помню,
    mirror code как редактор и хайлайтер кода
    Select2 для тегов
    Bootstrap frontend
    Php backend

    В общем-то результатом доволен, вполне юзабельно. Есть куча вещей для улучшения, но так лень… :)


  1. bosha
    15.08.2016 12:54

    Зачем, когда есть просто куча статических генераторов сайтов написанных на python? Вы по сути сделали тоже самое, только с меньшим количеством возможностей. Я для своих заметок и блога выбрал pelican. Помимо всего прочего, есть дополнения чтобы прикрутить самый различный функционал (мат. формулы, TOC, etc).