Разбор исходников Outwiker. Формат хранения заметок

Немного рекламы

Оглавление

Структура дерева заметок

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

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

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

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

Ограничения на имена заметок

На имена заметок накладываются некоторые ограничения. Во-первых, ограничения накладывает файловая система. Если под Linux имя директории не может включать в себя только нулевой символ (\0), а в остальном вы не ограничены, то под Windows вы не можете создать папку (и, соответственно, заметку) с символами >, <, |, ?, *, : и ". Если вы работаете под Linux, то при попытке создать заметку, содержащую в имени один из этих символов, вы получите предупреждение, показанное на следующем рисунке, но создать заметку сможете.

Под Windows вам этого сделать не удастся.

Другое ограничение связано с внутренним устройством OutWiker. Все папки внутри папки с заметками, начинающиеся с символов __ (два символа подчеркивания), программа считает служебными директориями и не отображает в дереве заметок. Например, все прикрепленные файлы содержатся в папке __attach внутри каждой заметки (в случае, если прикрепленные файлы есть). Про хранение вложенных файлов будет сказано ниже.

При работе с исходниками OutWiker, например, при создании плагина папки и файлы явно создавать не нужно, для создания заметок и работы с прикрепленными файлами существуют специальные классы внутри API OutWiker (забегая вперед скажу, что классы, предназначенные для работы со страницами содержатся в файле src/outwiker/core/tree.py).

Также в папке с заметкой может храниться значок, установленный для заметки. Файл со значком может записан в различных графических форматах, но рекомендуется использовать формат png. В этом случае файл со значком должен иметь имя __icon.png. Изображение значка должно иметь размер 16x16 пикселей и может использовать прозрачность. Чтобы внешний вид заметок не зависел от настроек программы OutWiker на различных компьютерах, файлы значков, как и файлы стилей страниц, о чем будет сказано далее, копируются в папку с заметкой.

Стиль страниц хранится в файле __style.html и, если есть такая необходимость, в папке __style могут располагаться дополнительные файлы. Подразумевается, что основные определения стиля хранятся в __style.html, а в папке __style могут находиться рисунки или скрипты на языке JavaScript, необходимые для отображения стиля. Если для страницы устанавливается стиль по умолчанию, то файл __style.html и папка __style просто удаляются.

Формат файла __page.opt

Файл __page.opt является основным файлом в папке заметки, именно он определяет формат страницы, а также различные ее настройки, но этот файл не содержит содержимое страницы, которое видит пользователь (для этого служит файл __page.text), о котором будет сказано ниже.

Файл __page.opt является текстовым и по сути представляет собой ini-файл, хорошо знакомый пользователям Windows. То есть в нем содержатся разделы, обозначенные квадратными скобками, а за названием раздела расположены параметры в формате "имя=значение". Файл должен быть записан в кодировке UTF-8. Ниже приведен пример файла __page.opt, пока не обращайте особого внимания на параметры, мы их рассмотрим ниже.

[General]
type = wiki
tags = html, софт
order = 0
datetime = 2014-04-12 12:46:55.170000
cursorposition = 121
uid = __a07bd7a7-2be3-41f7-a17d-1ec3997ee988

[Tree]
expand = True

[wiki]
md5_hash = cef7664a01cb932d419a203b2e63b568

[Misc]
pageindex = 0

В данном примере содержатся три раздела параметров: General, Tree, wiki и Misc. Количество разделов и настроек внутри них зависит от формата страницы, в этом примере приведены параметры для викистраницы.

Параметры, общие для всех видов страниц

Для начала разберем параметры, общие для всех типов страниц. Начнем с раздела [General].

  • type. Это единственный обязательный параметр среди всех параметров. Именно он определяет тип страницы. На данный момент существуют 4 типа страниц со следующими типами:
    • text - простая текстовая страница.
    • html - страница в формате HTML.
    • wiki - викистраница.
    • search - страница глобального поиска.
  • order. Задает положение заметки в дереве по сравнению с заметками того же уровня. Чем это значение меньше, тем выше располагается заметка в ветви. Если заметки имеют одинаковое значение параметра order или оно отсутствует, то такие заметки сортируются по алфавиту.
  • tags. Этот параметр хранит список меток, которые были применены к странице. Метки перечисляются через запятую (после запятой можно ставить пробел).
  • datetime. Дата и время последнего изменения страницы. Дата и время записывается в формате вида "m-H:S.%f". За расшифровкой этих символов можете обратиться к документации Python. Для наглядности приведу пример значения этого параметра: "2014-04-15 21:07:43.871098"
  • cursorposition. Положение курсора перед закрытием страницы. Это значение используется для того, чтобы при повторном открытии страницы курсор стоял на том же самом месте, как и в тот момент, когда страница закрывалась. Этот параметр появился в OutWiker 1.8.0.720.
  • uid. Уникальынй идентификатор страницы, который используется для ссылок. В приведенном выше примере идентификатор равен __a07bd7a7-2be3-41f7-a17d-1ec3997ee988, это значит, что ссылка на эту страницу будет выглядить как page://__a07bd7a7-2be3-41f7-a17d-1ec3997ee988. При создании заметки странице не присваивается никакой идентификатор, и этот параметр отсутствует, он появляется, когда идентификатор впервые запрашивается, например, при копировании ссылки на страницу в буфер обмена с помощью пункта меню "Инструменты -> Копировать ссылку на страницу" или одноименного пункта контекстного меню. Этот параметр появился в OutWiker 1.8.0.732.

Из общих параметров остался не рассмотренным еще один, а именно параметр expand из раздела [Tree]. Этот параметр имеет булевый тип и может принимать значения True или False. Этот параметр обозначает, должна ли быть развернута ветвь дерева, начинающаяся с этого узла (заметки). Этот параметр используется для того, чтобы при следующем открытии дерева сохранялась "развернутость" всех его узлов.

Формат простых текстовых заметок

Формат файла __page.opt для простых текстовых заметок не имеет каких-то специфических параметров. При этом параметр type в разделе [General] имеет значение text.

Текст заметки хранится в файле __page.text в том виде, в котором он отображается в окне редактирования.

Классы, предназначенные для работы с текстовой страницей расположены в папке src/outwiker/pages/text/.

Формат страниц в формате HTML

Страница для заметок в формате HTML должна иметь значение параметра type равным html.

Кроме того, этот тип страниц в разделе [General] имеет дополнительный параметр linewrap булевого типа. Если этот параметр имеет значение True, то для данной заметки будет включен режим "Автоматический перенос строк", и для каждого введенного в окне редактора переноса строк будет добавлен тег <br>.

Если этот параметр имеет значение False, тогда теги <br> добавляться не будут, и пользователь сам должен будет писать теги <br> bkb <p> для оформления абзацев. В этом случае введенный код HTML будет интерпретироваться точно так, как он введен. Этот режим может быть удобен, например, для подготовки текста для сайта.

Кроме того, у HTML- и викистраниц есть дополнительный параметр pageindex в разделе [Misc], он определяет какую вкладку на данной странице в последний раз открывал пользователь. Если пользователь завершил работу со страницей на вкладке "HTML", это значение будет равно 0, если на вкладке "Просмотр", то - 1.

При работе с OutWiker пользователь вводит только тело HTML, а именно то, что обычно включается в теги <body>...</body>, после чего программа создает полноценный файл .html, причем есть возможность посмотреть, что же получается в конечном итоге. Результат полного оформления HTML-страницы OutWiker сохраняет в файл __content.html в папке страницы. Этот файл содержит полностью завершенную HTML-страницу со всеми стилями оформления, добавленными переносами строк <br> (если включен режим "Автоматический перенос строк") и т.д.

Например, для HTML-страницы, содержащей фразу "Hello World", и использующей стиль страницы по умолчанию, файл __content.html будет выглядеть следующим образом:

<!DOCTYPE html>
<html>
<head>
        <meta http-equiv='X-UA-Compatible' content='IE=edge' />
        <meta http-equiv='content-type' content='text/html; charset=utf-8'/>

        <style type='text/css'>
                body, div, p, table {
                        font-size:10pt;
                        font-family:Verdana;
                }

                img{border:none}

        </style>

</head>

<body>
Hello world!
</body>
</html>

Классы, предназначенные для работы с HTML-страницей расположены в папке src/outwiker/pages/html/.

Формат викистраниц

Формат хранения викистраниц во многом напоминает страницы в формате HTML, ведь в конечном итоге викинотация преобразуется в тот же самый HTML, который также сохраняется в файл __content.html.

Страница, использующая викинотацию, должна иметь значение параметра type равным wiki. Все выше сказанное относительно файла __content.html относится и к викистраницам с учетом того, что от викинотации к HTML-странице текст проходит более сложный путь, и перенос строк на викистраницах работает по своим правилам (и нет режима "Автоматический перенос строк").

Кроме того, HTML-код викистраниц проходит дополнительную стадию обработки, чтобы сделать полученный HTML-код более читабельным, расставляя дополнительные переносы строк (не путать с тегом <br>) после некоторых тегов (за этот процесс отвечает класс HtmlImprover из файла src/outwiker/core/htmlimprover.py).

Для примера, если викистраница имеет содержимое:

'''Hello World!'''

||border=1
|| Ячейка таблицы 1 || Ячейка таблицы 2 ||
|| Ячейка таблицы 3 || Ячейка таблицы 4 ||

полученный в итоге код HTML будет выглядеть следующим образом:

<!DOCTYPE html>
<html>
<head>
        <meta http-equiv='X-UA-Compatible' content='IE=edge' />
        <meta http-equiv='content-type' content='text/html; charset=utf-8'/>

        <style type='text/css'>
                body, div, p, table {
                        font-size:10pt;
                        font-family:Verdana;
                }

                img{border:none}

        </style>

</head>

<body>
<b>Hello World!</b><br>
<br>
<table border=1>
<tr>
<td align="center">Ячейка таблицы 1</td>
<td align="center">Ячейка таблицы 2</td>
</tr>
<tr>
<td align="center">Ячейка таблицы 3</td>
<td align="center">Ячейка таблицы 4</td>
</tr>
</table>
</body>
</html>

Плагины, такие как, например, Source, могут добавлять свои теги между тегами <head> ... </head>.

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

Для того, чтобы определить, изменилась ли страница, OutWiker рассчитывает контрольную сумму по алгоритму MD5 от строки, полученной склеиванием следующих элементов:

  • Заголовка страницы.
  • Текста страницы.
  • Текущего списка установленных плагинов.
  • Стиля страницы.
  • Списка прикрепленных файлов.
  • Списка дочерних страниц.
  • Некоторых настроек программы, влияющих на сгенерированный код HTML.

Полученный MD5-хэш записывается в параметр md5_hash в разделе [wiki]. Он может выглядеть, например, следующим образом:

[wiki]
md5_hash = dd03106a9e3705caeba5ac75a83ce518

Этот параметр не является обязательным, в случае его отсутствия или, если в нем записана неверная строка, ничего страшного не произойдет, просто данная страница при следующем открытии вкладки "Просмотр" или "HTML" заново создаст файл __content.html, после чего в данный параметр будет записана новая контрольная сумма MD5.

Как и у HTML-страниц, у викистраниц существует параметр pageindex в разделе [Misc], он также определяет, какую вкладку на данной странице в последний раз открывал пользователь. Если пользователь завершил работу со страницей на вкладке "Вики", это значение будет равно 0, если на вкладке "Просмотр", то - 1, если на вкладке "HTML", то - 2.

Классы, предназначенные для работы с викистраницей расположены в папке src/outwiker/pages/wiki/.

Формат страниц глобального поиска

Формат страниц глобального поиска несколько отличается от форматов хранения записей другого типа, поскольку этому типу страниц не нужно хранить большой объем текста. Поэтому в папке страницы поиска содержится обязательный файл __page.opt, но нет файла __page.text.

Файл __page.opt может иметь следующий вид:

[General]
type = search
tags = проверка, test
order = 2
datetime = 2014-04-28 20:56:28.363891

[Search]
phrase = искомая фраза
tags = test, html
strategy = 0
sort = 0

[SearchResults]
page_0 = Пример страницы
page_1 = Тесты
page_2 = Тесты/Проверка
page_3 = Тесты/Проверка/Плагины/source
page_4 = Тесты/Проверка/Абырвалг
page_5 = Тесты/Проверка/Тест
page_6 = HTML5

Для данного типа страниц параметр type из раздела [General] должен быть установлен в значение search. Все остальные параметры из этого раздела аналогичны одноименным параметрам страниц, описанных выше.

Рассмотрим теперь параметры, специфические для страницы глобального поиска. Начнем с раздела [Search], где хранятся параметры, описывающие последний поиск:

  • phrase. Фраза, которая будет искаться по всем страницам дерева.
  • tags. Метки, которые должны быть проставлены на страницах, чтобы они попали в результат поиска. Теги должны быть разделены запятыми, если теги не установлены, значит поиск осуществляется по всем страницам дерева. Не путайте этот параметр с одноименным параметром из раздела [General], страница поиска тоже может быть отмечена метками.
  • strategy определяет поведение поиска в случае выбора двух и более меток. Если параметр strategy равен 0 или в нем записано ошибочное значение, значит для того, чтобы страница попала в результаты поиска, необходимо, чтобы в ней была проставлена хотя бы одна метка из выбранных (хранимых в параметре tags). Если параметр strategy равен 1, значит для того, чтобы страница попала в результаты поиска, необходимо, чтобы в ней была проставлены все выбранные на странице поиска метки.
  • sort определяет способ сортировки найденных результатов. Если параметр sort равен 0 или имеет ошибочное значение, сортировка найденных страниц будет осуществляться по алфавиту по заголовку страницы (поведение по умолчанию). Если параметр sort равен 1, сортировка найденных страниц будет осуществляться по заголовку страницы в обратном порядке. Если параметр sort равен 2, сортировка найденных страниц будет осуществляться по дате последнего изменения страницы, причем страницы с наиболее свежими правками будут располагаться вверху. Если параметр sort равен 3, сортировка найденных страниц будет осуществляться по дате последнего изменения страницы, причем страницы с наиболее свежими правками будут располагаться внизу.

В разделе [SearchResults] сохраняются пути до найденных страниц. Формат хранения результатов поиска видно на приведенном выше примере. Результат сохраняется на тот случай, можно через какое-то время можно было бы вернуться к старому результату поиска без его перезапуска, поскольку эта процедура может быть довольно длительной.

Классы, предназначенные для работы со страницей поиска расположены в папке src/outwiker/pages/search/.

Хранение вложенных файлов

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

Когда новая заметка только была создана, она не имеет папки __attach, она будет создана только при первой необходимости - когда вы прикрепите какой-нибудь файл, нажмете кнопку "Открыть папку с прикрепленными файлами" в окне "Прикрепленные файлы" или выберете пункт меню "Инструменты - Копировать путь до прикрепленных файлов".

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

Одно из применений таких служебных папок описывается в следующем разделе.

Хранение миниатюр

На страницах в формате вики есть возможность создавать уменьшенные копии изображений (миниатюры) с помощью команды %thumb% ... %%. При использовании этой команды могут быть заданы размеры создаваемых миниатюр. Поскольку миниатюры иногда могут оказаться полезными сами по себе, то они отображаются не просто с помощью тега <img> со ссылкой на оригинальный файл и с атрибутами width и height, задающими размер, а миниатюра создается в виде отдельного файла.

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

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

Например, если к викистранице прикреплен файл image.png, а на самой странице содержится текст:

%thumb width=200%Attach:image.png%%

%thumb width=400%Attach:image.png%%

%thumb height=200%Attach:image.png%%

%thumb maxsize=200%Attach:image.png%%

то в папке __attach/__thumb/ будут созданы следующий файлы:

  • th_width_200_image.png
  • th_width_400_image.png
  • th_height_200_image.png
  • th_maxsize_200_image.png

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

К слову, в той же папке __attach/__thumb/ создаются изображения, созданные из формул в формате TeX с помощью mimeTex при использовании викикоманды {$...$}, но поскольку в будущих версиях программы планируется команду {$...$} вынести из самой программы в отдельный плагин, не будем останавливаться на этой особенности. Скажу только, что изображения с формулами хранятся в виде файлов .gif, начинающихся с символов "eqn_", за которыми идет хэш-сумма текстового представления формулы (например, eqn_2dda9e2c1f85e046c867e33f61bf5896.gif)

Заключение

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

Для страницы со стилем по умолчанию и без прикрепленных файлов папка с заметкой будет выглядеть вот так:

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

К оглавлению документации

Немного рекламы

Вы можете подписаться на новости сайта через RSS, Группу Вконтакте или Канал в Telegram.
5 stars

Рейтинг 5.0/5. Всего 8 голос(а, ов)




Подписаться на комментарии
Автор:
Тема:
 Ваш комментарий
 
 
Введите код 838