/* * Copyright 2011 Oliver Buchtala * * This file is part of ndogen. * * ndogen is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ndogen is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ndogen. If not, see <http://www.gnu.org/licenses/>. */ package org.ndogen.converter; import java.io.PrintWriter; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; import org.antlr.runtime.ANTLRStringStream; import org.antlr.runtime.CharStream; import org.antlr.runtime.CommonTokenStream; import org.antlr.runtime.RecognitionException; import org.antlr.runtime.tree.Tree; import org.ndogen.Fixture; import org.ndogen.TestUtils; import org.ndogen.antlr.DebugCharStream; import org.ndogen.markdown.MarkdownParser; import org.ndogen.markdown.MarkdownParser.document_return; import org.ndogen.markdown.MarkdownScanner; import org.ndogen.watch.task.ContentProvider; /** * Converts a Markdown source into html. * This will not create a standalone html page. * Use this in combination with a html template file. */ public class Markdown2Html implements ContentProvider { ContentProvider markdownProvider; // private TemplateProcessor templateProcessor; public Markdown2Html(ContentProvider markdownProvider) { super(); this.markdownProvider = markdownProvider; // templateProcessor = new TemplateProcessor(); } @Override public String getContent() { String input = markdownProvider.getContent(); CharStream lexerInput; lexerInput = new ANTLRStringStream(input); lexerInput = new DebugCharStream(lexerInput); MarkdownScanner lexer = new MarkdownScanner(lexerInput); CommonTokenStream tokens = new CommonTokenStream(lexer); MarkdownParser parser = new MarkdownParser(tokens); try { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); IndentWriter out = new IndentWriter(pw); document_return doc = parser.document(); Tree tree = (Tree) doc.getTree(); processTree(out, tree, new State()); return sw.toString(); } catch (RecognitionException e) { e.printStackTrace(); return "<h1>Parser Error!</h1>"; } // return "<html><h1>Not implemented yet</h1></html>"; } protected void processTree(IndentWriter out, Tree node, State state) { int type = node.getType(); switch(type) { case 0: for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } break; case MarkdownParser.SECTION: state.sectionLevel++; String title = node.getChild(0).getText(); out.println(String.format("<h%d>%s</h%d>", state.sectionLevel, title, state.sectionLevel)); out.indent(); for (int i = 1; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.dedent(); state.sectionLevel--; break; case MarkdownParser.TEXT_BLOCK: out.println("<p>"); out.indent(); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.dedent(); out.println(); out.println("</p>"); break; case MarkdownParser.TEXT: out.print(node.getText()); break; case MarkdownParser.LIST: out.println("<ul>"); out.indent(); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.dedent(); out.println("</ul>"); break; case MarkdownParser.LIST_ITEM: out.println("<li>"); out.indent(); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.dedent(); out.println(); out.println("</li>"); break; case MarkdownParser.QUOTE_BLOCK: out.println("<blockquote><p>"); out.indent(); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.dedent(); out.println(); out.println("</p></blockquote>"); break; case MarkdownParser.CODE_BLOCK: out.println("<pre>"); state.insertNL = true; out.indent(); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.dedent(); state.insertNL = false; out.println("</pre>"); break; case MarkdownParser.NL: if(state.breakLine) { out.println("<br/>"); } else if (state.insertNL) { out.println(); } else { out.print(" "); } break; case MarkdownParser.EL: // skip this break; case MarkdownParser.EMPH: out.print("<em>"); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.print("</em>"); break; case MarkdownParser.STRONG: out.print("<strong>"); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.print("</strong>"); break; case MarkdownParser.INLINE_CODE: out.print("<code>"); for (int i = 0; i < node.getChildCount(); i++) { processTree(out, node.getChild(i), state); } out.print("</code>"); break; case MarkdownParser.LINK: String text = node.getChild(0).getText(); String link = node.getChild(1).getText(); try { URL url = new URL(link); link = url.toString(); } catch (MalformedURLException e) { System.err.println("Malformed Url: " + link); out.print(text); break; } out.print("<a href=\""+link+"\">"+text+"</a>"); break; default: System.out.println("Skipping unhandled node "+ node.getText()); // skip } } public static class State { int sectionLevel = 0; boolean breakLine = false; boolean insertNL = false; } public static void main(String[] args) { Fixture fixture = TestUtils.getFixture("fixtures/markdown/parser", "links"); final String input = fixture.getInput(); Markdown2Html markdown2Html = new Markdown2Html(new ContentProvider() { @Override public String getContent() { return input; } }); String html = markdown2Html.getContent(); System.out.println(html); } }