Пишем программу для создания книг FB2 - страница 4

Шрифт
Интервал

стр.

Читает нам… Но сердце бьется,
Надежду робкую тая -
Авось он, гордый, ошибется!
1857

Структура

Теперь, после лирического отступления, самое интересное: структурирование книги.

Книга может иметь разделение на части, главы, тома и книги, ну мало ли чего придумает автор…

В FB2 структура задается тэгами

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

Программе для обработки структуры понадобится стек (напомню, стек - это список с правилом "последний пришел - первый вышел")


Полученный код FB2, как эталоном, я проверяю программой "FictionBook Editor". Так вот, экзаменатору не нравится такая структура:


// начало примера

H1 | Кальман Миксат. ОСАДА БЕСТЕРЦЕ

S| (История одного чудака)

H2 | ВВЕДЕНИЕ

// конец примера


Т.е. между секциями не должно быть ничего лишнего…

А вот так будет все нормально:


// начало примера

H1 | Кальман Миксат. ОСАДА БЕСТЕРЦЕ

H1 | (История одного чудака)

H2 | ВВЕДЕНИЕ

// конец примера


Итак, когда при обработке списка ListBox1 встречается строка с типом от H1 до H5 вызывается процедура StyleStucture;

// начало кода

procedure StyleStucture;

begin

if CurStyle <> oldStyle then

begin // пока предположим, что предыдущий стиль был не заголовок

if SytleStack.Count = 0 then // если стек пуст

begin // записываем стиль в стек

SytleStack.Add(TObject(CurStyle))

end

else // если в стеке что-то есть

begin // значит надо проверить последний из заголовков

LastStyle:= TmyStyle(SytleStack.Last); // считываем последний стиль

case SubStyle(CurStyle, LastStyle) of // вычисляем разность текущий стиль минус последний

0: OutList.Add('

'); // стили равны, ничего особенного делать не надо

1: SytleStack.Add(TObject(CurStyle)); // новый стиль больше, добавляем его в стек

// предыдущая секция не закончилась, т. к. новая будет в ее входить как матрешка

else // иначе, считаем что разность меньше нуля

begin

OutList.Add('

');

while CurStyle <>LastStyle do

begin

SytleStack.Delete(SytleStack.Count-1); // уменьшаем стек

OutList.Add(''); // завершаем секции до тех пор пока

LastStyle:= TmyStyle(SytleStack.Last); // текущий стиль и стиль в стеке не сравняются.

end;

end;

end;// case

end;

OutList.Add('

'); // начинаем новую секцию

OutList.Add('');</p><p>end;</p><p>OutList.Add('<p>'+s+'</p>'); // записываем заголовок секции</p><p>end; // StyleStucture;</p><p>// конец кода</p><br><p>Пожалуй, это самый тяжелый код в данном манускрипте, но он вроде работает, хотя я вижу в нем по крайней мере две неувязки, но что это, не скажу…</p><br><p>Ну вот с обработкой книги почти закончили, мелкие подробности увидите в исходнике.</p><br><p>Нажимаем пункт меню File - Save as FB2.</p><p>И - ничего не получается. Запланированная шутка. Вылезла надпись "Заполнить поля" и фокус перенаправлен на начальную закладку.</p><p>Напоминаю FB2 - это не только легкоусвояемый (легкоусваиваемый) текст, но и очень нужный и полезный заголовок книги.</p><p>Давайте посмотрим, все таки, что происходит при выборе пункта Save as FB2</p><p>// начало кода</p><p>procedure TForm1.SaveasFB21Click(Sender: TObject);</p><p>begin</p><p>if not BookHaveName then // проверяем, все ли в порядке в заголовке</p><p>begin // если нет, то происходит все то что Вы видели</p><p>PageControl1.ActivePageIndex:= 0;</p><p>ShowMessage('Fill the form.');</p><p>exit;</p><p>end;</p><p>SaveDialog1.FileName:= form1.FB2_file.Text;</p><p>if SaveDialog1.Execute then</p><p>Make_fb2(SaveDialog1.FileName);</p><p>end;</p><p>// конец кода</p><br><p>Посмотрим на процедуру BookHaveName</p><p>// начало кода</p><p>function BookHaveName: boolean;</p><p>begin</p><p>with Form1 do</p><p>result:= (book_title.Text <> '') and</p><p>(FB2_file.Text <> '') and</p><p>(GenresBox.Count > 0);</p><p>end;</p><p>// конец кода</p><p>Ничего особенного в этой функции нет. Единственно из-за чего я ее вытащил, это сказать, что Вы можете и скорее даже будете вынуждены, как-то изменить ее, чтобы контроль заполнения заголовка книги был более разумным.</p><br><p>А я пока вернусь к заполнению заголовка.</p><p>В программе Вы видите три закладки Title-info, Document-info и Publish-info. В формате FB2 есть еще кое-что, но я пока это игнорировал. Предоставляю Вам такую возможность. Код Вам в руки…</p><br><p>Итак Title-info</p><p>Поле Project - само заполнится при открытии текстового файла. При желании, Вы можете изменить, имя сохраняемого fb2 файла.</p></div></div> <!-- Yandex.RTB R-A-2387110-10 --> <div id="yandex_rtb_R-A-2387110-10" class="rsya-rtb-block"><div class="rs-placeholder"></div></div> <script>window.yaContextCb.push(() => { Ya.Context.AdvManager.render({ "blockId": "R-A-2387110-10", "renderTo": "yandex_rtb_R-A-2387110-10" }) }) </script> <div class="show-more show-more_reader text-center mt-4"> <a class="btn btn-info" href="/read/pishem-programmu-dlya-sozdaniya-knig-fb2-yuriy-karpov?page=5" > Читать дальше </a> </div> </section> <hr class="w-100"> <section> <div class="pagination-container"> <nav> <ul class="pagination"> <li class="page-item"> <a class="page-link" href="/book/pishem-programmu-dlya-sozdaniya-knig-fb2-yuriy-karpov#tx">1</a> </li> <li class="page-item"> <a class="page-link" href="/read/pishem-programmu-dlya-sozdaniya-knig-fb2-yuriy-karpov?page=3#tx">3</a> </li> <li class="page-item active"> <span class="page-link">4</span> </li> <li class="page-item"> <a class="page-link" href="/read/pishem-programmu-dlya-sozdaniya-knig-fb2-yuriy-karpov?page=5#tx">5</a> </li> <li class="page-item"> <a class="page-link" href="/read/pishem-programmu-dlya-sozdaniya-knig-fb2-yuriy-karpov?page=6#tx">6</a> </li> <li class="page-item disabled"> <span class="page-link">…</span> </li> </ul> </nav> </div> <div class="text-center"> <form class="form form-inline justify-content-center align-items-center pager-form" action="/read/pishem-programmu-dlya-sozdaniya-knig-fb2-yuriy-karpov#tx"> <label for="reader-pagination-page mt-1"> Перейти на </label> <input id="reader-pagination-page" class="form-control pager-form__page" type="number" name="page" required="required" value="5" min="1" max="16" step="1" > <span class="pager-form__appendix"> стр. </span> <button class="btn btn-info">ОК</button> </form> </div> </section> <hr class="w-100"> </div> <section class="mt-4"> <div class="h2 text-break">Похожие книги </div> <div class="container"> <div class="row"> <div class="col-6 col-sm-6 col-md-3 col-lg-3 book-card "> <div class="text-center"> <a class="card__img-link book-card__img-link" href="/book/angliyskiy-po-metodu-w-cat-yuriy-karpov" > <img class="card__img book-card__img book-img img img-fluid lazyload" width="200" height="300" data-src="/uploads/books/images/6e/6e56ce88d74c256984aea790fd5b364b43649f56.jpg" alt="Английский по методу w_cat" > <div class="lazy__img-spinner" style="width: 200px; height: 300px;" ></div> </a> </div> <div> <div class="book-card__meta"> <div class="text-center"> <a href="/book/angliyskiy-po-metodu-w-cat-yuriy-karpov"><b>Английский по методу w_cat</b></a> </div> <div class="text-center"> <a class="text-dark" href="/author/yuriy-karpov">Юрий Карпов</a> </div> </div> </div> </div> <div class="col-6 col-sm-6 col-md-3 col-lg-3 book-card "> <div class="text-center"> <a class="card__img-link book-card__img-link" href="/book/izvlekaem-arhiv-iz-fb2-yuriy-karpov" > <img class="card__img book-card__img book-img img img-fluid lazyload" width="200" height="300" data-src="/build/no_cover.398201c8.jpg" alt="Извлекаем архив из fb2" > </a> </div> <div> <div class="book-card__meta"> <div class="text-center"> <a href="/book/izvlekaem-arhiv-iz-fb2-yuriy-karpov"><b>Извлекаем архив из fb2</b></a> </div> <div class="text-center"> <a class="text-dark" href="/author/yuriy-karpov">Юрий Карпов</a> </div> </div> </div> </div> <div class="col-6 col-sm-6 col-md-3 col-lg-3 book-card "> <div class="text-center"> <a class="card__img-link book-card__img-link" href="/book/rekursiya-yuriy-karpov" > <img class="card__img book-card__img book-img img img-fluid lazyload" width="200" height="300" data-src="/build/no_cover.398201c8.jpg" alt="Рекурсия" > </a> </div> <div> <div class="book-card__meta"> <div class="text-center"> <a href="/book/rekursiya-yuriy-karpov"><b>Рекурсия</b></a> </div> <div class="text-center"> <a class="text-dark" href="/author/yuriy-karpov">Юрий Карпов</a> </div> </div> </div> </div> <div class="col-6 col-sm-6 col-md-3 col-lg-3 book-card "> <div class="text-center"> <a class="card__img-link book-card__img-link" href="/book/informacionnaya-tehnologiya-process-sozdaniya-dokumentacii-gost" > <img class="card__img book-card__img book-img img img-fluid lazyload" width="200" height="300" data-src="/build/no_cover.398201c8.jpg" alt="Информационная технология. Процесс создания документации пользователя программного средства" > </a> </div> <div> <div class="book-card__meta"> <div class="text-center"> <a href="/book/informacionnaya-tehnologiya-process-sozdaniya-dokumentacii-gost"><b>Информационная технология. Процесс создания документации пользователя программного средства</b></a> </div> <div class="text-center"> <a class="text-dark" href="/author/gost">ГОСТ</a> </div> </div> </div> </div> </div> <div class="row"> <div class="col-6 col-sm-6 col-md-3 col-lg-3 book-card "> <div class="text-center"> <a class="card__img-link book-card__img-link" href="/book/kak-pochistit-skany-knig-i-sdelat-knigu-kpnemo" > <img class="card__img book-card__img book-img img img-fluid lazyload" width="200" height="300" data-src="/uploads/books/images/2b/2b961e71e25136e4c136784d9a862d90061def31.jpg" alt="Как почистить сканы книг и сделать книгу" > <div class="lazy__img-spinner" style="width: 200px; height: 300px;" ></div> </a> </div> <div> <div class="book-card__meta"> <div class="text-center"> <a href="/book/kak-pochistit-skany-knig-i-sdelat-knigu-kpnemo"><b>Как почистить сканы книг и сделать книгу</b></a> </div> <div class="text-center"> <a class="text-dark" href="/author/kpnemo">KpNemo</a> </div> </div> </div> </div> <div class="col-6 col-sm-6 col-md-3 col-lg-3 book-card "> <div class="text-center"> <a class="card__img-link book-card__img-link" href="/book/spravochnik-po-flash-neizvestnyy-avtor" > <img class="card__img book-card__img book-img img img-fluid lazyload" width="200" height="300" data-src="/build/no_cover.398201c8.jpg" alt="Справочник по Flash" > </a> </div> <div> <div class="book-card__meta"> <div class="text-center"> <a href="/book/spravochnik-po-flash-neizvestnyy-avtor"><b>Справочник по Flash</b></a> </div> <div class="text-center"> <a class="text-dark" href="/author/neizvestnyy-avtor">Неизвестный Автор</a> </div> </div> </div> </div> <div class="col-6 col-sm-6 col-md-3 col-lg-3 book-card "> <div class="text-center"> <a class="card__img-link book-card__img-link" href="/book/pyat-urokov-velikogo-magistra-ili-povest-o-tom-kak-petya-viktor-ryabchenko" > <img class="card__img book-card__img book-img img img-fluid lazyload" width="200" height="300" data-src="/uploads/books/images/8a/8ab4fbf36082f9be90c145904c9bdcab58da098c.jpg" alt="Пять уроков Великого Магистра, или повесть о том, как Петя Бочкин изучал программирование" > <div class="lazy__img-spinner" style="width: 200px; height: 300px;" ></div> </a> </div> <div> <div class="book-card__meta"> <div class="text-center"> <a href="/book/pyat-urokov-velikogo-magistra-ili-povest-o-tom-kak-petya-viktor-ryabchenko"><b>Пять уроков Великого Магистра, или повесть о том, как Петя Бочкин изучал программирование</b></a> </div> <div class="text-center"> <a class="text-dark" href="/author/viktor-ryabchenko">Виктор Рябченко</a> </div> </div> </div> </div> </div> </div> </section> </main> </div> <script src="/build/runtime.5332280c.js" defer></script><script src="/build/site.5073c1ee.js" defer></script> <!-- Yandex.Metrika counter --> <script type="text/javascript" > (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date(); for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }} k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://cdn.jsdelivr.net/npm/yandex-metrica-watch/tag.js", "ym"); ym(92416503, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true }); </script> <noscript><div><img src="https://mc.yandex.ru/watch/92416503" style="position:absolute; left:-9999px;" alt="" /></div></noscript> <!-- /Yandex.Metrika counter --> <!-- Google tag (gtag.js) --> <script async src="https://www.googletagmanager.com/gtag/js?id=G-EPPXZH8YVB"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-EPPXZH8YVB'); </script> </div> </body> </html>