franta-hg@61: /** franta-hg@61: * XML Web generátor – program na generování webových stránek franta-hg@61: * Copyright © 2012 František Kučera (frantovo.cz) franta-hg@61: * franta-hg@61: * This program is free software: you can redistribute it and/or modify franta-hg@61: * it under the terms of the GNU General Public License as published by franta-hg@61: * the Free Software Foundation, either version 3 of the License, or franta-hg@61: * (at your option) any later version. franta-hg@61: * franta-hg@61: * This program is distributed in the hope that it will be useful, franta-hg@61: * but WITHOUT ANY WARRANTY; without even the implied warranty of franta-hg@61: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the franta-hg@61: * GNU General Public License for more details. franta-hg@61: * franta-hg@61: * You should have received a copy of the GNU General Public License franta-hg@61: * along with this program. If not, see . franta-hg@61: */ franta-hg@6: package cz.frantovo.xmlWebGenerator; franta-hg@6: franta-hg@6: import java.io.File; franta-hg@27: import java.io.IOException; franta-hg@27: import java.io.PrintStream; franta-hg@6: import java.util.Date; franta-hg@6: import java.net.URI; franta-hg@6: import java.net.URISyntaxException; franta-hg@67: import java.net.URLDecoder; franta-hg@67: import java.nio.charset.Charset; franta-hg@38: import static cz.frantovo.xmlWebGenerator.NástrojeCLI.*; franta-hg@6: franta-hg@28: /** franta-hg@28: * Knihovna funkcí volaných z XSLT. franta-hg@28: * franta-hg@36: * TODO: franta-hg@32: * - rozdělit na více modulů (jmenných prostorů). franta-hg@32: * - CLI konektor franta-hg@28: * franta-hg@28: * @author fiki franta-hg@28: */ franta-hg@6: public class Funkce { franta-hg@27: franta-hg@30: private static final String PŘÍKAZ_PYGMENTIZE = "pygmentize"; franta-hg@32: private static final String PŘÍKAZ_DOT = "dot"; franta-hg@37: private static final String PŘÍKAZ_MARKDOWN = "markdown"; franta-hg@32: private static final String ADRESÁŘ_VÝSTUPNÍ = "výstup"; franta-hg@32: private static int počítadloDiagramů = 0; franta-hg@69: private static String počítadloDiagramůKontext = ""; // aktuálně zpracovávaná stránka, při změně vynulujeme počítadlo franta-hg@30: franta-hg@28: /** franta-hg@28: * Zjištuje, kdy byl naposledy daný soubor změněn. franta-hg@28: * @param soubor cesta k souboru franta-hg@28: * @return datum poslední změny franta-hg@28: * @throws URISyntaxException franta-hg@28: */ franta-hg@21: public static Date posledníZměna(String soubor) throws URISyntaxException { franta-hg@28: URI uri = new URI(soubor); franta-hg@28: File f = new File(uri); franta-hg@28: return new Date(f.lastModified()); franta-hg@21: } franta-hg@27: franta-hg@27: /** franta-hg@27: * Zvýrazňuje syntaxi zdrojového kódu. Používá k tomu externí program/knihovnu pygmentize. franta-hg@27: * @param zdroják zdrojový kód, který předáme příkazu pygmentize na standardním vstupu franta-hg@27: * @param jazyk předáme příkazu pygmentize jako parametr -l <lexer> franta-hg@28: * @return zvýrazněný text nebo null, pokud došlo k chybě. franta-hg@31: * TODO: franta-hg@36: * - vracet místo textu instanci com.icl.saxon.om.NodeInfo http://saxon.sourceforge.net/saxon6.5.3/extensibility.html franta-hg@31: * - nebo kontrolovat validitu vygenerovaného kódu (v současnosti se spoléháme na bezchybnost pygmentize) franta-hg@27: */ franta-hg@27: public static String zvýrazniSyntaxi(String zdroják, String jazyk) throws IOException, InterruptedException { franta-hg@28: if (jazyk == null || jazyk.length() == 0) { franta-hg@28: System.err.println("Není vyplněn atribut „jazyk“ → není jasné, jak se má zvýrazňovat."); franta-hg@28: return null; franta-hg@36: } else if (isPříkazDostupný(PŘÍKAZ_PYGMENTIZE)) { franta-hg@27: Runtime r = Runtime.getRuntime(); franta-hg@30: Process p = r.exec(new String[]{PŘÍKAZ_PYGMENTIZE, "-f", "html", "-l", jazyk}); franta-hg@27: franta-hg@27: PrintStream vstupProcesu = new PrintStream(p.getOutputStream()); franta-hg@27: vstupProcesu.print(zdroják); franta-hg@27: vstupProcesu.close(); franta-hg@27: franta-hg@27: String výsledek = načtiProud(p.getInputStream()); franta-hg@27: String chyby = načtiProud(p.getErrorStream()); franta-hg@27: franta-hg@27: p.waitFor(); franta-hg@27: franta-hg@27: if (chyby.length() == 0) { franta-hg@28: // Pozor: pygmentize má i při chybě návratový kód 0 → je potřeba kontrolovat chybový výstup. franta-hg@27: return výsledek; franta-hg@27: } else { franta-hg@28: System.err.print("Při zvýrazňování syntaxe došlo k chybě: " + chyby); franta-hg@28: return null; franta-hg@27: } franta-hg@27: } else { franta-hg@30: System.err.println("Příkaz " + PŘÍKAZ_PYGMENTIZE + " není na vašem systému dostupný → zvýrazňování syntaxe nebude fungovat."); franta-hg@28: System.err.println("Můžete ho nainstalovat pomocí:"); franta-hg@28: System.err.println("\t$ aptitude install python-pygments # (Debian/Ubuntu)"); franta-hg@28: System.err.println("\t$ yum install python-pygments # (Fedora/RedHat)"); franta-hg@28: return null; franta-hg@27: } franta-hg@27: } franta-hg@27: franta-hg@28: /** franta-hg@31: * Vygeneruje CSS styl pro zvýrazňování syntaxe. franta-hg@31: * @return obsah CSS souboru nebo null, pokud generování nebylo možné franta-hg@31: */ franta-hg@31: public static String generujCssSyntaxe() throws IOException, InterruptedException { franta-hg@36: if (isPříkazDostupný(PŘÍKAZ_PYGMENTIZE)) { franta-hg@31: Runtime r = Runtime.getRuntime(); franta-hg@31: Process p = r.exec(new String[]{PŘÍKAZ_PYGMENTIZE, "-S", "default", "-f", "html"}); franta-hg@31: return načtiProud(p.getInputStream()); franta-hg@31: } else { franta-hg@31: return null; franta-hg@31: } franta-hg@31: } franta-hg@31: franta-hg@31: /** franta-hg@32: * Vytvoří obrázek s diagramem. franta-hg@32: * @param zadání definice diagramu ve formátu dot franta-hg@52: * @param vodorovně zda má být graf orientovaný vodorovně (funguje jen při kompletní = false) franta-hg@52: * @param kompletní false, pokud k zadání chceme doplnit digraph d {…} franta-hg@67: * @param kontext kam diagram patří – typicky název stránky, do které je vložen franta-hg@67: * diagramy se pak budou číslovat v rámci tohoto kontextu franta-hg@67: * → nebude docházet k přepisování diagramů jiných stránek při částečném přegenerování webu. franta-hg@67: * @param souborZadání null pokud chceme automatické číslování | nebo zadáme název souboru se zadáním diagramu – vygenerovaný diagram se pak bude jmenovat stejně franta-hg@32: * @return název souboru bez přípony, který byl vytvořen, nebo null, pokud došlo k chybě. franta-hg@32: */ franta-hg@67: public static String vytvořDiagram(String zadání, boolean vodorovně, boolean kompletní, String kontext, String souborZadání) throws IOException, InterruptedException { franta-hg@36: if (isPříkazDostupný(PŘÍKAZ_DOT)) { franta-hg@67: franta-hg@67: String soubor; franta-hg@67: if (souborZadání == null) { franta-hg@67: if (kontext == null) { franta-hg@67: počítadloDiagramů++; franta-hg@67: soubor = "diagram-" + počítadloDiagramů; franta-hg@67: } else { franta-hg@67: // TODO: tohle by se mělo udělat v XSLT franta-hg@67: kontext = URLDecoder.decode(kontext, Charset.defaultCharset().name()); franta-hg@67: franta-hg@67: // Každá stránka bude mít svoje diagramy číslované od 1 franta-hg@67: if (!počítadloDiagramůKontext.equals(kontext)) { franta-hg@67: počítadloDiagramůKontext = kontext; franta-hg@67: počítadloDiagramů = 0; franta-hg@67: } franta-hg@67: franta-hg@67: počítadloDiagramů++; franta-hg@67: soubor = "diagram-" + kontext + "-" + počítadloDiagramů; franta-hg@67: } franta-hg@67: } else { franta-hg@67: soubor = souborZadání; franta-hg@67: } franta-hg@69: String souborSložka = ADRESÁŘ_VÝSTUPNÍ + File.separator + soubor; franta-hg@32: franta-hg@52: String zdroják; franta-hg@52: if (kompletní) { franta-hg@52: zdroják = zadání; franta-hg@52: } else { franta-hg@52: StringBuilder b = new StringBuilder(zadání.length() + 200); franta-hg@52: b.append("digraph d {\n"); franta-hg@52: b.append("\tbgcolor=\"transparent\";\n"); franta-hg@52: if (vodorovně) { franta-hg@52: b.append("\trankdir=LR;"); franta-hg@52: } franta-hg@52: b.append(zadání); franta-hg@52: b.append("}\n"); franta-hg@52: zdroják = b.toString(); franta-hg@32: } franta-hg@32: franta-hg@32: Runtime r = Runtime.getRuntime(); franta-hg@32: Process p = r.exec(new String[]{PŘÍKAZ_DOT, "-T", "svg", "-o", souborSložka + ".svg"}); franta-hg@32: franta-hg@32: /** franta-hg@32: * TODO: generovat i PNG bitmapu franta-hg@32: */ franta-hg@32: PrintStream vstupProcesu = new PrintStream(p.getOutputStream()); franta-hg@32: vstupProcesu.print(zdroják.toString()); franta-hg@32: vstupProcesu.close(); franta-hg@32: franta-hg@32: String chyby = načtiProud(p.getErrorStream()); franta-hg@32: franta-hg@32: p.waitFor(); franta-hg@32: franta-hg@32: if (chyby.length() == 0) { franta-hg@69: return soubor; franta-hg@32: } else { franta-hg@32: System.err.print("Při vytváření diagramu došlo k chybě: " + chyby); franta-hg@32: return null; franta-hg@32: } franta-hg@32: } else { franta-hg@32: System.err.println("Příkaz " + PŘÍKAZ_DOT + " není na vašem systému dostupný → diagramy nelze vygreslit."); franta-hg@32: System.err.println("Můžete ho nainstalovat pomocí:"); franta-hg@32: System.err.println("\t$ aptitude install graphviz # (Debian/Ubuntu)"); franta-hg@32: System.err.println("\t$ yum install graphviz # (Fedora/RedHat)"); franta-hg@32: return null; franta-hg@32: } franta-hg@32: } franta-hg@32: franta-hg@32: /** franta-hg@37: * Převede text ve wiki syntaxi do XHTML. franta-hg@37: * @param wiki vstupní text v dané wiki syntaxi franta-hg@37: * @param syntaxe null nebo volitelně syntaxe (markdown, texy) franta-hg@37: * @return naformátované XHTML franta-hg@37: */ franta-hg@37: public static String formátujWiki(String wiki, String syntaxe) throws IOException { franta-hg@37: if (isPříkazDostupný(PŘÍKAZ_MARKDOWN)) { franta-hg@37: Runtime r = Runtime.getRuntime(); franta-hg@37: Process p = r.exec(new String[]{PŘÍKAZ_MARKDOWN}); franta-hg@37: franta-hg@37: /** franta-hg@37: * TODO: oříznout mezery na začátcích řádků, pokud je jich všude stejně? franta-hg@37: * (odsazení v XML) franta-hg@37: */ franta-hg@37: PrintStream vstupProcesu = new PrintStream(p.getOutputStream()); franta-hg@37: vstupProcesu.print(wiki); franta-hg@37: vstupProcesu.close(); franta-hg@37: franta-hg@37: String chyby = načtiProud(p.getErrorStream()); franta-hg@37: String xhtml = načtiProud(p.getInputStream()); franta-hg@37: franta-hg@37: if (chyby.length() == 0) { franta-hg@37: return xhtml; franta-hg@37: } else { franta-hg@37: System.err.print("Při zpracování wiki syntaxe došlo k chybě: " + chyby); franta-hg@37: return null; franta-hg@37: } franta-hg@37: } else { franta-hg@37: System.err.println("Příkaz " + PŘÍKAZ_MARKDOWN + " není na vašem systému dostupný → nelze formátovat texty ve wiki syntaxi."); franta-hg@37: System.err.println("Můžete ho nainstalovat pomocí:"); franta-hg@37: System.err.println("\t$ aptitude install markdown # (Debian/Ubuntu)"); franta-hg@37: System.err.println("\t$ yum install perl-Text-Markdown # (Fedora/RedHat)"); franta-hg@37: return null; franta-hg@37: } franta-hg@37: } franta-hg@6: }