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: }