/*
* Copyright 2013 Julien Viet
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.asciidoc.intellij;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import org.apache.geronimo.gshell.io.SystemOutputHijacker;
import org.asciidoc.intellij.actions.AsciiDocAction;
import org.asciidoc.intellij.editor.AsciiDocPreviewEditor;
import org.asciidoc.intellij.editor.javafx.JavaFxHtmlPanelProvider;
import org.asciidoc.intellij.settings.AsciiDocApplicationSettings;
import org.asciidoctor.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.file.Path;
import java.util.Map;
/**
* @author Julien Viet
*/
public class AsciiDoc {
private static Asciidoctor asciidoctor;
/**
* Base directory to look up includes.
*/
private final File baseDir;
/**
* Images directory.
*/
private final Path imagesPath;
private final String name;
public AsciiDoc(File path, Path imagesPath, String name) {
this.baseDir = path;
this.imagesPath = imagesPath;
this.name = name;
synchronized (AsciiDoc.class) {
if (asciidoctor == null) {
SystemOutputHijacker.install();
ClassLoader old = Thread.currentThread().getContextClassLoader();
ByteArrayOutputStream boasOut = new ByteArrayOutputStream();
ByteArrayOutputStream boasErr = new ByteArrayOutputStream();
SystemOutputHijacker.register(new PrintStream(boasOut), new PrintStream(boasErr));
try {
Thread.currentThread().setContextClassLoader(AsciiDocAction.class.getClassLoader());
asciidoctor = Asciidoctor.Factory.create();
asciidoctor.requireLibrary("asciidoctor-diagram");
InputStream is = this.getClass().getResourceAsStream("/sourceline-treeprocessor.rb");
if (is == null) {
throw new RuntimeException("unable to load script sourceline-treeprocessor.rb");
}
asciidoctor.rubyExtensionRegistry().loadClass(is).treeprocessor("SourceLineTreeProcessor");
} finally {
SystemOutputHijacker.deregister();
notify(boasOut, boasErr);
Thread.currentThread().setContextClassLoader(old);
}
}
}
}
private void notify(ByteArrayOutputStream boasOut, ByteArrayOutputStream boasErr) {
String out = boasOut.toString();
String err = boasErr.toString();
if (out.length() > 0) {
Notification notification = AsciiDocPreviewEditor.NOTIFICATION_GROUP.createNotification("Message during rendering " + name, out,
NotificationType.INFORMATION, null);
notification.setImportant(false);
Notifications.Bus.notify(notification);
}
if (err.length() > 0) {
Notification notification = AsciiDocPreviewEditor.NOTIFICATION_GROUP.createNotification("Error during rendering " + name, err,
NotificationType.INFORMATION, null);
notification.setImportant(true);
Notifications.Bus.notify(notification);
}
}
public String render(String text) {
synchronized (asciidoctor) {
ClassLoader old = Thread.currentThread().getContextClassLoader();
ByteArrayOutputStream boasOut = new ByteArrayOutputStream();
ByteArrayOutputStream boasErr = new ByteArrayOutputStream();
SystemOutputHijacker.register(new PrintStream(boasOut), new PrintStream(boasErr));
try {
Thread.currentThread().setContextClassLoader(AsciiDocAction.class.getClassLoader());
return "<div id=\"content\">\n" + asciidoctor.render(text, getDefaultOptions()) + "\n</div>";
} finally {
SystemOutputHijacker.deregister();
notify(boasOut, boasErr);
Thread.currentThread().setContextClassLoader(old);
}
}
}
public Map<String, Object> getDefaultOptions() {
Attributes attrs = AttributesBuilder.attributes().showTitle(true)
.sourceHighlighter("coderay").attribute("coderay-css", "style")
.attribute("env", "idea").attribute("env-idea").get();
if (imagesPath != null) {
final AsciiDocApplicationSettings settings = AsciiDocApplicationSettings.getInstance();
if (settings.getAsciiDocPreviewSettings().getHtmlPanelProviderInfo().getClassName().equals(JavaFxHtmlPanelProvider.class.getName())) {
attrs.setAttribute("outdir", imagesPath.toAbsolutePath().normalize().toString());
}
}
OptionsBuilder opts = OptionsBuilder.options().safe(SafeMode.UNSAFE).backend("html5").headerFooter(false).attributes(attrs).option("sourcemap", "true")
.baseDir(baseDir);
return opts.asMap();
}
}