#!/bin/bash BLOGNAME=Тех-детали RESULT=blog.pdf SRC=articles WKHTMLTOPDF=wkhtmltopdf-amd64 FH_OPTS="-B 27 -T 24 --footer-line --header-line --footer-spacing 10 --header-spacing 10 --header-left $BLOGNAME --header-right [title] --footer-right [page]" EXTRA_OPTS="--image-quality 100" TOC_OPTS="toc --xsl-style-sheet wkhtmltopdf-toc.xsl" OBJECTS="$SRC/boostspirit.html $SRC/c.html $SRC/cint.html $SRC/blog-post.html $SRC/subversion.html $SRC/cd-flac-mp3.html $SRC/boostspirit2.html $SRC/haskell.html $SRC/usb.html $SRC/subversion2.html $SRC/geant4-94-chargeexchangemc-aka-cexmc.html $SRC/f-spot.html $SRC/c2.html $SRC/9.html $SRC/vim-ctags-perl.html $SRC/tcl.html $SRC/haskell2.html $SRC/c-haskell.html $SRC/fedora-15-wicd.html $SRC/cern-root.html $SRC/vim.html $SRC/vim-2.html $SRC/firefox-6-thunderbird-6-fedora-14.html $SRC/ctags-c-c.html $SRC/make.html $SRC/texlive.html $SRC/ngrep.html $SRC/nginx.html $SRC/vim-taghighlight-tagbar.html $SRC/geant4-95.html $SRC/vim-powerline.html $SRC/nginx-i.html $SRC/nginx-ii.html $SRC/vim2.html $SRC/mate-compiz-fedora-17.html $SRC/nginx-myutil.html $SRC/blog-post2.html $SRC/shell-powerline.html $SRC/vim-vimwiki.html $SRC/diff.html $SRC/unicode-linux-fedora-17.html $SRC/powerline-linux.html $SRC/linux.html $SRC/vim-tex-minted.html $SRC/pdf-odp-ppt-latex.html $SRC/vim-xkb-switch-libcall.html $SRC/a-perl-script-for-gathering-blogger.html $SRC/fedora-17-fedora-18.html $SRC/vim3.html $SRC/c11-rvalue.html $SRC/tsung.html $SRC/c3.html $SRC/blog-post3.html" $WKHTMLTOPDF $FH_OPTS $EXTRA_OPTS $TOC_OPTS $OBJECTS $RESULTЯ привожу его здесь только для того, чтобы показать, насколько гибок wkhtmltopdf: его опции перечислены в переменных FH_OPTS, EXTRA_OPTS и TOC_OPTS. Переменная OBJECTS представляет собой список всех файлов из директории articles/.
Результат оказался очень хорошим, предельно близким к оригиналу! После этого я на некоторое время успокоился, но затем меня снова начали терзать сомнения. В самом деле, несмотря на огромное количество опций wkhtmltopdf, отвечающих за внешний вид окончательного PDF документа, на выходе мы имеем примерно то же самое, что было в самом начале - груду неструктурированного мусора, которым невозможно управлять (редактировать, менять внешний вид структурных элементов и т.п.). Нужен другой формат, например tex.
Исследования показали, что есть такая программа pandoc, которая, судя по ее описанию, способна преобразовывать огромное количество форматов из одного в другой. В частности, она умеет выполнять преобразование из HTML в формат tex - то, что нужно! Установив pandoc, и опробовав его на одном из файлов в директории articles/, я увидел, что подсветка синтаксиса исходных кодов пропала. Я рассказывал, как я вставляю подсвеченный код в блог. По сути, он заворачивается внутрь тэгов <pre><tt> .. </tt></pre>, а конкретные цвета подставляет плагин TOhtml редактора vim на основании используемых для данного типа файла синтаксических правил. Кроме того, конвертор TOhtml заменяет пробелы на символы . Выяснилось, что pandoc не умеет подсвечивать составленные таким образом блоки HTML. Однако, он таки может подсвечивать исходный код, если внутри тэгов <pre> .. </pre> удалить все HTML тэги и символы неразрывного пробела, оставив голый исходный код, и снабдить тэг <pre> атрибутом class="тип_файла" или class="brush: тип_файла", где тип_файла - это синтаксический тип файла, например, cpp для C++. Просмотреть список поддерживаемых pandoc синтаксических типов файлов можно, введя команду
pandoc --versionКроме того, вставленные когда-то хедеры и футеры HTML, оказались не нужны. Да и ссылки на изображения не нужны тоже. Поэтому я написал небольшой quick and dirty скрипт process_html.sh, который автоматизирует преобразование содержимого тэгов <pre>, удаляет хедэры и футеры HTML и ссылки на изображения.
#!/bin/bash CLASS= while getopts :l: opt; do case $opt in l) CLASS=$OPTARG ;; \?) echo "Invalid option: -$OPTARG" ;; :) echo "Option -$OPTARG requires an argument."; exit 1 ;; esac done shift $((OPTIND-1)) sed -e 's/\(^.*\)\?\(<\/\?pre>\)/\1\n\2\n/' "$@" | sed -e 's/.*<\/\?html>\|<\/\?body>.*//; /<head>/,/<\/head>/d' \ -e 's/<a href.*\+>\(<img[^>]\+src="\).*\(\/images[^"]\+"[^>]\+>\)/\1..\2/g' \ -e '/^<tt>/,/^<\/tt>/s/<[^>]\+>//g; /^<pre>$/,/^<\/pre>$/s/ / /g' \ -e "s/^<pre>$/<pre class=\"$CLASS\">/"Я поместил этот скрипт в новую поддиректорию tex/, соседнюю с articles/ и images/. Единственная опция -l указывает значение для атрибута class тэга <pre>, то есть синтаксический тип исходных кодов в исходной странице HTML. Очевидно, на одной странице HTML могут находиться исходные коды разных синтаксических типов (например, на языках fortran и C++), поэтому этот скрипт нельзя рассматривать как полностью автоматический: ручная правка полученного результата может оказаться необходимой. Ну а в простейшем случае, достаточно выполнить
./process_html.sh -lcpp ../articles/c.html | pandoc --normalize -f html -o c.texчтобы из файла c.html получить файл c.tex. Файл c.tex не является законченным (standalone) документом tex. Его нужно вставить в шаблон. Я использовал следующий шаблон blog.tex:
\documentclass[12pt]{article} % adjust page geometry \usepackage[a4paper,vmargin={2cm,2cm},hmargin={2cm,2cm}]{geometry} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage{amssymb,amsmath} \usepackage{ifxetex,ifluatex} \usepackage{fixltx2e} % provides \textsubscript % use upquote if available, for straight quotes in verbatim environments \IfFileExists{upquote.sty}{\usepackage{upquote}}{} \ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex \usepackage[utf8]{inputenc} \else % if luatex or xelatex \ifxetex \usepackage{mathspec} \usepackage{xltxtra,xunicode} \usepackage{fontspec} % enables loading of OpenType fonts \usepackage{polyglossia} % support for languages % fonts: \defaultfontfeatures{Scale=MatchLowercase,Mapping=tex-text} \setmainfont{DejaVu Sans} \setsansfont{DejaVu Sans} \setmonofont{DejaVu Sans Mono} % Russian/English document: \usepackage{xecyr} \else \usepackage{fontspec} \fi \defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} \newcommand{\euro}{€} \fi % use microtype if available \IfFileExists{microtype.sty}{\usepackage{microtype}}{} \usepackage{color} \usepackage{xcolor} \usepackage{fancyvrb} \newcommand{\VerbBar}{|} \newcommand{\VERB}{\Verb[commandchars=\\\{\}]} \DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}} % Add ',fontsize=\small' for more characters per line \usepackage{framed} \definecolor{shadecolor}{rgb}{1.0, 1.0, 0.9} \newenvironment{Shaded}{ \begin{shaded} \scriptsize }{\end{shaded}} \newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{{#1}}}} \newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{{#1}}} \newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} \newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} \newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{{#1}}} \newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} \newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{{#1}}} \newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{{#1}}}} \newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{{#1}}} \newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} \newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{{#1}}} \newcommand{\RegionMarkerTok}[1]{{#1}} \newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{{#1}}}} \newcommand{\NormalTok}[1]{{#1}} \usepackage{graphicx} % Redefine \includegraphics so that, unless explicit options are % given, the image width will not exceed the width of the page. % Images get their normal width if they fit onto the page, but % are scaled down if they would overflow the margins. \makeatletter \def\ScaleIfNeeded{% \ifdim\Gin@nat@width>\linewidth \linewidth \else \Gin@nat@width \fi } \makeatother \let\Oldincludegraphics\includegraphics {% \catcode`\@=11\relax% \gdef\includegraphics{\@ifnextchar[{\Oldincludegraphics}{\Oldincludegraphics[width=\ScaleIfNeeded]}}% }% \ifxetex \usepackage[setpagesize=false, % page size defined by xetex unicode=false, % unicode breaks when used with xetex xetex]{hyperref} \else \usepackage[unicode=true]{hyperref} \fi \definecolor{linkcolor}{HTML}{AF8787} \hypersetup{breaklinks=true, bookmarks=true, pdfauthor={}, pdftitle={}, colorlinks=true, citecolor=blue, urlcolor=blue, linkcolor=linkcolor, pdfborder={0 0 0}} \urlstyle{same} % don't use monospace font for urls \setlength{\parindent}{0pt} \setlength{\parskip}{6pt plus 2pt minus 1pt} \setlength{\emergencystretch}{3em} % prevent overfull lines \setcounter{secnumdepth}{0} \ifxetex \newfontfamily\cyrillicfont{DejaVu Sans} \setmainlanguage{russian} \setotherlanguage[variant=american]{english} \fi %\usepackage[raggedright]{titlesec} \author{} \date{} \begin{document} \tableofcontents \include{boostspirit} \include{c} \include{cint} \include{blog-post} \include{subversion} \include{cd-flac-mp3} \include{boostspirit2} \include{9} \include{tsung} \end{document}Здесь много разных сложных объявлений до начала собственно документа. Откуда я их взял? Исходный шаблон можно получить, просто запустив pandoc с опцией -s (или --standalone) на каком-нибудь HTML файле, в котором присутствует исходный код с тэгом <pre> и атрибутом class (без этого не сгенерируется объявление среды Shaded). Конечно же, я изменил получившийся таким способом шаблон, во-первых, удалив содержимое между тэгами \begin{document} и \end{document} и заменив его на объявление \tableofcontents и список файлов в формате tex для вставки в документ (здесь их пока только девять: восемь самых старых постов и один из новых), а во-вторых, добавив определения для генерации кириллических шрифтов xetex из шрифтов DejaVu. Кроме того, я изменил геометрию страницы (второе объявление в скрипте), определил цвет shadecolor, цвет linkcolor (для элементов оглавления) и действия внутри среды Shaded (использовать блок shaded и меньший размер шрифта scriptsize).
Я решил, что исходные коды будут помещены на светлом бежевом фоне shadecolor, а работа внутри интерактивных пользовательских оболочек отмечена темной полосой слева. Во втором случае, из предварительно обработанного программой process_html.sh файла в формате HTML следует в соответствующих местах удалить из тэга <pre> атрибут class, а в файле в формате tex, созданном pandoc, обрамить соответствующие места (они будут ограничиваться тэгами \begin{verbatim} и \end{verbatim}) тэгами
\begin{leftbar} \scriptsize ... \end{leftbar}После описанных мероприятий со всеми девятью файлами и запуска
latexmk -xelatex blog.texя получил вот такой файл blog.pdf. Результат хороший (при том, что Google испортил цвета шрифтов и ухудшил разрешение картинок при вставке в Google Docs, в оригинальном документе PDF все выглядит очень прилично). Даже при таком малоавтоматизированном процессе это было довольно-таки быстро.
Update. Продолжив добавлять отдельные страницы в PDF документ, столкнулся с интересной проблемой. В некоторых моих статьях есть примеры исходного кода на VimL (если кто не знает, так называется скриптовый язык для vim). Так вот, pandoc не умеет подсвечивать VimL. Оказывается, для подсветки языков pandoc использует haskell библиотеку highlighting-kate, которая, как не трудно догадаться, использует определения синтаксиса языков из KDE-шного редактора Kate. Kate поддерживает синтаксис около 200 языков, но не поддерживает VimL! Зафайлил им баг по этому поводу.
Ситуация, однако, оказалась не безвыходной. Я уже писал про латеховский пакет minted, который использует питоновскую библиотеку pygments для подсветки исходного кода. В общем, я решил в случае с исходным кодом на VimL использовать minted. Для этого в файл blog.tex добавляем строку
\usepackage{minted}, а в файле, обработанном process_html.sh, удаляем атрибут class из соответствующего тэга <pre>. Передаем, как и раньше, этот файл на обработку pandoc, открываем полученный файл tex в редакторе, и заменяем соответствующие открывающие и закрывающие тэги \begin{verbatim} и \end{verbatim} на
\begin{Shaded} \begin{minted}{vim} ... \end{minted} \end{Shaded}Пакет minted требует, чтобы компилятор был запущен с опцией --shell-escape, поэтому собираем blog.pdf командой
latexmk -pdf -pdflatex="xelatex --shell-escape %O %S" blog.texВ качестве бонуса имеем полное совпадение стиля подсветки исходного кода VimL со стилем подсветки других синтаксических типов. Это потому, что pandoc для рендеринга подсветки по умолчанию использует стиль той же pygments! (Опция pandoc, отвечающая за стиль подсветки, --highlight-style, может принимать и другие значения, но по умолчанию она равна pygments).
Комментариев нет:
Отправить комментарий