Hlavní navigace

LuaTeX: použití základního rozhraní mezi TeXem a skripty

Pavel Tišnovský

Ve druhé části seriálu o programovatelném sázecím systému LuaTeX si na několika demonstračních příkladech ukážeme kooperaci mezi jádrem LuaTeXu a interpretrem skriptovacího jazyka Lua. Taktéž si řekneme, jak lze volat Lua funkci s využitím uživatelsky definovaných příkazů.

Obsah

1. Programovatelný sázecí systém LuaTeX: použití základního rozhraní mezi TeXem a skripty

2. Vytvoření tabulky v dokumentu s využitím programové smyčky

3. Zdrojový kód čtvrtého demonstračního příkladu

4. Volání skriptu uloženého v externím souboru s využitím funkce dofile

5. Zdrojový kód pátého demonstračního příkladu

6. Rozdělení deklarace tabulky na statickou a dynamickou část

7. Zdrojový kód šestého demonstračního příkladu

8. Načítání externích dat (vypočtených v jiném nástroji)

9. Volání funkce deklarované v externím souboru

10. Zdrojový kód sedmého demonstračního příkladu

11. Vytvoření nového příkazu volajícího funkci deklarovanou v jazyku Lua

12. Zdrojový kód osmého demonstračního příkladu

13. Repositář s popsanými demonstračními příklady

14. Odkazy na Internetu

1. Programovatelný sázecí systém LuaTeX: použití základního rozhraní mezi TeXem a skripty

V první části seriálu o sázecím systému LuaTeX jsme se seznámili se základními vlastnostmi tohoto nástroje a taktéž s některými odlišnostmi LuaTeXu od klasického TeXu. Posléze jsme si ukázali nově přidaný příkaz \directlua, který slouží k zajištění základního rozhraní mezi přepsaným a upraveným jádrem TeXu a interpretrem skriptovacího jazyka Lua (tento příkaz mohou používat jak uživatelé plainTeXu, tak i LaTeXu). Taktéž jsme se zmínili o příkazu nazvaném luacode, jenž zjednodušuje volání skriptů. Tento příkaz se používá v LaTeXu resp. přesněji řečeno v LuaLaTeXu stylem \begin\{luacode}\end{luacode} (takže se vlastně jedná o nově definované prostředí, i když s některými omezeními). Dnes si ukážeme některé další možnosti obou zmíněných příkazů, popíšeme si způsob využití externích skriptů a nakonec se seznámíme s tím, jak je možné vhodnou kombinací příkazů \newcommand (popř. \def pro uživatele plainTeXu) a \directlua do LuaTeXu/LuaLaTeXu přidat vlastní příkazy, samozřejmě s možností předání případných parametrů těmto příkazům.

Obrázek 1: Dokument vygenerovaný demonstračním příkladem, s nímž jsme se seznámili minule.

2. Vytvoření tabulky v dokumentu s využitím programové smyčky

Demonstrační příklady popsané minule byly ve skutečnosti velmi jednoduché až primitivní, takže při pohledu na ně možná nemuselo být příliš jasné, v čem vlastně spočívá výhoda kombinace TeXu a skriptovacího jazyka Lua. Podívejme se nyní na poněkud složitější dokument, v němž je umístěna tabulka s druhými mocninami celých čísel od 1 do 16. Celá tabulka je vygenerována skriptem vytvořeným v programovacím jazyce Lua, v němž lze využít funkci nazvanou pow pocházející ze standardní knihovny math [1].

Tabulka je do vstupního bufferu TeXu „vypsána“ funkcí tex.print() (TeX vidí a následně zpracuje už vygenerovanou tabulku), což znamená, že jsme si museli dát pozor na problematický znak zpětného lomítka (o této problematice jsme se taktéž zmiňovali minule). TeXem se zpracuje přibližně tento kód:

\documentclass{article}
\usepackage{luacode}
 
\begin{document}
 
\section*{Mocniny dvou}
 
\subsection*{verze 1}
 
\begin{tabular}{|r|r|}
\hline
$n$ & $2^n$ \\
\hline
1 & 2 \\
2 & 4 \\
3 & 8 \\
4 & 16 \\
5 & 32 \\
6 & 64 \\
7 & 128 \\
8 & 256 \\
9 & 512 \\
10 & 1024 \\
11 & 2048 \\
12 & 4096 \\
13 & 8192 \\
14 & 16384 \\
15 & 32768 \\
16 & 65536 \\
\hline
\end{tabular}
 
\end{document}

V tomto demonstračním příkladu používáme upravené prostředí nazvané luacode* a nikoli pouze luacode. Je tomu tak především z toho důvodu, aby se zamezilo expanzi TeXovských maker ještě předtím, než bude kód v prostředí předán interpretru jazyka Lua.

3. Zdrojový kód čtvrtého demonstračního příkladu

Úplný zdrojový kód v celkovém pořadí již čtvrtého demonstračního příkladu vypadá následovně:

\documentclass{article}
\usepackage{luacode}
 
\begin{document}
 
\section*{Mocniny dvou}
 
\subsection*{verze 1}
 
\begin{luacode*}
tex.print("\\begin{tabular}{|r|r|}\\hline")
tex.print("$n$&$2^n$\\\\")
tex.print("\\hline")
for n = 1,16 do
    tex.print(n .. "&" .. math.pow(2, n))
    tex.print("\\\\")
end
tex.print("\\hline")
tex.print("\\end{tabular}")
\end{luacode*}
 
\end{document}

Základ pro vytvoření obsahu tabulky tvoří čtveřice řádků:

for n = 1,16 do
    tex.print(n .. "&" .. math.pow(2, n))
    tex.print("\\\\")
end

Ve skutečnosti se však do interpretru jazyka Lua předá jediný řádek, v němž jsou příkazy odděleny mezerami (to je v jazyku Lua zcela legitimní):

tex.print("\\begin{tabular}{|r|r|}\\hline") tex.print("$n$&$2^n$\\\\") tex.print("\\hline") for n = 1,16 do tex.print(n .. "&" .. math.pow(2, n)) tex.print("\\\\") end tex.print("\\hline") tex.print("\\end{tabular}")

Obrázek 2: Dokument vygenerovaný předchozím demonstračním příkladem.

4. Volání skriptu uloženého v externím souboru s využitím funkce dofile

Ve standardní knihovně programovacího jazyka Lua existuje funkce nazvaná dofile() [2], která dokáže do aktuálně běžícího skriptu načíst obsah jiného zdrojového souboru a následně ho zpracovat (interpretovat). Tato funkce je samozřejmě, podobně jako i další funkce ze základních knihoven, dostupná i v LuaTeXu, čehož můžeme využít pro oddělení dokumentů od skriptů. Dokument bude uložen v jednom souboru (v tomto příkladu se konkrétně bude jmenovat test5.tex), zatímco skript bude uložen ve druhém souboru nazvaném test5.lua. Načtení a okamžitá interpretace skriptu s programovou smyčkou určenou pro výpočet a vygenerování tabulky druhých mocnin pak v dokumentu zajistí jediný řádek:

\directlua{dofile("test5.lua")}

První předností tohoto způsobu oddělení skriptu od dokumentu je fakt, že nedojde ke spojení všech řádků skriptu před jeho předáním interpretru (to může v některých případech způsobit problémy, například při použití jednořádkových komentářů). Dále je toto oddělení výhodné i z praktického hlediska – programátorské textové editory nebudou mít problém ani se zvýrazněním syntaxe dokumentů (TeX/LaTeX) ani s Lua skripty, zatímco při použití jediného souboru je zvýraznění syntaxe s rozpoznáním rozdílných sekcí problematické (popravdě jsem zatím neviděl editor, který by tuto kombinaci bez problémů podporoval).

5. Zdrojový kód pátého demonstračního příkladu

Obsah souboru (přesněji řečeno dokumentu) test5.tex se díky oddělení skriptu do samostatného souboru zkrátil a současně i zpřehlednil:

\documentclass{article}
\usepackage{luacode}
 
\begin{document}
 
\section*{Mocniny dvou}
 
\subsection*{verze 2}
 
\directlua{dofile("test5.lua")}
 
\end{document}

Poznámka: řádek \usepackage{luacode} je vlastně v tomto demonstračním příkladu zbytečný, neboť příkaz \directlua je přímo zabudován do LuaTeXu (v předchozím příkladu bylo nutné tento řádek použít).

Samotný skript uložený v souboru nazvaném test5.lua potom vypadá následovně:

tex.print("\\begin{tabular}{|r|r|}\\hline")
tex.print("$n$&$2^n$\\\\")
tex.print("\\hline")
for n = 1,16 do
    tex.print(n .. "&" .. math.pow(2, n))
    tex.print("\\\\")
end
tex.print("\\hline")
tex.print("\\end{tabular}")

Zdvojení zpětných lomítek v tomto skriptu stále nalezneme, a to konkrétně z toho důvodu, že zpětné lomítko má v řetězcových literálech jazyka Lua speciální význam; viz též [3].

Obrázek 3: Dokument vygenerovaný předchozím demonstračním příkladem.

6. Rozdělení deklarace tabulky na statickou a dynamickou část

Při pohledu na demonstrační příklad zmíněný v předchozí kapitole jste si pravděpodobně uvědomili, že se v Lua skriptu zbytečně a k tomu navíc velmi pracně vytváří celá tabulka, včetně všech příkazů určených pro definici jejího začátku s deklarací sloupců, prvním řádkem s popisem obou sloupců apod. Celý skript je kvůli tomu dosti nepřehledný, navíc v něm snadno může dojít k chybě, která se těžko hledá (TeX totiž nahlásí chybu v kódu, který „vidí“ v průběhu tokenizace a expanze maker, tedy po zpracování interpretrem, bez přímé vazby na vstupní dokument).

Ovšem kooperace mezi TeXovským dokumentem a Lua skripty je ve skutečnosti velmi variabilní, takže je například možné dokument i k němu příslušející skript upravit takovým způsobem, že se tabulka deklaruje přímo v TeXovském dokumentu (jak je to obvyklé) a pouze ty řádky vytvářené tabulky, které se mají vypočítat, budou vytvářeny skriptem naprogramovaným v jazyku Lua. Příkaz \directlua{dofile(„jméno_skrip­tu.lua“)} se nám tedy posune dovnitř definice celé tabulky a samozřejmě díky tomu dojde ke značnému zjednodušení vlastního skriptu, z něhož je odstraněna většina otrocky napsaných příkazů tex.print(). Další výhoda tohoto přístupu spočívá v tom, že kód uložený ve skriptu bude možné využít na více místech (například tehdy, pokud by se data do tabulky načítala z datového souboru, což je téma, kterému se budeme věnovat o několik odstavců níže).

Poznámka: dejte si pozor na to, že tento způsob není možné použít ve chvíli, kdy se kombinuje prostředí tabular s prostředím luacode či luacode* (viz též http://tex.stackexchange.com/qu­estions/253706/is-it-possible-to-view-the-latex-code-after-lua-expansion-is-made).

7. Zdrojový kód šestého demonstračního příkladu

V dokumentu v pořadí již šestého demonstračního příkladu vidíme deklaraci běžné tabulky s jedním řádkem (nadpisem) a voláním příkazu \directlua:

\documentclass{article}
\usepackage{luacode}
 
\begin{document}
 
\section*{Mocniny dvou}
 
\subsection*{verze 3}
 
\begin{tabular}{|r|r|}
\hline
$n$ & $2^n$ \\
\hline
\directlua{dofile("test6.lua")}
\hline
\end{tabular}
 
\end{document}

Poznámka: řádek \usepackage{luacode} je v tomto demonstračním příkladu opět zbytečný a uváděn je pouze pro úplnost.

Skript se nám zjednoduší na pouhé čtyři řádky, které jsou již mnohem čitelnější, než tomu bylo v příkladu předchozím:

for n = 1,16 do
    tex.print(n .. "&" .. math.pow(2, n))
    tex.print("\\\\")
end

Obrázek 4: Dokument vygenerovaný předchozím demonstračním příkladem.

8. Načítání externích dat (vypočtených v jiném nástroji)

Samozřejmě není nutné, aby skript naprogramovaný v jazyku Lua prováděl pouze nějaké výpočty. Poměrně často se totiž ocitneme v situaci, kdy jsou již data vypočtena či naměřena s využitím jiného externího nástroje a my „pouze“potřebujeme tato data vhodným způsobem vložit do dokumentu. Jedním z poměrně flexibilních způsobů je právě použití skriptu naprogramovaného v jazyku Lua. Předpokládejme pro jednoduchost, že máme následující datový soubor, jehož obsah potřebujeme vložit do tabulky:

42
0
-100
NaN
6502
123456

Pomoci nám může následující skript, který data postupně načte a vloží do tabulky s očíslováním jednotlivých řádků (tento úkol zajišťuje počitadlo lineno):

local infile = io.open("test6.data")
local lineno = 1
 
if not infile then
    print("Chyba pri otevirani souboru")
else
    for line in infile:lines() do
        print(lineno, line)
        tex.print(lineno .. "&" .. line)
        tex.print("\\\\")
        lineno = lineno + 1
    end
    infile:close()
end

Poznámka: pokud není zapotřebí provádět alespoň základní detekci, zda soubor se vstupními daty existuje a je dostupný (čitelný), lze skript ještě více zjednodušit:

local lineno = 1
for line in io.lines("test6.data") do
    print(lineno, line)
    tex.print(lineno .. "&" .. line)
    tex.print("\\\\")
    lineno = lineno + 1
end

Tento skript lze samozřejmě vylepšit a rozšířit. Jedno z možných vylepšení spočívá v detekci speciálních znaků ve vstupním souboru. Tyto znaky, mezi než patří zejména dvojice zpětných lomítek, znak & apod., je nutné například funkcí subs nahradit za odpovídající ekvivalenty, které nebudou při vložení do tabulky způsobovat problémy. Možných rozšíření je celá řada; zmiňme například načítání souborů CSV s detekcí, zda na prvním řádku jsou umístěny popisy sloupců, filtrace dat na základě skriptu, použití externího modulu pro práci se soubory JSON a XML atd.

9. Volání funkce deklarované v externím souboru

V externích souborech s Lua skripty je možné deklarovat různé datové struktury (tj. tabulky fungující jako záznamy, pole i asociativní pole) a taktéž funkce. Pokud například budeme mít v souboru nazvaném test7.lua uloženu deklaraci funkce pro (rekurzivní) výpočet faktoriálu, bude možné takovou funkci nechat zpracovat interpretrem a následně je možné tuto funkci volat:

function factorial(n)
    if n <= 1 then
        return 1
    else
        return n * factorial(n-1)
    end
end

Poznámka: interpret při prvním čtení definice funkce provede základní kontrolu a překlad funkce do bajtkódu (viz též [4] a [5]).

10. Zdrojový kód sedmého demonstračního příkladu

Zkusme nyní použít funkci factorial(), jejíž definice je uložena v samostatném souboru nazvaném test7.lua. Tento soubor je nejdříve nutné načíst do interpretru, což se provede jednoduše:

\directlua{dofile("test7.lua")}

Následně se již funkce může volat, například opět při vytváření tabulky:

\begin{tabular}{|r|r|}
\hline
$n$ & $n!$ \\
\hline
1   & \directlua{tex.print(factorial(1))} \\
10  & \directlua{tex.print(factorial(10))} \\
100 & \directlua{tex.print(factorial(100))} \\
\hline
\end{tabular}

Úplný zdrojový kód dokumentu vypadá takto:

\documentclass{article}
\usepackage{luacode}
 
\directlua{dofile("test7.lua")}
 
\begin{document}
 
\section*{Faktorial}
 
\subsection*{verze 1}
 
\begin{tabular}{|r|r|}
\hline
$n$ & $n!$ \\
\hline
1   & \directlua{tex.print(factorial(1))} \\
10  & \directlua{tex.print(factorial(10))} \\
100 & \directlua{tex.print(factorial(100))} \\
\hline
\end{tabular}
 
\end{document}

Obrázek 5: Dokument vygenerovaný předchozím demonstračním příkladem.

11. Vytvoření nového příkazu volajícího funkci deklarovanou v jazyku Lua

V praxi může být výhodnější nevolat funkci naprogramovanou v jazyku Lua nepřímo:

\directlua{tex.print(factorial(42))}

ale použít namísto toho uživatelský příkaz deklarovaný na úrovni plainTeXu či LaTeXu, tedy takto:

\factorial{1}

Podívejme se nyní, jak je možné tohoto stavu dosáhnout. Nejdříve opět musíme předat interpretru jazyka Lua skript, v němž je deklarována funkce, která se má volat:

\directlua{dofile("test8.lua")}

Následně můžeme s využitím příkazu \newcommand (LaTeX) či \def (TeX) vytvořit nový uživatelský příkaz, který bude interně volat naši funkci, samozřejmě s předáním všech potřebných parametrů:

\newcommand*{\factorial}[1]{%
  \directlua{tex.print(factorial(#1))}%
}

V praxi se tento nový příkaz deklarovaný na úrovni (La)TeXu použije následujícím způsobem:

\begin{tabular}{|r|r|}
\hline
$n$ & $n!$ \\
\hline
1   & \factorial{1} \\
10  & \factorial{10} \\
100 & \factorial{100} \\
\hline
\end{tabular}

což vlastně odpovídá předchozímu kódu:

\begin{tabular}{|r|r|}
\hline
$n$ & $n!$ \\
\hline
1   & \directlua{tex.print(factorial(1))} \\
10  & \directlua{tex.print(factorial(10))} \\
100 & \directlua{tex.print(factorial(100))} \\
\hline
\end{tabular}

První varianta je evidentně mnohem čitelnější než varianta druhá.

12. Zdrojový kód osmého demonstračního příkladu

Nový příkaz deklarovaný na úrovni LaTeXu je použit v osmém demonstračním příkladu, jehož zdrojový kód je zobrazen pod tímto odstavcem:

\documentclass{article}
\usepackage{luacode}
 
\directlua{dofile("test8.lua")}
 
\newcommand*{\factorial}[1]{%
  \directlua{tex.print(factorial(#1))}%
}
 
\begin{document}
 
\section*{Faktorial}
 
\subsection*{verze 2}
 
\begin{tabular}{|r|r|}
\hline
$n$ & $n!$ \\
\hline
1   & \factorial{1} \\
10  & \factorial{10} \\
100 & \factorial{100} \\
\hline
\end{tabular}
 
\end{document}

Obsah souboru test8.lua:

function factorial(n)
    if n <= 1 then
        return 1
    else
        return n * factorial(n-1)
    end
end

Obrázek 6: Dokument vygenerovaný předchozím demonstračním příkladem.

13. Repositář s popsanými demonstračními příklady

Demonstrační příklady popsané v předchozím i v dnešním článku, byly uloženy do veřejného Git repositáře, z něhož si je můžete snadno stáhnout a otestovat:

# Soubor Stručný popis Odkaz
1 test1.tex příkaz \directlua https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test1.tex
2 test1.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test1.pdf
       
3 test2.tex prostředí luacode https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test2.tex
4 test2.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test2.pdf
       
5 test3.tex zpětné lomítko, expanze maker https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test3.tex
6 test3.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test3.pdf
       
7 test4.tex vygenerování tabulky https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test4.tex
8 test4.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test4.pdf
       
9 test5.tex použití funkce dofile() https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test5.tex
10 test5.lua skript pro vygenerování tabulky https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test5.lua
11 test5.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test5.pdf
       
12 test6.tex tvorba tabulek v Lua skriptech https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test6.tex
13 test6.lua zjednodušený skript vygenerování tabulky https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test6.lua
14 test6.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test6.pdf
       
15 test7.tex volání funkce pro výpočet faktoriálu https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test7.tex
16 test7.lua funkce pro výpočet faktoriálu https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test7.lua
17 test7.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test7.pdf
       
18 test8.tex vytvoření nového příkazu factorial https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test8.tex
19 test8.lua funkce pro výpočet faktoriálu https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test8.lua
20 test8.pdf dokument vysázený LuaTeXem https://github.com/tisnik/pre­sentations/blob/master/lu­atex/slides/test8.pdf

14. Odkazy na Internetu

  1. LuaTex
    http://www.luatex.org/
  2. LuaTex: dokumentace
    http://www.luatex.org/docu­mentation.html
  3. LuaTex Wiki
    http://wiki.luatex.org/in­dex.php/Main_Page
  4. LuaTeX (Wikipedia)
    https://en.wikipedia.org/wiki/LuaTeX
  5. Paper o LuaTeXu
    https://www.tug.org/TUGboat/tb28–3/tb90hoekwater-luatex.pdf
  6. TeX (Wikibooks)
    https://en.wikibooks.org/wiki/TeX
  7. LaTeX (Wikibooks)
    https://en.wikibooks.org/wiki/LaTeX
  8. The Latin Modern (LM) Family of Fonts
    http://www.gust.org.pl/projects/e-foundry/latin-modern
  9. Sázecí system TeX
    https://www.phil.muni.cz/~letty/tex/
  10. CSTeX – česká a slovenská podpora TeXu
    http://petr.olsak.net/cstex.html
  11. Proč nerad používám LaTeX
    http://petr.olsak.net/ftp/ol­sak/bulletin/nolatex.pdf
  12. εχTEX
    http://www.extex.org/index.html
  13. PlainTeX (Wikipedia)
    https://cs.wikipedia.org/wi­ki/PlainTeX
  14. What is the difference between \def and \newcommand? (SO)
    http://tex.stackexchange.com/qu­estions/655/what-is-the-difference-between-def-and-newcommand#658
  15. LaTeX/Macros
    https://en.wikibooks.org/wi­ki/LaTeX/Macros
  16. TeX (StackExchange)
    http://tex.stackexchange.com/
Našli jste v článku chybu?

26. 7. 2016 12:08

Taky si myslím, že to někdo aktivně zrcadlil do "správné" orientace, nicméně perexové obrázky vybírá Petr, tak mu do toho moc nekecám :-)

26. 7. 2016 16:59

Ty možnosti jsou především v psaní maker. Kdysi dávno :) jsem psal balík maker pro zobrazení pozic hry Go. Pro LaTeX existovalo několik balíčků, které pracovaly systémem, že se popsala pozice a zobrazil se výsledek, zpravidla za spolupráce s balíkem PSTricks. Bylo to nesmírně zdlouhavé, zvláště když jste pracovali s partií. V té době ještě bohužel nebyl LuaLaTeX, takže jsem to musel psát pro ne moc rozšířený ConTeXt MkIV.

Místo zdlouhavého popisování se načetla celá partie ze standardního SGF s…

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Podnikatel.cz: Dárkové poukazy. Vaše byznys výhra

Dárkové poukazy. Vaše byznys výhra

Měšec.cz: Stavební spoření: alternativa i pro seniory

Stavební spoření: alternativa i pro seniory

120na80.cz: Co všechno ovlivňuje ženskou plodnost?

Co všechno ovlivňuje ženskou plodnost?

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Podnikatel.cz: Udávání a účtenková loterie, hloupá komedie

Udávání a účtenková loterie, hloupá komedie

Vitalia.cz: I církev dnes vyrábí potraviny

I církev dnes vyrábí potraviny

Vitalia.cz: Mondelez stahuje rizikovou čokoládu Milka

Mondelez stahuje rizikovou čokoládu Milka

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

Root.cz: Certifikáty zadarmo jsou horší než za peníze?

Certifikáty zadarmo jsou horší než za peníze?

Podnikatel.cz: Zavře krám u #EET Malá pokladna a Teeta?

Zavře krám u #EET Malá pokladna a Teeta?

120na80.cz: Pánové, pečujte o svoje přirození a prostatu

Pánové, pečujte o svoje přirození a prostatu

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

Vitalia.cz: Když přijdete o oko, přijdete na rok o řidičák

Když přijdete o oko, přijdete na rok o řidičák

Vitalia.cz: Paštiky plné masa ho zatím neuživí

Paštiky plné masa ho zatím neuživí

Podnikatel.cz: Chtějte údaje k dani z nemovitostí do mailu

Chtějte údaje k dani z nemovitostí do mailu

Vitalia.cz: Pamlsková vyhláška bude platit jen na základkách

Pamlsková vyhláška bude platit jen na základkách