package flow.netbeans.markdown;
import flow.netbeans.markdown.api.RenderOption;
import flow.netbeans.markdown.api.Renderable;
import flow.netbeans.markdown.options.MarkdownGlobalOptions;
import java.io.IOException;
import java.util.Set;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;
import org.openide.cookies.EditorCookie;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.util.Exceptions;
import org.pegdown.LinkRenderer;
import org.pegdown.ParsingTimeoutException;
import org.pegdown.PegDownProcessor;
import org.pegdown.ast.RootNode;
public class RenderableImpl implements Renderable {
private static final String TITLE = "{%TITLE%}";
private static final String CONTENT = "{%CONTENT%}";
private static final String SWING_TEMPLATE = "<html><body>" + CONTENT;
private final DataObject context;
public RenderableImpl(DataObject context) {
this.context = context;
}
@Override
public String renderAsHtml(Set<RenderOption> renderOptions) throws IOException {
MarkdownGlobalOptions markdownOptions = MarkdownGlobalOptions.getInstance();
String sourceText = getSourceText(renderOptions);
String bodyText = renderBodyText(renderOptions, markdownOptions, sourceText);
return renderHtmlText(renderOptions, markdownOptions, bodyText);
}
private String renderBodyText(Set<RenderOption> renderOptions, MarkdownGlobalOptions markdownOptions,
String sourceText) throws IOException {
String bodyText;
try {
PegDownProcessor markdownProcessor = new PegDownProcessor(markdownOptions.getExtensionsValue());
final boolean resolveImageUrls = renderOptions.contains(RenderOption.RESOLVE_IMAGE_URLS);
final boolean resolveLinkUrls = renderOptions.contains(RenderOption.RESOLVE_LINK_URLS);
if (resolveImageUrls || resolveLinkUrls) {
RootNode rootNode = markdownProcessor.parseMarkdown(sourceText.toCharArray());
FileObject sourceFile = context.getPrimaryFile();
final PreviewSerializer htmlSerializer
= new PreviewSerializer(sourceFile.toURL(), resolveImageUrls, resolveLinkUrls);
bodyText = htmlSerializer.toHtml(rootNode);
}
else {
RootNode rootNode = markdownProcessor.parseMarkdown(sourceText.toCharArray());
final ExportSerializer htmlSerializer
= new ExportSerializer(new LinkRenderer());
bodyText = htmlSerializer.toHtml(rootNode);
}
}
catch (ParsingTimeoutException ex) {
throw new IOException(ex);
}
return bodyText;
}
private String getSourceText(Set<RenderOption> renderOptions) throws IOException {
String sourceText = null;
if (renderOptions.contains(RenderOption.PREFER_EDITOR)) {
EditorCookie ec = context.getLookup().lookup(EditorCookie.class);
final StyledDocument sourceDoc = ec.getDocument();
if (sourceDoc != null) {
sourceText = getDocumentText(sourceDoc);
}
}
if (sourceText == null) {
FileObject sourceFile = context.getPrimaryFile();
sourceText = sourceFile.asText();
}
return sourceText;
}
private String getDocumentText(final Document sourceDoc) {
final String[] sourceTextRef = {null};
Runnable r = new Runnable() {
@Override
public void run() {
try {
sourceTextRef[0] = sourceDoc.getText(0, sourceDoc.getLength());
}
catch (BadLocationException ex) {
Exceptions.printStackTrace(ex);
}
}
};
sourceDoc.render(r);
return sourceTextRef[0];
}
private String getHtmlTemplate(Set<RenderOption> renderOptions, MarkdownGlobalOptions markdownOptions) {
String htmlTemplate;
if (renderOptions.contains(RenderOption.SWING_COMPATIBLE)) {
htmlTemplate = SWING_TEMPLATE;
}
else {
htmlTemplate = markdownOptions.getHtmlTemplate();
}
return htmlTemplate;
}
private String renderHtmlText(Set<RenderOption> renderOptions, MarkdownGlobalOptions markdownOptions,
String bodyText) {
String htmlTemplate = getHtmlTemplate(renderOptions, markdownOptions);
FileObject sourceFile = context.getPrimaryFile();
String htmlText = htmlTemplate
.replace(TITLE, sourceFile.getName())
.replace(CONTENT, bodyText);
return htmlText;
}
}