Skip to content

Commit

Permalink
resolves asciidoctor#59 set outdir/outfile attributes
Browse files Browse the repository at this point in the history
- set site-related attributes
  * site-root
  * site-source
  * site-destination,
  * site-baseurl
  * site-url
- set site, implict and default attributes in front of user-defined attributes
- set outdir/outfile attributes so extensions know where to write files
- automatically configure imagesoutdir if imagesdir starts with / and imagesoutdir is not set
- set docfile attribute in addition to docdir
- only set docdir if base_dir is :docdir
- add tests for docfile, outfile and outdir
- include spec_helper using require_relative
- update documentation
  • Loading branch information
mojavelinux committed Jun 21, 2016
1 parent c1a3dac commit 71ed563
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 67 deletions.
85 changes: 68 additions & 17 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ endif::[]
:uri-asciidoc: http://asciidoc.org
:uri-asciidoctor: http://asciidoctor.org
:uri-gem: http://rubygems.org/gems/jekyll-asciidoc
:uri-gem-asciidoctor: http://rubygems.org/gems/asciidoctor
:uri-gem-asciidoctor: http://rubygems.org/gems/asciidoctor
:uri-repo: https://github.com/asciidoctor/jekyll-asciidoc
:uri-jekyll: https://jekyllrb.com
:uri-front-matter: http://jekyllrb.com/docs/frontmatter/
:uri-liquid-templates: https://jekyllrb.com/docs/templates/
:uri-asciidoctor-diagram: http://asciidoctor.org/docs/asciidoctor-diagram/
:uri-graphviz: http://www.graphviz.org

ifdef::status[]
Expand Down Expand Up @@ -109,7 +110,7 @@ Here's a sample AsciiDoc file that meets these criteria:
----
---
layout: info
permalink: /page/
permalink: /sample/
---
= Sample Page
:uri-asciidoctor: http://asciidoctor.org
Expand All @@ -128,7 +129,7 @@ Alternatively, you can define the page variables directly in the AsciiDoc header
----
= Sample Page
:page-layout: info
:page-permalink: /page/
:page-permalink: /sample/
:uri-asciidoctor: http://asciidoctor.org
This is a sample page composed in AsciiDoc.
Expand Down Expand Up @@ -269,6 +270,11 @@ asciidoc:
The following implicit AsciiDoc attributes are automatically defined for each page:

....
site-root=(absolute path of root directory)
site-source=(absolute path of source directory)
site-destination=(absolute path of output directory)
site-baseurl=(value of the baseurl config option)
site-url=(value of the url config option)
env=site
env-site
site-gen=jekyll
Expand Down Expand Up @@ -405,7 +411,7 @@ Now run the `bundle` command to install the new gems.

=== Step 3: Create a Templates Folder

Next, create a new folder in your site named [path]___templates__ to store your templates.
Next, create a new folder in your site named [path]__templates_ to store your templates.

$ mkdir _templates

Expand Down Expand Up @@ -453,7 +459,9 @@ TIP: You can find additional examples of custom templates in the https://github.

== Enabling Asciidoctor Diagram

Asciidoctor Diagram is a set of extensions for Asciidoctor that allow you to embed diagrams written using the PlantUML, Graphviz, ditaa, or Shaape syntax inside your AsciiDoc documents.
{uri-asciidoctor-diagram}[Asciidoctor Diagram] is a set of extensions for Asciidoctor that allow you to embed diagrams generated by PlantUML, Graphviz, ditaa, Shaape, and other plain-text diagram tools inside your AsciiDoc documents.
In order to use Asciidoctor Diagram in a Jekyll project successfully, *you must use Jekyll >= 3.0.0 and a version of this plugin >= 2.0.0*.
Other combinations are known to have issues.

[IMPORTANT]
For Graphviz and PlantUML diagram generation, {uri-graphviz}[Graphviz] must be installed (i.e., the `dot` utility must be available on your `$PATH`.
Expand All @@ -473,7 +481,7 @@ group :jekyll_plugins do
...
end
----
<1> version can be configured differently
<1> Customize the version of Asciidoctor Diagram as needed.

Then, run the Bundler command to install it:

Expand All @@ -497,22 +505,30 @@ gems:
----
--

Both of the previous configurations are the equivalent of passing `-r asciidoctor-diagram` to the `asciidoctor` command.
The preceding configurations are the equivalent of passing `-r asciidoctor-diagram` to the `asciidoctor` command.

=== Generated Image Location

By default diagram images are generated in the root folder.
Thus, images URLs are not properly referenced from the generated HTML pages.
Asciidoctor Diagram needs some context in order to write the images to the proper location.
At a minimum, you must set the following configuration in {path-config}:

To fix this, set the `imagesdir` attribute in any AsciiDoc file that contains diagrams.
[source,yaml]
----
asciidoctor:
base_dir: :docdir
safe: unsafe
----

With this configuration, Asciidoctor Diagram will generate images relative to the generated HTML page (i.e., into the same directory).

._posts/2015-12-24-diagrams.adoc
You can use the following example to test your setup:

._posts/2016-01-01-diagram-sample.adoc
[source,asciidoc]
----
= Diagrams
:imagesdir: /images/2015-12-24 <1>
= Diagram Sample
[graphviz, dot-example, svg]
[graphviz,dot-example,svg]
....
digraph g {
a -> b
Expand All @@ -522,10 +538,45 @@ digraph g {
}
....
----
<1> the date in the imagesdir value must match the date of the post (e.g., 2015-12-24)

WARNING: The images are generated after Jekyll copies assets to the [path]_{empty}_site_ directory.
Therefore, you'll have to run `jeykll` twice before you see the images in the preview.
If you'd rather serve all images from the same folder, set the `imagesdir` attribute relative to the site root in {path-config}:

[source,yaml]
----
asciidoctor:
base_dir: :docdir
safe: unsafe
attributes:
imagesdir: /images
----

With this configuration, all images will be generated into the [path]_images_ directory inside the destination folder.

==== Preserving Generated Images

Since Asciidoctor Diagram writes to the output folder, you have instruct Jekyll not to remove these generated files.
One way to do this is to apply a "`monkeypatch`" to Jekyll.
Add the file [path]_jekyll-ext.rb_ to the [path]__plugins_ folder of your project root (creating the folder if it does not already exist) and populate the file with the following content:

._plugins/jekyll-ext.rb
[source,ruby]
----
class Jekyll::Cleaner
def cleanup!; end
end
----

An alternative to the monkeypath approach is to signal folders that contain generated images in the `keep_files` option in {path-config}:

[source,yaml]
----
keep_files: [images]
asciidoctor:
base_dir: :docdir
safe: unsafe
attributes:
imagesdir: /images
----

== Supplemental AsciiDoc Assets

Expand Down
78 changes: 58 additions & 20 deletions lib/jekyll-asciidoc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ class AsciiDocConverter < Converter

def initialize(config)
# NOTE jekyll-watch reinitializes plugins using a shallow clone of config, so no need to reconfigure
# NOTE configured check only works if asciidoc key is defined as Hash in _config.yml
unless ::Jekyll::AsciiDoc::Configured === (asciidoc_config = (config['asciidoc'] ||= {}))
if ::String === asciidoc_config
::Jekyll.logger.warn('jekyll-asciidoc: The AsciiDoc-related configuration should be defined using a Hash (under the `asciidoc` key) instead of discrete entries.')
Expand Down Expand Up @@ -129,28 +130,39 @@ def initialize(config)

unless ::Jekyll::AsciiDoc::Configured === (asciidoctor_config = (config['asciidoctor'] ||= {}))
asciidoctor_config.replace(asciidoctor_config.each_with_object({}) {|(k, v), h| h[k.to_sym] = v })
case (base_dir = asciidoctor_config[:base_dir])
source = ::File.expand_path(config['source'])
dest = ::File.expand_path(config['destination'])
case (base = asciidoctor_config[:base_dir])
when ':source'
asciidoctor_config[:base_dir] = ::File.expand_path(config['source'])
asciidoctor_config[:base_dir] = source
when ':docdir'
if ::Jekyll::MIN_VERSION_3
asciidoctor_config[:base_dir] = :docdir
else
::Jekyll.logger.warn('jekyll-asciidoc: Using :docdir as value of base_dir option requires Jekyll 3. Falling back to source directory.')
asciidoctor_config[:base_dir] = ::File.expand_path(config['source'])
asciidoctor_config[:base_dir] = source
end
else
asciidoctor_config[:base_dir] = ::File.expand_path(base_dir) if base_dir
base = asciidoctor_config[:base_dir] = ::File.expand_path(base) if base
end
asciidoctor_config[:safe] ||= 'safe'
asciidoctor_config[:attributes] = DEFAULT_ATTRIBUTES
.merge(::Jekyll::AsciiDoc::Utils.compile_attributes(asciidoctor_config[:attributes]))
.merge(IMPLICIT_ATTRIBUTES)
site_attributes = {
'site-root' => ::Dir.pwd,
'site-source' => source,
'site-destination' => dest,
'site-baseurl' => config['baseurl'],
'site-url' => config['url']
}
attrs = asciidoctor_config[:attributes] = ::Jekyll::AsciiDoc::Utils.compile_attributes(
asciidoctor_config[:attributes], site_attributes.merge(IMPLICIT_ATTRIBUTES).merge(DEFAULT_ATTRIBUTES))
if (imagesdir = attrs['imagesdir']) && !attrs.key?('imagesoutdir') && imagesdir.start_with?('/')
attrs['imagesoutdir'] = ::File.join(dest, imagesdir)
end
asciidoctor_config.extend(::Jekyll::AsciiDoc::Configured)
end

@config = config
@docdir = nil
@path_info = nil
@setup = false
end

Expand Down Expand Up @@ -183,37 +195,54 @@ def output_ext(ext)
end

def before_render(document, payload)
record_docdir(document) if ::Jekyll::AsciiDoc::Document === document
record_path_info(document) if ::Jekyll::AsciiDoc::Document === document
end

def after_render(document)
clear_docdir if ::Jekyll::AsciiDoc::Document === document
clear_path_info if ::Jekyll::AsciiDoc::Document === document
end

def record_docdir(document)
@docdir = ::File.dirname(::File.expand_path(document.path, document.site.source))
def record_path_info(document, opts = {})
@path_info = {
'docfile' => (docfile = ::File.join(document.site.source, document.relative_path)),
'docdir' => ::File.dirname(docfile)
}
unless opts[:source_only]
@path_info.update({
'outfile' => (outfile = document.destination(document.site.dest)),
'outdir' => ::File.dirname(outfile)
})
end
end

def clear_docdir
@docdir = nil
def clear_path_info
@path_info = {}
end

def load_header(document)
setup
record_docdir(document) if ::Jekyll::MIN_VERSION_3
record_path_info(document, source_only: true) if ::Jekyll::MIN_VERSION_3
# NOTE merely an optimization; if this doesn't match, the header still gets isolated by the processor
header = document.content.split(HeaderBoundaryRx, 2)[0]
case @config['asciidoc']['processor']
when 'asciidoctor'
# NOTE return instance even if header is empty since attributes may be inherited from config
opts = @config['asciidoctor'].merge(parse_header_only: true)
opts[:base_dir] = @docdir if opts[:base_dir] == :docdir && @docdir
unless @path_info.empty?
if opts[:base_dir] == :docdir
# NOTE this assignment happens inside the processor anyway
opts[:base_dir] = @path_info['docdir']
else
@path_info.delete('docdir')
end
opts[:attributes] = opts[:attributes].merge(@path_info)
end
# NOTE return instance even if header is empty since attributes may be inherited from config
doc = ::Asciidoctor.load(header, opts)
else
::Jekyll.logger.warn(%(jekyll-asciidoc: Unknown AsciiDoc processor: #{@config['asciidoc']['processor']}. Cannot load document header.))
doc = nil
end
clear_docdir if ::Jekyll::MIN_VERSION_3
clear_path_info if ::Jekyll::MIN_VERSION_3
doc
end

Expand All @@ -226,7 +255,15 @@ def convert(content)
case @config['asciidoc']['processor']
when 'asciidoctor'
opts = @config['asciidoctor'].merge(header_footer: standalone)
opts[:base_dir] = @docdir if opts[:base_dir] == :docdir && @docdir
unless @path_info.empty?
if opts[:base_dir] == :docdir
# NOTE this assignment happens inside the processor anyway
opts[:base_dir] = @path_info['docdir']
else
@path_info.delete('docdir')
end
opts[:attributes] = opts[:attributes].merge(@path_info)
end
::Asciidoctor.convert(content, opts)
else
::Jekyll.logger.warn(%(jekyll-asciidoc: Unknown AsciiDoc processor: #{@config['asciidoc']['processor']}. Passing through unparsed content.))
Expand Down Expand Up @@ -333,7 +370,8 @@ module Filters
#
# Returns the HTML formatted String.
def asciidocify(input, doctype = nil)
(@context.registers[:cached_asciidoc_converter] ||= ::Jekyll::AsciiDoc::Utils.get_converter(@context.registers[:site]))
(@context.registers[:cached_asciidoc_converter] ||=
::Jekyll::AsciiDoc::Utils.get_converter(@context.registers[:site]))
.convert(doctype ? %(:doctype: #{doctype}\n#{input}) : input.to_s)
end
end
Expand Down
5 changes: 4 additions & 1 deletion spec/fixtures/relative_includes/about/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

We provide content design services for open source tech companies.

docdir={docdir}
* docfile={docfile}
* docdir={docdir}
* outfile={outfile}
* outdir={outdir}
== Our Team

Expand Down
5 changes: 5 additions & 0 deletions spec/fixtures/root_relative_imagesdir/_config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
gems:
- jekyll-asciidoc
asciidoctor:
attributes:
imagesdir: /images
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@

Lorem ipsum.

docdir={docdir}
* docfile={docfile}
* docdir={docdir}
* outfile={outfile}
* outdir={outdir}
Loading

0 comments on commit 71ed563

Please sign in to comment.