001/*
002 * Copyright (c) 2012-2017 Institut National des Sciences Appliquées de Lyon (INSA-Lyon)
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 */
009
010package org.eclipse.golo.doc;
011
012import org.eclipse.golo.compiler.parser.ASTCompilationUnit;
013import gololang.FunctionReference;
014import gololang.Predefined;
015
016import java.nio.file.Path;
017import java.util.Map;
018import java.util.List;
019
020
021import com.github.rjeschke.txtmark.BlockEmitter;
022import com.github.rjeschke.txtmark.Configuration;
023import com.github.rjeschke.txtmark.Processor;
024
025
026public class HtmlProcessor extends AbstractProcessor {
027
028  private Path srcFile;
029  private final DocIndex globalIndex = new DocIndex();
030
031  @Override
032  protected String fileExtension() {
033    return "html";
034  }
035
036  public DocIndex globalIndex() {
037    return globalIndex;
038  }
039
040  /**
041   * Returns the direct link to the given documentation element from a given filename.
042   */
043  public String linkToDoc(String src, DocumentationElement dst) {
044    Path out = outputFile(src);
045    if (out.getParent() != null) {
046      out = out.getParent();
047    }
048    return out.relativize(docFile(dst)).toString()
049      + (dst.id().isEmpty() ? "" : ("#" + dst.id()));
050  }
051
052  @Override
053  public String render(ModuleDocumentation documentation) throws Throwable {
054    FunctionReference template = template("template", fileExtension());
055    globalIndex.update(documentation);
056    addModule(documentation);
057    Path doc = docFile(documentation);
058    if (doc.getParent() != null) {
059      doc = doc.getParent();
060    }
061    return (String) template.invoke(this, documentation, doc.relativize(srcFile));
062  }
063
064  @Override
065  public void process(Map<String, ModuleDocumentation> docs, Path targetFolder) throws Throwable {
066    setTargetFolder(targetFolder);
067    for (Map.Entry<String, ModuleDocumentation> doc : docs.entrySet()) {
068      renderModule(doc.getKey(), doc.getValue());
069    }
070    renderIndex("index");
071    renderIndex("index-all");
072  }
073
074  private void renderModule(String sourceFile, ModuleDocumentation doc) throws Throwable {
075    String moduleName = doc.moduleName();
076    srcFile = outputFile(moduleName + "-src");
077    Predefined.textToFile(renderSource(moduleName, sourceFile), srcFile);
078    Predefined.textToFile(render(doc), outputFile(moduleName));
079  }
080
081  private String renderSource(String moduleName, String filename) throws Throwable {
082    FunctionReference template = template("src", fileExtension());
083    String content = (String) Predefined.fileToText(filename, "UTF-8");
084    int nbLines = 0;
085    for (int i = 0; i < content.length(); i++) {
086      if (content.charAt(i) == '\n') {
087        nbLines++;
088      }
089    }
090    return (String) template.invoke(moduleName, content, nbLines);
091  }
092
093  public static BlockEmitter blockHighlighter() {
094    return new BlockEmitter() {
095      @Override
096      public void emitBlock(StringBuilder out, List<String> lines, String meta) {
097        String language;
098        if ("".equals(meta)) {
099          language = "golo";
100        } else {
101          language = meta;
102        }
103        out.append("<pre class=\"listing\">");
104        out.append(String.format("<code class=\"lang-%s\" data-lang=\"%s\">", language, language));
105        for (String rawLine : lines) {
106          String line = rawLine
107            .replace("&", "&amp;")
108            .replace(">", "&gt;")
109            .replace("<", "&lt;");
110          out.append(line);
111          out.append('\n');
112        }
113        out.append("</code></pre>");
114        out.append('\n');
115      }
116    };
117  }
118
119  public static String sectionTitle(int level, DocumentationElement doc, Path src) {
120    String permalink = String.format("<a class=\"permalink\" href=\"#%s\" title=\"link to this section\">&#182;</a>",
121        doc.id());
122    String srclink = src == null ? ""
123      : String.format("<nav class=\"srclink\"><a href=\"%s#l-%s\" rel=\"source\" title=\"Link to the corresponding source\">Source</a></nav>",
124          src, doc.line());
125    return String.format("<h%s id=\"%s\">%s%s</h%s>%s", level, doc.id(), doc.label(), permalink, level, srclink);
126  }
127
128  public static String tocItem(DocumentationElement doc) {
129    return String.format("<a href=\"#%s\">%s</a>", doc.id(), doc.label());
130  }
131
132  public static String process(String documentation, int rootLevel, Configuration configuration) {
133    return Processor.process(AbstractProcessor.adaptSections(documentation, rootLevel), configuration);
134  }
135}