////
Included in:

- user-manual: Extensions: Extension Points
////

Here are the extension points that are available in Asciidoctor 0.1.4.

Preprocessor::
  Processes the raw source lines before they are passed to the parser.

TreeProcessor::
  Processes the [.class]#Asciidoctor::Document# (AST) once parsing is complete.

Postprocessor::
  Processes the output after the document has been converted, but before it's written to disk.

DocinfoProcessor::
  Adds additional content to the header or footer regions of the generated document.

Block processor::
  Processes a block of content marked with a custom block style (i.e., `[custom]`). (similar to an AsciiDoc filter)

Block macro processor::
  Registers a custom block macro and processes it (e.g., `gist::12345[]`).

Inline macro processor::
  Registers a custom inline macro and processes it (e.g., `btn:[Save]`).

Include processor::
  Processes the `include::<filename>[]` directive.

These extensions are registered per document using a callback that feels sort of like a DSL:

```ruby
Asciidoctor::Extensions.register do |document|
  preprocessor FrontMatterPreprocessor
  tree_processor ShellSessionTreeProcessor
  postprocessor CopyrightFooterPostprocessor
  docinfo_processor TrackingCodeDocinfoProcessor if document.basebackend? 'html'
  block ShoutBlock
  block_macro GistBlockMacro if document.basebackend? 'html'
  inline_macro ManInlineMacro
  include_processor UriIncludeProcessor
end
```

CAUTION: Extension classes must be defined outside of the register block.
Once an extension class is registered, it is frozen, preventing further modification.
If you define an extension class inside the register block, it will result in an error on subsequent invocations.

You can register more than one processor of each type, though you can only have one processor per custom block or macro.
Each registered class is instantiated when the [.class]#Asciidoctor::Document# is created.

NOTE: There is currently no extension point for processing a built-in block, such as a normal paragraph.
Look for that feature in a future Asciidoctor release.

////
For now, you need to use the Asciidoctor API (not the CLI) in order to register the extensions and invoke Asciidoctor.
Eventually, we'll be able to load extensions packaged in a RubyGem (Ruby) or JAR (Java) by scanning
the LOAD_PATH (Ruby) or classpath (Java), respectively.
We may also ship some built-in extensions that can be enabled using an attribute named `extensions`, similar to how Markdown processors work.

TIP: For those of you on the JVM, yes, you can write extensions in Java.
We've prototyped it and it works.
We're still sorting out a few technical challenges and documentation to make it completely smooth, but we'll get there.
For details, follow the discussion in issue {issue-ref}/79[#79].
////
