From 1a9a4cd894417d250312214152891b24ffbba3a0 Mon Sep 17 00:00:00 2001 From: Dan Allen Date: Sat, 4 Jun 2016 00:17:17 -0600 Subject: [PATCH] resolves #82 restructure configuration keys - move AsciiDoc configuration to Hash under asciidoc key - use old keys if new keys aren't specified - add deprecation warning if old structure is detected - chomp trailing hyphen on page_attribute_prefix in initialize - treat nil value for page_attribute_prefix as empty string - use a module to mark initialized configuration - update README to document new keys - explain that the asciidoctor block accepts any option supported by the Asciidoctor API --- README.adoc | 54 +++++++++++++++++++++++--------- lib/jekyll-asciidoc.rb | 70 ++++++++++++++++++++++++++---------------- 2 files changed, 84 insertions(+), 40 deletions(-) diff --git a/README.adoc b/README.adoc index ac08497..414e27d 100644 --- a/README.adoc +++ b/README.adoc @@ -18,6 +18,8 @@ ifdef::env-github[] :tip-caption: :bulb: :warning-caption: :warning: endif::[] +// Aliases: +:path-config: pass:q[[path]___config.yml__] // URIs: :uri-asciidoc: http://asciidoc.org :uri-asciidoctor: http://asciidoctor.org @@ -73,7 +75,7 @@ Then, run the `bundle` command from Bundler to install the gem: Using Bundler:: + -- -Add the `jekyll-asciidoc` plugin gem to your [path]_Gemfile_ +Add the `jekyll-asciidoc` plugin gem to your [path]_Gemfile_: [source,ruby] ---- @@ -94,7 +96,7 @@ If you are not using Bundler for managing Jekyll then install gems manually $ gem install jekyll-asciidoc -And then, add the `jekyll-asciidoc` gem to the list of gems for Jekyll to load in your site's [path]_{empty}_config.yml_ file: +And then, add the `jekyll-asciidoc` gem to the list of gems for Jekyll to load in your site's {path-config} file: [source,yaml] ---- @@ -223,37 +225,59 @@ The `--safe` flag disables third-party plugins such as this one. == Configuration -This section describes the configuration options for this plugin, which are _optional_. +This section describes the configuration options for this plugin, which are all _optional_. + +=== AsciiDoc + +NOTE: Prior to v1.2.0 of this plugin, the configuration options in this section were flat, top-level names (e.g., `asciidoc_ext`). +These names are now deprecated, but still supported. By default, this plugin uses Asciidoctor to convert AsciiDoc files. -Since Asciidoctor is the only option, the default setting is equivalent to the following configuration in [path]_{empty}_config.yml_: +Since Asciidoctor is currently the only option, the default setting is equivalent to the following configuration in {path-config}: [source,yaml] ---- -asciidoc: asciidoctor +asciidoc: + processor: asciidoctor ---- -To tell Jekyll which extensions to recognize as AsciiDoc files, add the following line to your [path]_{empty}_config.yml_: +IMPORTANT: The `asciidoc` block should only appear _once_ inside {path-config}. +If you define any other options that are documented in this section, you should append them to the `asciidoc` block. + +To tell Jekyll which file extensions to match as AsciiDoc files, append the `ext` option to the `asciidoc` block of your {path-config}: [source,yaml] ---- -asciidoc_ext: asciidoc,adoc,ad +asciidoc: + ext: asciidoc,adoc,ad ---- The extensions shown in the previous listing are the default values, so you don't need to specify this option if those defaults are sufficient. AsciiDoc attributes defined in the document header whose names begin with `page-` are promoted to Jekyll front matter. The part of the name after the `page-` prefix is used as the key (e.g., page-layout becomes layout). -If you want to change this attribute prefix, add the following line to your [path]_{empty}_config.yml_: +If you want to change this attribute prefix, append the `page_attribute_prefix` option to the `asciidoc` block of your {path-config}: [source,yaml] ---- -asciidoc_page_attribute_prefix: jekyll +asciidoc: + page_attribute_prefix: jekyll ---- A hyphen is automatically added to the value of this configuration setting if the value is non-empty. -To pass additional attributes to AsciiDoc, or override the default attributes defined in the plugin, add the following lines to your [path]_{empty}_config.yml_: +By default, all eligible AsciiDoc files are processed. +If you only want files containing a front matter header to be processed, add the `require_front_matter_header` option to the `asciidoc` block of your {path-config}: + +[source,yaml] +---- +asciidoc: + require_front_matter_header: true +---- + +=== Asciidoctor + +To pass additional attributes to AsciiDoc, or override the default attributes defined in the plugin, add the following lines to your {path-config}: [source,yaml] ---- @@ -264,12 +288,14 @@ asciidoctor: - pygments-css=style ---- +In addition to `attributes`, you can define any another option key (e.g., `safe`) that is recognized by the http://asciidoctor.org/docs/user-manual/#ruby-api-options[Asciidoctor API]. + === Enabling hard line breaks Many Jekyll users are used to writing in GitHub-flavored Markdown (GFM), which preserves hard line breaks in paragraph content. Asciidoctor supports this feature for AsciiDoc files. (In fact, previous versions of this plugin enabled this behavior by default). -If you want to enable this behavior for AsciiDoc files, add the `hardbreaks-option` attribute to the Asciidoctor attributes configuration in your site's [path]_{empty}_config.yml_ file: +If you want to enable this behavior for AsciiDoc files, add the `hardbreaks-option` attribute to the Asciidoctor attributes configuration in your site's {path-config} file: [source,yaml] ---- @@ -287,7 +313,7 @@ asciidoctor: - hardbreaks-option=@ ---- -If you already have AsciiDoc attributes defined in the [path]_{empty}_config.yml_, the new attribute should be added as a sibling entry in the YAML collection. +If you already have AsciiDoc attributes defined in the {path-config}, the new attribute should be added as a sibling entry in the YAML collection. WARNING: Keep in mind, if you enable hard line breaks, you won't be able to use the http://asciidoctor.org/docs/asciidoc-recommended-practices/#one-sentence-per-line[one sentence-per-line writing technique]. @@ -303,7 +329,7 @@ For Graphviz and PlantUML diagram generation, {uri-graphviz}[Graphviz] must be i Using Bundler:: + -- -Add `asciidoctor-diagram` gem to your [path]_Gemfile_ +Add `asciidoctor-diagram` gem to your [path]_Gemfile_: [source,ruby] ---- @@ -327,7 +353,7 @@ Install gems manually $ gem install asciidoctor-diagram -Then, add the `asciidoctor-diagram` gem to the list of gems for Jekyll to load in your site's [path]_{empty}_config.yml_ file: +Then, add the `asciidoctor-diagram` gem to the list of gems for Jekyll to load in your site's {path-config} file: [source,yaml] ---- diff --git a/lib/jekyll-asciidoc.rb b/lib/jekyll-asciidoc.rb index 914a909..b612595 100644 --- a/lib/jekyll-asciidoc.rb +++ b/lib/jekyll-asciidoc.rb @@ -2,6 +2,7 @@ module Jekyll MIN_VERSION_3 = ::Gem::Version.new(VERSION) >= ::Gem::Version.new('3.0.0') unless defined? MIN_VERSION_3 module AsciiDoc + module Configuration; end module Utils def self.has_front_matter?(delegate_method, asciidoc_ext_re, path) ::File.extname(path) =~ asciidoc_ext_re ? true : delegate_method.call(path) @@ -24,19 +25,35 @@ class AsciiDocConverter < Converter highlighter_suffix %(\n) def initialize(config) - @setup = false - (@config = config)['asciidoc'] ||= 'asciidoctor' - asciidoc_ext = (config['asciidoc_ext'] ||= 'asciidoc,adoc,ad') - asciidoc_ext_re = (config['asciidoc_ext_re'] = /^\.(?:#{asciidoc_ext.tr ',', '|'})$/ix) - config['asciidoc_page_attribute_prefix'] ||= 'page' - unless (asciidoctor_config = (config['asciidoctor'] ||= {})).frozen? + # NOTE jekyll-watch reinitializes plugins using a shallow clone of config, so no need to reconfigure + unless ::Jekyll::AsciiDoc::Configuration === (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.' + asciidoc_config = config['asciidoc'] = { 'processor' => asciidoc_config } + else + asciidoc_config['processor'] ||= 'asciidoctor' + end + old_asciidoc_ext = config.delete('asciidoc_ext') + asciidoc_ext = (asciidoc_config['ext'] ||= (old_asciidoc_ext || 'asciidoc,adoc,ad')) + asciidoc_ext_re = (asciidoc_config['ext_re'] = /^\.(?:#{asciidoc_ext.tr ',', '|'})$/ix) + old_page_attr_prefix_def = config.key?('asciidoc_page_attribute_prefix') + old_page_attr_prefix_val = config.delete('asciidoc_page_attribute_prefix') + unless (page_attr_prefix = asciidoc_config['page_attribute_prefix']) + page_attr_prefix = old_page_attr_prefix_def ? (old_page_attr_prefix_val || '') : + (asciidoc_config.key?('page_attribute_prefix') && '' || 'page') + end + asciidoc_config['page_attribute_prefix'] = page_attr_prefix.chomp('-') + asciidoc_config['require_front_matter_header'] = !!asciidoc_config.fetch('require_front_matter_header', false) + + asciidoctor_config = (config['asciidoctor'] ||= {}) asciidoctor_config.replace(::Hash[asciidoctor_config.map {|key, val| [key.to_sym, val] }]) asciidoctor_config[:safe] ||= 'safe' - (asciidoctor_config[:attributes] ||= []).tap do |attributes| - attributes.unshift('notitle', 'idprefix', 'idseparator=-', 'linkattrs') - attributes.concat(IMPLICIT_ATTRIBUTES) + (asciidoctor_config[:attributes] ||= []).tap do |attrs| + attrs.unshift('notitle', 'idprefix', 'idseparator=-', 'linkattrs') + attrs.concat(IMPLICIT_ATTRIBUTES) end - if ::Jekyll::MIN_VERSION_3 && !config['asciidoc_require_front_matter'] + + if ::Jekyll::MIN_VERSION_3 && !asciidoc_config['require_front_matter'] if (del_method = ::Jekyll::Utils.method(:has_yaml_header?)) unless (new_method = ::Jekyll::AsciiDoc::Utils.method(:has_front_matter?)).respond_to?(:curry) new_method = new_method.to_proc # Ruby < 2.2 @@ -44,14 +61,17 @@ def initialize(config) del_method.owner.define_singleton_method(del_method.name, new_method.curry[del_method][asciidoc_ext_re]) end end - asciidoctor_config.freeze + + asciidoc_config.extend ::Jekyll::AsciiDoc::Configuration end + @config = config + @setup = false end def setup return self if @setup @setup = true - case @config['asciidoc'] + case (processor = @config['asciidoc']['processor']) when 'asciidoctor' begin require 'asciidoctor' unless defined? ::Asciidoctor::VERSION @@ -61,15 +81,15 @@ def setup raise ::FatalException.new('Missing dependency: asciidoctor') end else - STDERR.puts %(Invalid AsciiDoc processor: #{@config['asciidoc']}) + STDERR.puts %(Invalid AsciiDoc processor: #{processor}) STDERR.puts ' Valid options are [ asciidoctor ]' - raise ::FatalException.new(%(Invalid AsciiDoc processor: #{@config['asciidoc']})) + raise ::FatalException.new(%(Invalid AsciiDoc processor: #{processor})) end self end def matches(ext) - ext =~ @config['asciidoc_ext_re'] + ext =~ @config['asciidoc']['ext_re'] end def output_ext(ext) @@ -82,11 +102,11 @@ def convert(content) if (standalone = content.start_with?(STANDALONE_HEADER)) content = content[STANDALONE_HEADER.length..-1] end - case @config['asciidoc'] + case (processor = @config['asciidoc']['processor']) when 'asciidoctor' ::Asciidoctor.convert(content, @config['asciidoctor'].merge(header_footer: standalone)) else - warn 'Unknown AsciiDoc converter. Passing through unparsed content.' + warn %(Unknown AsciiDoc processor: #{processor}. Passing through unparsed content.) content end end @@ -95,19 +115,19 @@ def load_header(content) setup # NOTE merely an optimization; if this doesn't match, the header still gets isolated by the processor header = content.split(HEADER_BOUNDARY_RE, 2)[0] - case @config['asciidoc'] + case (processor = @config['asciidoc']['processor']) when 'asciidoctor' - # NOTE return a document even if header is empty because attributes may be inherited from config + # NOTE return instance even if header is empty since attributes may be inherited from config ::Asciidoctor.load(header, @config['asciidoctor'].merge(parse_header_only: true)) else - warn 'Unknown AsciiDoc converter. Cannot load document header.' + warn %(Unknown AsciiDoc processor: #{processor}. Cannot load document header.) end end end end module Generators - # Promotes select AsciiDoc attributes to Jekyll front matter + # Promotes sanctioned AsciiDoc attributes to Jekyll front matter class AsciiDocPreprocessor < Generator module NoLiquid def render_with_liquid? @@ -122,9 +142,7 @@ def generate(site) @converter = (::Jekyll::MIN_VERSION_3 ? site.find_converter_instance(::Jekyll::Converters::AsciiDocConverter) : site.getConverterImpl(::Jekyll::Converters::AsciiDocConverter)).setup - unless (@page_attr_prefix = site.config['asciidoc_page_attribute_prefix']).empty? - @page_attr_prefix = %(#{@page_attr_prefix.chomp '-'}-) - end + @page_attr_prefix = site.config['asciidoc']['page_attribute_prefix'] site.pages.each do |page| enhance_page(page) if @converter.matches(page.ext) @@ -144,10 +162,10 @@ def enhance_page page, collection = nil page.data['author'] = doc.author if doc.author page.data['date'] = ::DateTime.parse(doc.revdate).to_time if collection == 'posts' && doc.attr?('revdate') - page_attr_prefix_length = @page_attr_prefix.length + page_attr_prefix_len = @page_attr_prefix.length unless (adoc_front_matter = doc.attributes .select {|name| name.start_with?(@page_attr_prefix) } - .map {|name, val| %(#{name[page_attr_prefix_length..-1]}: #{val == '' ? '""' : val}) }).empty? + .map {|name, val| %(#{name[page_attr_prefix_len..-1]}: #{val == '' ? '""' : val}) }).empty? page.data.update(::SafeYAML.load(adoc_front_matter * %(\n))) end