Skip to content

Commit

Permalink
resolves issue #86 by adding extension API support
Browse files Browse the repository at this point in the history
  • Loading branch information
lordofthejars committed Oct 2, 2013
1 parent 98927df commit c69b607
Show file tree
Hide file tree
Showing 39 changed files with 1,602 additions and 482 deletions.
550 changes: 323 additions & 227 deletions src/main/java/org/asciidoctor/Asciidoctor.java

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/main/java/org/asciidoctor/Attributes.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class Attributes {
public static final String MAX_INCLUDE_DEPTH = "max-include-depth";
public static final String ATTRIBUTE_MISSING = "attribute-missing";
public static final String ATTRIBUTE_UNDEFINED = "attribute-undefined";

public static final String JRUBY = "jruby";

private Map<String, Object> attributes = new HashMap<String, Object>();

Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/asciidoctor/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class Options {
public static final String DOCTYPE = "doctype";
public static final String BASEDIR = "base_dir";
public static final String TEMPLATE_CACHE ="template_cache";
public static final String SOURCE = "source";

private Map<String, Object> options = new HashMap<String, Object>();

Expand Down
11 changes: 11 additions & 0 deletions src/main/java/org/asciidoctor/extension/BlockMacroProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.asciidoctor.extension;

import org.asciidoctor.internal.DocumentRuby;

public abstract class BlockMacroProcessor extends MacroProcessor {

public BlockMacroProcessor(String macroName, DocumentRuby documentRuby) {
super(macroName, documentRuby);
}

}
41 changes: 41 additions & 0 deletions src/main/java/org/asciidoctor/extension/BlockProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.asciidoctor.extension;

import java.util.HashMap;
import java.util.Map;

import org.asciidoctor.internal.Block;
import org.asciidoctor.internal.DocumentRuby;
import org.asciidoctor.internal.Reader;
import org.asciidoctor.internal.RubyHashUtil;
import org.jruby.Ruby;

public abstract class BlockProcessor extends Processor {

protected static final Map<String, Object> config = new HashMap<String, Object>();

public static Map<String, Object> config() {
return config;
}

// Glue code to convert the config object to proper Ruby types using Ruby runtime
public static void setup(Ruby rubyRuntime) {
Map<String, Object> raw = config();
Map<String, Object> converted = RubyHashUtil.convertMapToRubyHashWithSymbols(rubyRuntime, raw);
raw.clear();
raw.putAll(converted);
}

protected String context;
protected Map<String, Object> options;

public BlockProcessor(String context, DocumentRuby documentRuby) {
super(documentRuby);
this.context = context;
}

protected Map<String, Object> options() {
return new HashMap<String, Object>();
}

public abstract Object process(Block parent, Reader reader, Map<String, Object> attributes);
}
91 changes: 91 additions & 0 deletions src/main/java/org/asciidoctor/extension/ExtensionRegistry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.asciidoctor.extension;

import org.asciidoctor.internal.AsciidoctorModule;
import org.asciidoctor.internal.RubyUtils;
import org.jruby.Ruby;

public class ExtensionRegistry {

private AsciidoctorModule asciidoctorModule;
private Ruby rubyRuntime;

public ExtensionRegistry(AsciidoctorModule asciidoctorModule, Ruby rubyRuntime) {
super();
this.asciidoctorModule = asciidoctorModule;
this.rubyRuntime = rubyRuntime;
}

public void preprocessor(Class<? extends Preprocessor> preprocessor) {
// this may change in future to external class to deal with dynamic
// imports
this.rubyRuntime.evalScriptlet("java_import " + preprocessor.getName());
this.asciidoctorModule.preprocessor(preprocessor.getSimpleName());
}

public void postprocessor(Class<? extends Postprocessor> postprocesor) {
// this may change in future to external class to deal with dynamic
// imports
this.rubyRuntime.evalScriptlet("java_import " + postprocesor.getName());
this.asciidoctorModule.postprocessor(postprocesor.getSimpleName());
}

public void includeProcessor(
Class<? extends IncludeProcessor> includeProcessor) {
// this may change in future to external class to deal with dynamic
// imports
this.rubyRuntime.evalScriptlet("java_import "
+ includeProcessor.getName());
this.asciidoctorModule.include_processor(includeProcessor
.getSimpleName());
}

public void treeprocessor(Class<? extends Treeprocessor> treeProcessor) {
// this may change in future to external class to deal with dynamic
// imports
this.rubyRuntime
.evalScriptlet("java_import " + treeProcessor.getName());
this.asciidoctorModule.treeprocessor(treeProcessor.getSimpleName());
}

public void block(String blockName,
Class<? extends BlockProcessor> blockProcessor) {
// this may change in future to external class to deal with dynamic
// imports
this.rubyRuntime.evalScriptlet("java_import "
+ blockProcessor.getName());
try {
// invoke setup(Ruby) method to convert config Map to RubyHash with symbols
blockProcessor.getMethod("setup", Ruby.class).invoke(null, this.rubyRuntime);
} catch (Exception e) {
throw new RuntimeException("Failed to invoke setup method on block processor class: " + blockProcessor, e);
}

this.asciidoctorModule.block_processor(
RubyUtils.toSymbol(rubyRuntime, blockName),
blockProcessor.getSimpleName());
}

public void blockMacro(String blockName,
Class<? extends BlockMacroProcessor> blockMacroProcessor) {
// this may change in future to external class to deal with dynamic
// imports
this.rubyRuntime.evalScriptlet("java_import "
+ blockMacroProcessor.getName());
this.asciidoctorModule.block_macro(
RubyUtils.toSymbol(rubyRuntime, blockName),
blockMacroProcessor.getSimpleName());
}

public void inlineMacro(String blockName,
Class<? extends InlineMacroProcessor> inlineMacroProcessor) {
// this may change in future to external class to deal with dynamic
// imports
this.rubyRuntime.evalScriptlet("java_import "
+ inlineMacroProcessor.getName());
this.asciidoctorModule.inline_macro(
RubyUtils.toSymbol(rubyRuntime, blockName),
inlineMacroProcessor.getSimpleName());
}


}
17 changes: 17 additions & 0 deletions src/main/java/org/asciidoctor/extension/IncludeProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.asciidoctor.extension;

import java.util.Map;

import org.asciidoctor.internal.DocumentRuby;
import org.asciidoctor.internal.PreprocessorReader;

public abstract class IncludeProcessor extends Processor {

public IncludeProcessor(DocumentRuby documentRuby) {
super(documentRuby);
}

public abstract boolean handles(String target);
public abstract void process(PreprocessorReader reader, String target, Map<String, Object> attributes);

}
21 changes: 21 additions & 0 deletions src/main/java/org/asciidoctor/extension/InlineMacroProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.asciidoctor.extension;

import org.asciidoctor.internal.DocumentRuby;
import org.jruby.RubyRegexp;
import org.jruby.util.ByteList;

public abstract class InlineMacroProcessor extends MacroProcessor {

protected RubyRegexp regexp;

public InlineMacroProcessor(String macroName, DocumentRuby documentRuby) {
super(macroName, documentRuby);
ByteList pattern = ByteList.create(macroName + ":(\\S+?)\\[.*?\\]");
regexp = RubyRegexp.newRegexp(rubyRuntime, pattern);
}

public RubyRegexp regexp() {
return regexp;
}

}
29 changes: 29 additions & 0 deletions src/main/java/org/asciidoctor/extension/MacroProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.asciidoctor.extension;

import java.util.HashMap;
import java.util.Map;

import org.asciidoctor.internal.Document;
import org.asciidoctor.internal.DocumentRuby;

public abstract class MacroProcessor extends Processor {

protected String macroName;

public MacroProcessor(String macroName, DocumentRuby documentRuby) {
super(documentRuby);
this.macroName = macroName;
}


public Map<Object, Object> options() {
return new HashMap<Object, Object>();
}

public Object process(DocumentRuby parent, String target, Map<String, Object> attributes) {
return process(new Document(parent, rubyRuntime), target, attributes);
}

protected abstract Object process(Document parent, String target, Map<String, Object> attributes);

}
13 changes: 13 additions & 0 deletions src/main/java/org/asciidoctor/extension/Postprocessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.asciidoctor.extension;

import org.asciidoctor.internal.DocumentRuby;

public abstract class Postprocessor extends Processor {

public Postprocessor(DocumentRuby documentRuby) {
super(documentRuby);
}

public abstract String process(String output);

}
16 changes: 16 additions & 0 deletions src/main/java/org/asciidoctor/extension/Preprocessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.asciidoctor.extension;

import java.util.List;

import org.asciidoctor.internal.DocumentRuby;
import org.asciidoctor.internal.PreprocessorReader;

public abstract class Preprocessor extends Processor {

public Preprocessor(DocumentRuby documentRuby) {
super(documentRuby);
}

public abstract PreprocessorReader process(PreprocessorReader reader, List<String> lines);

}
45 changes: 45 additions & 0 deletions src/main/java/org/asciidoctor/extension/Processor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.asciidoctor.extension;

import java.util.Map;

import org.asciidoctor.Attributes;
import org.asciidoctor.Options;
import org.asciidoctor.internal.Block;
import org.asciidoctor.internal.Document;
import org.asciidoctor.internal.DocumentRuby;
import org.asciidoctor.internal.RubyHashUtil;
import org.asciidoctor.internal.RubyUtils;
import org.jruby.Ruby;
import org.jruby.RubyHash;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;

public class Processor {

protected Document document;
protected Ruby rubyRuntime;

public Processor(DocumentRuby documentRuby) {
this.rubyRuntime = (Ruby) documentRuby.getAttributes()
.get(Attributes.JRUBY);
this.document = new Document(documentRuby, rubyRuntime);
}

public Block createBlock(Document parent, String context, String content, Map<String, Object> attributes,
Map<String, Object> options) {

options.put(Options.SOURCE, content);
options.put(Options.ATTRIBUTES, attributes);

IRubyObject rubyClass = rubyRuntime.evalScriptlet("Asciidoctor::Block");
RubyHash convertMapToRubyHashWithSymbols = RubyHashUtil.convertMapToRubyHashWithSymbols(rubyRuntime,
options);
Object[] parameters = {
parent.getDocumentRuby(),
RubyUtils.toSymbol(rubyRuntime, context),
convertMapToRubyHashWithSymbols };
return (Block) JavaEmbedUtils.invokeMethod(rubyRuntime, rubyClass,
"new", parameters, Block.class);
}

}
13 changes: 13 additions & 0 deletions src/main/java/org/asciidoctor/extension/Treeprocessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.asciidoctor.extension;

import org.asciidoctor.internal.DocumentRuby;

public abstract class Treeprocessor extends Processor {

public Treeprocessor(DocumentRuby documentRuby) {
super(documentRuby);
}

public abstract void process();

}
13 changes: 11 additions & 2 deletions src/main/java/org/asciidoctor/internal/AsciidoctorModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@

public interface AsciidoctorModule {

void preprocessor(String preprocessorClassName);
void postprocessor(String postprocessorClassName);
void block_processor(Object blockSymbol, String blockClassName);
void block_macro(Object blockSymbol, String blockClassName);
void inline_macro(Object blockSymbol, String blockClassName);
void include_processor(String includeProcessorClassName);
void treeprocessor(String treeprocessor);

Object render(String content, Map<String, Object> options);
Object render_file(String filename, Map<String, Object> options);

Document load_file(String filename, Map<String, Object> options);
Document load(String content, Map<String, Object> options);
DocumentRuby load_file(String filename, Map<String, Object> options);
DocumentRuby load(String content, Map<String, Object> options);

}
13 changes: 13 additions & 0 deletions src/main/java/org/asciidoctor/internal/Block.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.asciidoctor.internal;

import java.util.List;
import java.util.Map;

public interface Block {

String context();
List<String> lines();
Map<String, Object> attributes();


}
Loading

0 comments on commit c69b607

Please sign in to comment.