H2LRF: Hromadná konverze HTML
Motivační úvod
Z důvodů uvedených v minulém článku, jako svůj formát pro archivaci knih jsem zvolil HTML, přestože tento formát moje čtečka nepodporuje a já pro ni musím knihy konvertovat. Hned ze začátku bylo jasné, že konverze bude muset probíhat dávkově z příkazové řádky – prostě proto, že mám neustále spuštěný FAR Manager a spuštění commandlajnového programu je v něm otázka dvou stisknutých kláves ([písmeno]
a [ENTER]
), zatímco v grafickém prostředí bych tak rychle ani neotevřel start menu. Cílový formát byl nutně LRF (EPUB ještě nebyl v Sony Readeru podporován a ostatní formáty jsou výrazně horší), což ovšem určilo konverzní utilitu, kterou budu používat – nic jiného než Calibrovské HTML2LRF pro konverzi HTML do LRF z příkazové řádky neznám. Jediný problém byl v tom, že pokud má výstup HTML2LRF za něco stát, vyžaduje tato utilita poměrně hodně parametrů; také jsem rychle narazil na řadu nečekaných omezení tohoto programu. A tak vznikla myšlenka na H2LRF
, jakýsi „frontend“ pro HTML2LRF, který by fungoval z příkazového řádku a ušetřil mě co nejvíce myšlení, pamatování a psaní.
Při analýze, co vlastně chci dělat, vyplynuly následující požadavky:
-
Práce z příkazové řádky. Důvod už byl vysvětlen výše.
-
Podpora pro adresáře a pro hromadnou konverzi. HTML2LRF sám o sobě neumí hromadné konverze, zpracovává vždy jen jeden HTML soubor a veškeré snahy o hromadnost nechává na operačním systému. Což o to, to bych mohl udělat i já a psát něco jako
for /r %i in (*.htm) do html2lrf "%i"
, ale to je docela daleko od zamýšlené „konverze na dvě klávesy“. Navíc, i kdybych to zjednodušil dávkovým souborem, pořád by zůstal problém, že i výstupy (LRF soubory) by mohly zachovávat vstupní adresářovou strukturu. -
Všechny údaje o knize uvnitř souboru. Jak už jsem psal výše, pokud chci kvalitní výstup, potřebuji v HTML2LRF použít řadu parametrů: potřebuji vložit název knihy a jméno autora parametry
--title="Název"
a--author="Jméno Příjmení"
, potřebuji nadefinovat vhodný regulární výraz pro detekci kapitol, chci programu říct, před jakými HTML tagy má ukončit stránku a začít novou, atd. atd. Některé z těchto parametrů jsou sice u všech knih stejné nebo aspoň podobné, ale jiné se u každé knihy liší. Bylo by prima, kdyby mohly být zapsané přímo v HTML souboru a můj konverzní frontend si je odtamtud vytáhnul. -
Podpora pro „dědičnost“. Jak jsem napsal v minulém bodě, některé z parametrů HTML2LRF jsou víceméně stálé. Tudíž bych rád použil princip z HTML archívu (jeden společný stylopis, který používají všechny knihy a jen si v něm upravují ty části, které upravit potřebují) i pro parametry HTML2LRF – aby existoval jeden soubor, ve kterém jsou všechny společné definice, a k němu si jednotlivé knížky přidávaly nebo upravovaly parametry podle svých potřeb. A aby to tak šlo rekurzivně až do nekonečna*) – abych jméno autora a jméno autora pro řazení zadal v jednom souboru a ten potom použily všechny knihy tohoto autora (takže až zjistím, že jsem to jméno opsal špatně, budu moci změnit jediný soubor).
*) A to myslím doslova. Program nijak netestuje a ani testovat nebude zacyklení vkládaných souborů…
S těmito body na mysli jsem stvořil první verze programu, ale jak jsem ho začal používat, ukázalo se, že by se hodily i další funkce:
-
Podpora pro více výstupních formátů. Když Sony vypustilo firmware s podporou EPUBu, bylo jasné, že stávající aplikaci zaměřenou na LRF bude třeba doplnit – není asi žádný rozumný důvod, proč vytvářet univerzální archív a neumožnit jeho konverzi do lepších formátů, když se tyto formáty objeví. Znamenalo to ovšem vypořádat se s tím, že Calibre se sice snaží o dodržování společné syntaxe, ale ne vždy se mu to daří – takže třeba definice kapitol je u HTML2EPUB úplně jiná než u HTML2LRF (a co hůř, když zadám LRFovský parametr do EPUBovského konvertoru, tak ten parametr nepřeskočí ale skončí s chybou).
-
Řešení omezení jednotlivých formátů nebo konvertorů. Jakkoliv mám Calibre rád, nemohu zavírat oči nad některými jeho omezeními – například HTML2LRF nepodporovalo (a pokud vím, stále nepodporuje) direktivu
@import
pro vkládaní CSS stylů, což docela likviduje tu moji výchozí myšlenku, že kniha by měla odkazovat pouze svůj vlastní stylopis, ten zase svůj nadřízený stylopis, a tak dál až k nejvyššímu stylopisu. Nebo že HTML2LRF podporuje pokročilé CSS selektory (h3 + p
a podobně) částečně, a to tak, že ve výsledku dopadne text úplně blbě (h3 + p
je interpretováno jako „jakékoliv P následující po jakémkoliv H3“, tj. nenastyluje první odstavec v kapitole ale všechny odstavce ve všech kapitolách.Do toho pak ještě zasáhnou omezení jednotlivých formátů: EPUB například potřebuje mít v CSS nadefinované české fonty, naopak v LRF je velmi důležité je nedefinovat, protože by to zpomalovalo vykreslování stránek a zvětšovalo soubor knihy.
Postupně se objevují další a další nápady. Teď mě třeba velmi láká myšlenka rozšířit podporu ještě na více čtecích zařízení a například pro ně optimalizovat obrázky (k čemu mám mít v EPUBu obrázek 3000×2000 pixelů v plných barvách, když Sony Reader má zobrazitelnou plochu cca 570×760 pixelů v osmi stupních šedi a jeho implementace EPUBu dokonce takhle velký obrázek vůbec nezobrazí). Ale to je zatím hudba budoucnosti.
H2LRF
H2LRF je jméno prográmku, který moje požadavky uvedené výše řeší. Spouští se z příkazové řádky minimálně v podobě h2lrf soubor.htm
, zpracuje vstupní soubor a zavolá na něj HTML2LRF (nebo jiný konvertor) s příslušnými parametry. Nastavení si H2LRF bere z následujících zdrojů:
INI soubor
INI soubor se nachází ve stejném adresáři a pod stejným jménem souboru jako H2LRF sám, jen má příponu .ini
(tj. pokud je H2LRF nahrán do adresáře C:\Utils
pod standardním jménem, načítá inicializační soubor C:\Utils\h2lrf.ini
). Tento soubor je pouze čten (předpokládá se, že obsahuje jednorázová nastavení, která se budou měnit jen zcela výjimečně, pokud vůbec), program sám do něj nic nezapisuje, celá utilita se tedy klidně může nacházet v nějakém chráněném adresáři. INI soubor obsahuje následující sekce:
-
[Config]
Obsahuje jediný parametr
DefaultTarget = výstupní formát
, který programu říká, jakou výstupní formát použít, pokud nebyl na příkazové řádce zadán. -
[výstupní formát]
Těchto sekcí může být v souboru libovolně mnoho, jen je třeba zajistit, aby každá měla jedinečné jméno výstupního formátu. Sekce obsahuje základní nastavení pro vytváření tohoto formátu. Parametry jsou:
-
ExePath = cesta ke konvertoru
– který program provádí konverzi. Obsahem by měla být plná cesta, ale není to nezbytné, pokud se konvertor nachází v PATH. Příkladem je napříkladExePath=D:\Progs\Calibre\html2lrf.exe
. -
Prefix = odpovídající prefix v HTML souboru
– bude vysvětleno dále v popisu, jak H2LRF bere parametry přímo z HTML souboru. -
Extension = přípona výstupního souboru včetně tečky
– tady není co řešit, napíšete sem třeba.lrf
pro soubory LRF nebo.epub
pro soubory EPUB.
-
Příkazový řádek
Co by to bylo za commandlajnovou utilitu, kdyby nepřijímala nastavení z příkazové řádky. H2LRF si z ní bere parametry, které zřejmě budou při každém volání jiné – zejména jméno souboru(ů), který(é) má zpracovat, a několik dalších parametrů řídících zpracování. Parametry jsou zpracovávány postupně zleva doprava, jejich pořadí je v zásadě libovolné (ale efekt parametru se projeví až u souborů zadaných napravo od něj). Většinu parametrů nejspíš buď nepoužijete vůbec, nebo naopak vždycky, takže si je zapíšete do příslušného dávkového souboru. Všechny parametry jsou volitelné, jediná povinnost je uvést aspoň jeden soubor ke zpracování. Možné parametry jsou:
-
-r
zapne rekurzivní procházení adresářů (jinými slovy, zadané soubory se hledají i ve všech podadresářích). -
-r+
zapne rekurzivní procházení adresářů a nalezenou strukturu navíc použije i pro výstupní soubory (které jinak normálně sype všechny do jednoho adresáře). -
-t formát
vybere výstupní formát (viz konfigurační soubor). Pokud není uveden, použije se hodnota zDefaultTarget
. -
-o adresář
určí, do kterého adresáře budou ukládány výstupní soubory. Pokud není uveden, ukládají se do aktuálního pracovního adresáře. -
-e soubor
určí soubor, do kterého budou ukládána chybová hlášení. V tomto případě bude konverze pokračovat i tehdy, když u některého souboru došlo k chybě (například byl použit parametr, který konvertor nezná). Pokud není uveden, vypisují se chybová hlášení normálně na standardní výstup a po první chybě konverze skončí.Pozn.: pokud chcete záznam průběhu do souboru, ale chcete zastavit hned po první chybě, nepoužívejte
-e
ale standardní přesměrování standardního výstupu do souboruh2lrf ... >zaznam.log
. -
soubor nebo maska
určuje, který soubor nebo které soubory se mají konvertovat. Nejběžnější asi bude*.htm*
. Toto je jediný povinný parametr, může být samozřejmě uveden i víc než jednou.
HTML soubor samotný
Ta hlavní funkčnost celého H2LRF je soustředěna v této sekci – jak jste si všimli v předchozích dvou částech, dosud se řešilo jen spouštění samotného H2LRF, ale zatím nepadlo ani slovo o parametrech pro vlastní konvertor. Tak tady se dočkáte.
H2LRF definuje speciální formát standardních HTML tagů <meta>
, kterými řídí svoji práci a celou konverzi. Výhodou je, že tyto speciální tagy budou všemi specifikace-dodržujícími programy ignorovány, takže vstupní HTML soubor můžete úplně normálně používat – dokonce projde i validací (tedy za předpokladu, že jeho zbytek je validní).
K dizpozici jsou dva základní meta parametry:
-
<meta name="prefix@include" content="soubor">
celý tag smaže a na jeho místo vloží obsah souborusoubor
. Tento soubor pochopitelně může obsahovat svoje vlastní <meta …> včetně dalších@include
, ale i jakékoliv HTML tagy povolené v daném kontextu (takže například odkaz na další stylesheet, kterým obejdeme nepodporu HTML2LRF pro@import
ve stylopisech). Jde tak udělat celý řetěz vkládání.Pokud je
soubor
relativní cesta, vztahuje se relativně k souboru, ze kterého byl bezprostředně vložen. Pokud budu ze souboru/knihy/autor/serie/prvni_dil.htm
vkládat soubor../abc.inc
, značí to soubor/knihy/autor/abc.inc
. Pokud v tomto souboru bude dalšímeta @include
odkazující naxyz.inc
, bude vložen soubor/knihy/autor/xyz.inc
, zatímco soubor../klm.inc
by byl/knihy/klm.inc
(v obou případech se hledá relativně k/knihy/autor/abc.inc
). -
<meta name="prefixparametr" content="hodnota">
říká H2LRF, že má konvertoru předat na příkazové řádce textparametr=hodnota
, respektiveparametr
, pokud jehodnota
prázdná. Tohle právě zajistí, že si zdrojový HTML nese s sebou informaci, jak se vlastně má zkonvertovat do cílového formátu.
V obou případech prefix
říká, pro který typ výstupního formátu se má daný META tag vyhodnocovat. Řekněme, že konverze probíhá do formátu EPUB a že v INI souboru je pro formát EPUB stanoven prefix epub:
. H2LRF pak bude zpracovávat pouze ty meta tagy, které mají podobu <meta name="epub:něco" ... >
respektive <meta name="*:něco" ... >
, ostatní bude ignorovat (*:
je tzv. univerzální prefix, který se zpracovává vždy). To vám umožní mít v jednom HTML souboru různé parametry pro různé konverzní utility. Například:
...
<meta name="*:--title" content="Jistě, pane ministře">
(použije se pro všechny konverze)
<meta name="lrf:--header" content="">
(tento parametr existuje pouze v HTML2LRF)
<meta name="epub:@include" content="epub.inc">
(pokud konvertuji do EPUB, vloží se na tomto místě soubor epub.inc
)
...
V atributu content
mají speciální význam následující symboly:
-
%%
bude nahrazen jedním znakem%
-
%e
bude nahrazen prázdným řetězcem (je to proto, že atributcontent
nesmí být v některých verzích HTML prázdný. -
%r
znamená, že celý parametr bude zlikvidován. Je to proto, aby šlo zrušit nějaký parametr z nadřízeného souboru (řekněme, že v hlavním souboru pro všechny knihy zapnete--header
, ale zrovna narazíte na tu jednu knihu, kde header mít nechcete; tak v ní prostě použijete<meta name="lrf:--header" content="%r">
a je hotovo). -
%f
bude nahrazen plnou (absolutní) cestou ke konvertovanému souboru. Hodí se to například tehdy, když máte vedlekniha.htm
uložen ještě souborkniha.htm.jpg
, který chcete použít jako cover:<meta name="*:--cover" content="%f">
(tohle je zápis, který můžete dát do společného souboru pro všechny knihy). -
%d
bude nahrazen diskem, na kterém se nachází konvertovaný soubor. Nenapadá mě praktické použití, je to tu jen pro kompletnost (když už to je v příkazuFOR
, tak to může být i tady). -
%p
bude nahrazen plnou (absolutní) cestou do adresáře, ve kterém se nachází konvertovaný soubor. Může se to hodit v případě, že obrázek z příkladu na %f není uložen v souborukniha.htm.jpg
ale v souborucover.jpg
:<meta name="*:--cover" content="%pcover.jpg">
. -
%n
bude nahrazen pouze jménem konvertovaného souboru bez přípony. Dá se použít ve spolupráci s %p pro odkázání na cover v souborukniha.jpg
:<meta name="*:--cover" content="%p%f.jpg">
. -
%x
bude nahrazen příponou konvertovaného souboru. Platí to samé co pro %d. -
&
bude nahrazen znakem&
(pokud se například kniha jmenuje Sword & Sorcery – jenom samotný znak&
mnoho verzí HTML nepovoluje) -
<
bude nahrazen znakem<
(důvody stejné jako u&
) -
>
bude nahrazen znakem>
(důvody stejné jako u&
) -
"
bude nahrazen znakem"
(důvody stejné jako u&
)
Každopádně doporučuji vyzkoušet si, co H2LRF udělá na dodaném demo souboru (demo/demo.htm
). Zkuste si vyházet některé META tagy nebo naopak nějaké přidat a sledujte, jak se mění příkazový řádek předávaný programu HTML2LRF – a co se stane, když při spouštění H2LRF použijete parametr -t epub
.
verze 0.09
Verze 0.09 zavádí podporu pro Calibre 0.6 a v zásadě i jakéhokoliv jiného konverzního nástroje. Rozdíl je primárně v tom, že Calibre 0.6 mění strukturu příkazové řádky – na začátku musí být vstupní a výstupní soubor a teprve potom parametry konverze.
H2LRF na to reaguje zavedením parametru CommandLine
v h2lrf
, kde je uložen „vzor“ toho, jak má příkazová řádka vypadat. V podstatě to funguje tak, že konvertoru se jako parametr pošle právě tato CommandLine
, ovšem s tím, že některé řetězce v ní budou nahrazeny: Z %%
se stane %
(aby šlo na příkazové řádce zadat procento). Místo %INPUT%
se dosadí jméno vstupního souboru, místo %OUTPUT%
přijde jméno výstupního souboru. Místo %PARAMS%
program vloží seznam parametrů vygenerovaných z META tagů (viz výše).
Výchozím nastavením CommandLine
je %PARAMS% "%INPUT%" --output="%OUTPUT%"
, které odpovídá požadavkům Calibre 0.4 a 0,5; pro použití Calibre 0.6 má mít CommandLine
podobu "%INPUT%" "%OUTPUT%" %PARAMS%
.
Kromě toho došlo k přejmenování ExePath
na Converter
a přibyla možnost umístit jako CommandLine
tak Converter
už do sekce Config
(jako výchozí hodnotu pro všechny konverzní úlohy pro případ, že nejsou předefinovány v nastavení formátu).
Download
Program je určen a testován pro prostředí Windows, ale měl by fungovat na každém operačním systému, pro který lze kompilovat FreePascalem (nemám to ověřeno). Je distribuován jako freeware včetně zdrojového kódu (Delphi/FreePascal), pod podmínkou, že nebude prodáván a bude zachován odkaz na mě jakožto autora. Pokud uděláte nějaké úpravy, ocenil bych, kdybyste mi je poslali.
H2LRF v0.15 (9.3.2012, 479 KB): Podpora pro Unicode.
H2LRF v0.12 (1.8.2009, 165 KB)
H2LRF v0.08 (8.4.2009, 170 KB)
JirkaS: S Calibre (1.34) samotným by to souviset nemělo, stále ho s H2LRF používám a zcela bez problémů. Mám matnou vzpomínku, že jsem stejné varování kdysi měl taky a že byl možná problém v tom, když jsem .css soubory připojoval přímo z jiného .css pomocí
@import
. Teď používám systém, že kromě@import
(užitečný kvůli prohlížení knih v prohlížeči) připojuji nadřazené .css soubory i pomocí normálního<link>
v includovaných (<meta name="@include">
) definičních souborech. Ale nejsem si stoprocentně jistý, že to opravdu řeší tvůj problém.Ahoj, potreboval bych radu – dlouha leta pouzivam tuhle vybornou utilitku. Nedavno jsem ale presel na novy pocitac a tam ksem si nainstaloval i novou Calibre (1.30 64b). Ted jsem zjistil, ze vsechny knizky, ktere pres utilitu udelam maji chybu v CSS. Dival jsem se do logu a bylo tam tohle:
Flattening CSS and remapping font sizes…
Stylesheet ‚c:/Users/xxx/My%20Books/~Cz/common.css‘ referenced by file u’zzzzzz.html‘ not in manifest
Zkousel jsem pustit jen konverzi v Calibre a ta dopadla dobre.
Nemas predstavu, cim by to mohlo byt?
Dik Jirka
Verze 0.15: Tak ještě jeden opravený bug v Unicode verzi – nezpracovávalo se
@include
.Verze 0.14: Chybně se zpracovávaly odkazy dovnitř dokumentů (se symbolem
#
).Verze 0.13: Podpora pro Unicode.
To je v podstatě dobře – to demo bylo psané pro Calibre 0.5, kde skutečně byl parametr
--author
. Ten se ovšem v Calibre 0.6 změnil na--authors
, takže to demo už s novým Calibre bez úprav nefunguje.Jeste jeden problem v demu: demo.html obsahuje meta „author“. Na to mi ebook-convert vyhodil chybu:
ebook-convert.exe: error: ambiguous option: –author (–author-sort, –authors?).
Po uprave hlavicky uz funguje demo dobre.
Ano, dá se spustit i bez znalosti cesty. Utilitka však testuje cestu celou. Možná to není úplně šťastné řešení, ale je to tak.
Mas pravdu, jakmile tam je cela cesta, zacne to fungovat. Nicmene ebook-convert.exe se da spustit i bez znalosti cele cesty – calibre se prida pri instalaci do cesty. Je to lepsi, protoze pokud ho preinstaluju na jine misto, nemusim resit upravu ini filu. Nicmene, zanechme zbytecne kritiky, presto diky, velmi hezka utilitka.
Zjistil jsem, ze pokud upravim INI file tak, ze EPUB je defaultni target, zacne to fungovat. Po prohlidnuti zdrojaku si myslim, ze problem je ve funkci SetTarget, konkretne predpokladam, ze selze volani FileExists(Options.ConverterPath).
Ano, mě to funguje s EPUBem.
A tobě to bude fungovat taky, jen co Converter přepíšeš z
ebook-convert.exe
nac:\calibre\ebook-convert.exe
(nebo něco podobného, podle toho, kde máš nainstalovaný Calibre) – v tom parametru musí být celá cesta ke konvertovacímu programu.Zkousim, zkousim, ale stale dostavam, ze epub is not valid …
Ini file vypada takhle:
[Config]
DefaultTarget=lrf
Converter=ebook-convert.exe
CommandLine=“%INPUT%“ „%OUTPUT%“ %PARAMS%
AbsoluteLocalUrlPrefix=
[LRF]
;Converter=html2lrf.exe
;CommandLine=%PARAMS% „%INPUT%“ –output=“%OUTPUT%“
Prefix=lrf:
Extension=.lrf
[EPUB]
Converter=ebook-convert.exe
;CommandLine=%PARAMS% „%INPUT%“ –output=“%OUTPUT%“
Prefix=epub:
Extension=.epub
Vsimni si, ze LRF nema converter, ale spusti se. Pro Epub je to jedno – at ho tam mam, nebo ne, stjne se nespusti.
Zkusil jsem i nakopirovat html e exaci jak pises a stejne nic:
C:\…\h2lrf>h2lrf -t EPUB .\demo\*.htm
EPUB is not a valid target for conversion. Check your INI file.
C:\…\h2lrf>h2lrf -t EPUB *.htm
EPUB is not a valid target for conversion. Check your INI file.
Jeste jsem zapomel pouzivam WinXP Pro Sp2.
Tobe to funguje s epubem?
Nejpravděpodobnější bude, že máš v sekci
[EPUB]
špatně nastavenou položkuConverter
– zřejmě neukazuje na existující soubor. Pokud používáš Calibre 0.6, měl by tam být stejný ebook-convert.exe jako u LRF.Calibre 0.6.24 zatím vyzkoušené nemám, momentálně jsem u 0.6.13 a ta běží dobře. Nelíbí se mi ale moc to tvoje
demo\*.htm
– pokud používáš výchozí archív bez jakýchkoliv změn, mělo by to být spíš..\demo\*.htm
– ujisti se, že máš tu cestu opravdu dobře (nebo ještě lépe, zkopírujdemo.htm
icommon.inc
přímo k exáči a použij jenh2lrf -t epub *.htm
.Tak jsem tento programek zkousel, bohuzel zatim neuspesne. Zkousim spustit: h2lrf -t epub demo\*.htm (pouzivam demo html, ciste abych vyloucil chybu mezi klavesnici a zidli).
Vysledek je: „epub is not a valid target for conversion. Check your INI file.“
Pritom ini file (v baleni dodavany) obsahuje sekci [EPUB], ktera vypada celkem stejne jako sekce LRF, se kterou to spustit jde.
Dalsi problem je v Calibre. Verze 0.6.24 pokazde crashne na konci jakehokoli pokusu o zapis. Ale to je mozna zpusobene tim, ze se pokousim rozchodit vyvojarske prostredi (a moc mi to nejde).
Chybu bych opravil, ale PAScal jsem nevidel uz fakt hodne let a ani na nej nemam zadny nastroj.
Verze 0.12 – workaround pro chybnou práci s lokálními URL v
ebook-convert
.Verze 0.11 – jenom rychlá aktualizace, opravující jednu chybu a jeden detail.