jekyll-asciidoc 1.1.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/{LICENSE → LICENSE.adoc} +4 -3
- data/README.adoc +832 -122
- data/Rakefile +10 -1
- data/lib/jekyll-asciidoc.rb +6 -151
- data/lib/jekyll-asciidoc/compat.rb +14 -0
- data/lib/jekyll-asciidoc/converter.rb +218 -0
- data/lib/jekyll-asciidoc/filters.rb +18 -0
- data/lib/jekyll-asciidoc/integrator.rb +119 -0
- data/lib/jekyll-asciidoc/mixins.rb +12 -0
- data/lib/jekyll-asciidoc/utils.rb +86 -0
- data/lib/jekyll-asciidoc/version.rb +1 -1
- metadata +36 -16
data/Rakefile
CHANGED
@@ -2,6 +2,15 @@ require 'rake/clean'
|
|
2
2
|
|
3
3
|
default_tasks = []
|
4
4
|
|
5
|
+
begin
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
8
|
+
t.rspec_opts = ['-c']
|
9
|
+
end
|
10
|
+
default_tasks << :spec
|
11
|
+
rescue LoadError
|
12
|
+
end
|
13
|
+
|
5
14
|
begin
|
6
15
|
require 'bundler/gem_tasks'
|
7
16
|
default_tasks << :build
|
@@ -9,7 +18,7 @@ rescue LoadError
|
|
9
18
|
warn 'jekyll-asciidoc: Bundler is required to build this gem.
|
10
19
|
You can install Bundler using the `gem install` command:
|
11
20
|
|
12
|
-
$ gem install bundler' + %(\n\n)
|
21
|
+
$ [sudo] gem install bundler' + %(\n\n)
|
13
22
|
end
|
14
23
|
|
15
24
|
task :default => default_tasks unless default_tasks.empty?
|
data/lib/jekyll-asciidoc.rb
CHANGED
@@ -1,151 +1,6 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
env=site env-site site-gen=jekyll site-gen-jekyll builder=jekyll builder-jekyll jekyll-version=#{Jekyll::VERSION}
|
8
|
-
)
|
9
|
-
|
10
|
-
safe true
|
11
|
-
|
12
|
-
highlighter_prefix "\n"
|
13
|
-
highlighter_suffix "\n"
|
14
|
-
|
15
|
-
def initialize(config)
|
16
|
-
@config = config
|
17
|
-
config['asciidoc'] ||= 'asciidoctor'
|
18
|
-
asciidoc_ext = (config['asciidoc_ext'] ||= 'asciidoc,adoc,ad')
|
19
|
-
config['asciidoc_ext_re'] = Regexp.new("\.(#{asciidoc_ext.tr ',', '|'})$", Regexp::IGNORECASE)
|
20
|
-
config['asciidoc_page_attribute_prefix'] ||= 'page'
|
21
|
-
unless (asciidoctor_config = (config['asciidoctor'] ||= {})).frozen?
|
22
|
-
# NOTE convert keys to symbols
|
23
|
-
asciidoctor_config.keys.each do |key|
|
24
|
-
asciidoctor_config[key.to_sym] = asciidoctor_config.delete(key)
|
25
|
-
end
|
26
|
-
asciidoctor_config[:safe] ||= 'safe'
|
27
|
-
(asciidoctor_config[:attributes] ||= []).tap do |attributes|
|
28
|
-
attributes.unshift('notitle', 'hardbreaks', 'idprefix', 'idseparator=-', 'linkattrs')
|
29
|
-
attributes.concat(IMPLICIT_ATTRIBUTES)
|
30
|
-
end
|
31
|
-
asciidoctor_config.freeze
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def setup
|
36
|
-
return if @setup
|
37
|
-
@setup = true
|
38
|
-
case @config['asciidoc']
|
39
|
-
when 'asciidoctor'
|
40
|
-
begin
|
41
|
-
require 'asciidoctor' unless defined? ::Asciidoctor
|
42
|
-
rescue LoadError
|
43
|
-
STDERR.puts 'You are missing a library required to convert AsciiDoc files. Please run:'
|
44
|
-
STDERR.puts ' $ [sudo] gem install asciidoctor'
|
45
|
-
raise FatalException.new('Missing dependency: asciidoctor')
|
46
|
-
end
|
47
|
-
else
|
48
|
-
STDERR.puts "Invalid AsciiDoc processor: #{@config['asciidoc']}"
|
49
|
-
STDERR.puts ' Valid options are [ asciidoctor ]'
|
50
|
-
raise FatalException.new("Invalid AsciiDoc processor: #{@config['asciidoc']}")
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def matches(ext)
|
55
|
-
ext =~ @config['asciidoc_ext_re']
|
56
|
-
end
|
57
|
-
|
58
|
-
def output_ext(ext)
|
59
|
-
'.html'
|
60
|
-
end
|
61
|
-
|
62
|
-
def convert(content)
|
63
|
-
setup
|
64
|
-
case @config['asciidoc']
|
65
|
-
when 'asciidoctor'
|
66
|
-
Asciidoctor.convert(content, @config['asciidoctor'])
|
67
|
-
else
|
68
|
-
warn 'Unknown AsciiDoc converter. Passing through raw content.'
|
69
|
-
content
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def load_header(content)
|
74
|
-
setup
|
75
|
-
case @config['asciidoc']
|
76
|
-
when 'asciidoctor'
|
77
|
-
Asciidoctor.load(content, parse_header_only: true)
|
78
|
-
else
|
79
|
-
warn 'Unknown AsciiDoc converter. Cannot load document header.'
|
80
|
-
nil
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
module Generators
|
87
|
-
# Promotes select AsciiDoc attributes to Jekyll front matter
|
88
|
-
class AsciiDocPreprocessor < Generator
|
89
|
-
def generate(site)
|
90
|
-
asciidoc_converter = JEKYLL_MIN_VERSION_3 ?
|
91
|
-
site.find_converter_instance(Jekyll::Converters::AsciiDocConverter) :
|
92
|
-
site.getConverterImpl(Jekyll::Converters::AsciiDocConverter)
|
93
|
-
asciidoc_converter.setup
|
94
|
-
unless (page_attr_prefix = site.config['asciidoc_page_attribute_prefix']).empty?
|
95
|
-
page_attr_prefix = %(#{page_attr_prefix}-)
|
96
|
-
end
|
97
|
-
page_attr_prefix_l = page_attr_prefix.length
|
98
|
-
|
99
|
-
site.pages.each do |page|
|
100
|
-
if asciidoc_converter.matches(page.ext)
|
101
|
-
next unless (doc = asciidoc_converter.load_header(page.content))
|
102
|
-
|
103
|
-
page.data['title'] = doc.doctitle if doc.header?
|
104
|
-
page.data['author'] = doc.author if doc.author
|
105
|
-
|
106
|
-
unless (adoc_front_matter = doc.attributes
|
107
|
-
.select {|name| name.start_with?(page_attr_prefix) }
|
108
|
-
.map {|name, val| %(#{name[page_attr_prefix_l..-1]}: #{val}) }).empty?
|
109
|
-
page.data.update(SafeYAML.load(adoc_front_matter * "\n"))
|
110
|
-
end
|
111
|
-
|
112
|
-
page.data['layout'] = 'default' unless page.data.key? 'layout'
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
(JEKYLL_MIN_VERSION_3 ? site.posts.docs : site.posts).each do |post|
|
117
|
-
if asciidoc_converter.matches(JEKYLL_MIN_VERSION_3 ? post.data['ext'] : post.ext)
|
118
|
-
next unless (doc = asciidoc_converter.load_header(post.content))
|
119
|
-
|
120
|
-
post.data['title'] = doc.doctitle if doc.header?
|
121
|
-
post.data['author'] = doc.author if doc.author
|
122
|
-
post.data['date'] = DateTime.parse(doc.revdate).to_time if doc.attr? 'revdate'
|
123
|
-
|
124
|
-
unless (adoc_front_matter = doc.attributes
|
125
|
-
.select {|name| name.start_with?(page_attr_prefix) }
|
126
|
-
.map {|name, val| %(#{name[page_attr_prefix_l..-1]}: #{val}) }).empty?
|
127
|
-
post.data.update(SafeYAML.load(adoc_front_matter * "\n"))
|
128
|
-
end
|
129
|
-
|
130
|
-
post.data['layout'] = 'post' unless post.data.key? 'layout'
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
module Filters
|
138
|
-
# Convert an AsciiDoc string into HTML output.
|
139
|
-
#
|
140
|
-
# input - The AsciiDoc String to convert.
|
141
|
-
#
|
142
|
-
# Returns the HTML formatted String.
|
143
|
-
def asciidocify(input)
|
144
|
-
site = @context.registers[:site]
|
145
|
-
converter = JEKYLL_MIN_VERSION_3 ?
|
146
|
-
site.find_converter_instance(Jekyll::Converters::AsciiDocConverter) :
|
147
|
-
site.getConverterImpl(Jekyll::Converters::AsciiDocConverter)
|
148
|
-
converter.convert(input)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
1
|
+
require_relative 'jekyll-asciidoc/compat'
|
2
|
+
require_relative 'jekyll-asciidoc/utils'
|
3
|
+
require_relative 'jekyll-asciidoc/mixins'
|
4
|
+
require_relative 'jekyll-asciidoc/converter'
|
5
|
+
require_relative 'jekyll-asciidoc/integrator'
|
6
|
+
require_relative 'jekyll-asciidoc/filters'
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module AsciiDoc
|
3
|
+
Jekyll3Compatible = (::Gem::Version.new ::Jekyll::VERSION) >= (::Gem::Version.new '3.0.0')
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
module Jekyll
|
8
|
+
class Site
|
9
|
+
# Backport {::Jekyll::Site#find_converter_instance} to Jekyll 2.
|
10
|
+
def find_converter_instance klass
|
11
|
+
@converters.find {|candidate| klass === candidate } || raise(%(No Converters found for #{klass}))
|
12
|
+
end unless respond_to? :find_converter_instance
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module AsciiDoc
|
3
|
+
class Converter < ::Jekyll::Converter
|
4
|
+
DefaultAttributes = {
|
5
|
+
'idprefix' => '',
|
6
|
+
'idseparator' => '-',
|
7
|
+
'linkattrs' => '@'
|
8
|
+
}
|
9
|
+
DefaultFileExtensions = %w(asciidoc adoc ad)
|
10
|
+
DefaultPageAttributePrefix = 'page'
|
11
|
+
ImplicitAttributes = {
|
12
|
+
'env' => 'site',
|
13
|
+
'env-site' => '',
|
14
|
+
'site-gen' => 'jekyll',
|
15
|
+
'site-gen-jekyll' => '',
|
16
|
+
'builder' => 'jekyll',
|
17
|
+
'builder-jekyll' => '',
|
18
|
+
'jekyll-version' => ::Jekyll::VERSION
|
19
|
+
}
|
20
|
+
MessageTopic = 'Jekyll AsciiDoc:'
|
21
|
+
StandaloneOptionLine = Utils::StandaloneOptionLine
|
22
|
+
|
23
|
+
HeaderBoundaryRx = /(?<=\p{Graph})#{Utils::NewLine * 2}/
|
24
|
+
|
25
|
+
# Enable plugin when running in safe mode
|
26
|
+
# jekyll-asciidoc gem must also be declared in whitelist
|
27
|
+
safe true
|
28
|
+
|
29
|
+
# highlighter prefix/suffix not used by this plugin; defined only to avoid warning
|
30
|
+
highlighter_prefix nil
|
31
|
+
highlighter_suffix nil
|
32
|
+
|
33
|
+
def initialize config
|
34
|
+
@config = config
|
35
|
+
@logger = ::Jekyll.logger
|
36
|
+
@path_info = nil
|
37
|
+
@setup = false
|
38
|
+
|
39
|
+
# NOTE jekyll-watch reinitializes plugins using a shallow clone of config, so no need to reconfigure
|
40
|
+
# NOTE check for Configured only works if value of key is defined in _config.yml as Hash
|
41
|
+
unless Configured === (asciidoc_config = (config['asciidoc'] ||= {}))
|
42
|
+
if ::String === asciidoc_config
|
43
|
+
@logger.warn MessageTopic, 'The AsciiDoc configuration should be defined as Hash under asciidoc key instead of as discrete entries.'
|
44
|
+
asciidoc_config = config['asciidoc'] = { 'processor' => asciidoc_config }
|
45
|
+
else
|
46
|
+
asciidoc_config['processor'] ||= 'asciidoctor'
|
47
|
+
end
|
48
|
+
old_asciidoc_ext = config.delete 'asciidoc_ext'
|
49
|
+
asciidoc_ext = (asciidoc_config['ext'] ||= (old_asciidoc_ext || (DefaultFileExtensions * ',')))
|
50
|
+
asciidoc_ext_re = asciidoc_config['ext_re'] = /^\.(?:#{asciidoc_ext.tr ',', '|'})$/ix
|
51
|
+
old_page_attr_prefix_def = config.key? 'asciidoc_page_attribute_prefix'
|
52
|
+
old_page_attr_prefix_val = config.delete 'asciidoc_page_attribute_prefix'
|
53
|
+
unless (page_attr_prefix = asciidoc_config['page_attribute_prefix'])
|
54
|
+
page_attr_prefix = old_page_attr_prefix_def ? (old_page_attr_prefix_val || '') :
|
55
|
+
((asciidoc_config.key? 'page_attribute_prefix') ? '' : DefaultPageAttributePrefix)
|
56
|
+
end
|
57
|
+
asciidoc_config['page_attribute_prefix'] = page_attr_prefix.chomp '-'
|
58
|
+
asciidoc_config['require_front_matter_header'] = !!asciidoc_config['require_front_matter_header']
|
59
|
+
asciidoc_config.extend Configured
|
60
|
+
|
61
|
+
begin
|
62
|
+
if (dlg_method = Utils.method :has_yaml_header?) && asciidoc_config['require_front_matter_header']
|
63
|
+
if (::Jekyll::Utils.method dlg_method.name).arity == -1 # not original method
|
64
|
+
::Jekyll::Utils.define_singleton_method dlg_method.name, &dlg_method
|
65
|
+
end
|
66
|
+
else
|
67
|
+
unless (new_method = dlg_method.owner.method :has_front_matter?).respond_to? :curry
|
68
|
+
new_method = new_method.to_proc # Ruby < 2.2
|
69
|
+
end
|
70
|
+
::Jekyll::Utils.define_singleton_method dlg_method.name, new_method.curry[dlg_method][asciidoc_ext_re]
|
71
|
+
end
|
72
|
+
rescue ::NameError; end
|
73
|
+
end
|
74
|
+
|
75
|
+
if (@asciidoc_config = asciidoc_config)['processor'] == 'asciidoctor'
|
76
|
+
unless Configured === (@asciidoctor_config = (config['asciidoctor'] ||= {}))
|
77
|
+
asciidoctor_config = @asciidoctor_config
|
78
|
+
asciidoctor_config.replace Utils.symbolize_keys asciidoctor_config
|
79
|
+
source = ::File.expand_path config['source']
|
80
|
+
dest = ::File.expand_path config['destination']
|
81
|
+
case (base = asciidoctor_config[:base_dir])
|
82
|
+
when ':source'
|
83
|
+
asciidoctor_config[:base_dir] = source
|
84
|
+
when ':docdir'
|
85
|
+
if defined? ::Jekyll::Hooks
|
86
|
+
asciidoctor_config[:base_dir] = :docdir
|
87
|
+
else
|
88
|
+
@logger.warn MessageTopic, 'Using :docdir as value of base_dir option requires Jekyll 3. Falling back to source directory.'
|
89
|
+
asciidoctor_config[:base_dir] = source
|
90
|
+
end
|
91
|
+
else
|
92
|
+
asciidoctor_config[:base_dir] = ::File.expand_path base if base
|
93
|
+
end
|
94
|
+
asciidoctor_config[:safe] ||= 'safe'
|
95
|
+
site_attributes = {
|
96
|
+
'site-root' => ::Dir.pwd,
|
97
|
+
'site-source' => source,
|
98
|
+
'site-destination' => dest,
|
99
|
+
'site-baseurl' => config['baseurl'],
|
100
|
+
'site-url' => config['url']
|
101
|
+
}
|
102
|
+
attrs = asciidoctor_config[:attributes] = Utils.hashify_attributes asciidoctor_config[:attributes],
|
103
|
+
((site_attributes.merge ImplicitAttributes).merge DefaultAttributes)
|
104
|
+
if (imagesdir = attrs['imagesdir']) && !(attrs.key? 'imagesoutdir') && (imagesdir.start_with? '/')
|
105
|
+
attrs['imagesoutdir'] = ::File.join dest, imagesdir
|
106
|
+
end
|
107
|
+
asciidoctor_config.extend Configured
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def setup
|
113
|
+
return self if @setup
|
114
|
+
@setup = true
|
115
|
+
case @asciidoc_config['processor']
|
116
|
+
when 'asciidoctor'
|
117
|
+
begin
|
118
|
+
require 'asciidoctor' unless defined? ::Asciidoctor::VERSION
|
119
|
+
rescue ::LoadError
|
120
|
+
@logger.error MessageTopic, 'You are missing a library required to convert AsciiDoc files. Please install using:'
|
121
|
+
@logger.error '', '$ [sudo] gem install asciidoctor'
|
122
|
+
@logger.abort_with 'Bailing out; missing required dependency: asciidoctor'
|
123
|
+
end
|
124
|
+
else
|
125
|
+
@logger.error MessageTopic, %(Invalid AsciiDoc processor given: #{@asciidoc_config['processor']})
|
126
|
+
@logger.error '', 'Valid options are: asciidoctor'
|
127
|
+
@logger.abort_with 'Bailing out; invalid Asciidoctor processor.'
|
128
|
+
end
|
129
|
+
self
|
130
|
+
end
|
131
|
+
|
132
|
+
def matches ext
|
133
|
+
ext =~ @asciidoc_config['ext_re']
|
134
|
+
end
|
135
|
+
|
136
|
+
def output_ext ext
|
137
|
+
'.html'
|
138
|
+
end
|
139
|
+
|
140
|
+
def before_render document, payload
|
141
|
+
record_path_info document if Document === document
|
142
|
+
end
|
143
|
+
|
144
|
+
def after_render document
|
145
|
+
clear_path_info if Document === document
|
146
|
+
end
|
147
|
+
|
148
|
+
def record_path_info document, opts = {}
|
149
|
+
@path_info = {
|
150
|
+
'docfile' => (docfile = ::File.join document.site.source, document.relative_path),
|
151
|
+
'docdir' => (::File.dirname docfile),
|
152
|
+
'docname' => (::File.basename docfile, (::File.extname docfile))
|
153
|
+
}
|
154
|
+
unless opts[:source_only]
|
155
|
+
@path_info.update({
|
156
|
+
'outfile' => (outfile = document.destination document.site.dest),
|
157
|
+
'outdir' => (::File.dirname outfile),
|
158
|
+
'outpath' => document.url
|
159
|
+
})
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def clear_path_info
|
164
|
+
@path_info = nil
|
165
|
+
end
|
166
|
+
|
167
|
+
def load_header document
|
168
|
+
setup
|
169
|
+
record_path_info document, source_only: true if defined? ::Jekyll::Hooks
|
170
|
+
# NOTE merely an optimization; if this doesn't match, the header still gets isolated by the processor
|
171
|
+
header = (document.content.split HeaderBoundaryRx, 2)[0]
|
172
|
+
case @asciidoc_config['processor']
|
173
|
+
when 'asciidoctor'
|
174
|
+
opts = @asciidoctor_config.merge parse_header_only: true
|
175
|
+
if @path_info
|
176
|
+
if opts[:base_dir] == :docdir
|
177
|
+
opts[:base_dir] = @path_info['docdir'] # NOTE this assignment happens inside the processor anyway
|
178
|
+
else
|
179
|
+
@path_info.delete 'docdir'
|
180
|
+
end
|
181
|
+
opts[:attributes] = opts[:attributes].merge @path_info
|
182
|
+
end
|
183
|
+
# NOTE return instance even if header is empty since attributes may be inherited from config
|
184
|
+
doc = ::Asciidoctor.load header, opts
|
185
|
+
else
|
186
|
+
@logger.warn MessageTopic, %(Unknown AsciiDoc processor: #{@asciidoc_config['processor']}. Cannot load document header.)
|
187
|
+
doc = nil
|
188
|
+
end
|
189
|
+
clear_path_info if defined? ::Jekyll::Hooks
|
190
|
+
doc
|
191
|
+
end
|
192
|
+
|
193
|
+
def convert content
|
194
|
+
return '' if content.nil_or_empty?
|
195
|
+
setup
|
196
|
+
if (standalone = content.start_with? StandaloneOptionLine)
|
197
|
+
content = content[StandaloneOptionLine.length..-1]
|
198
|
+
end
|
199
|
+
case @asciidoc_config['processor']
|
200
|
+
when 'asciidoctor'
|
201
|
+
opts = @asciidoctor_config.merge header_footer: standalone
|
202
|
+
if @path_info
|
203
|
+
if opts[:base_dir] == :docdir
|
204
|
+
opts[:base_dir] = @path_info['docdir'] # NOTE this assignment happens inside the processor anyway
|
205
|
+
else
|
206
|
+
@path_info.delete 'docdir'
|
207
|
+
end
|
208
|
+
opts[:attributes] = opts[:attributes].merge @path_info
|
209
|
+
end
|
210
|
+
::Asciidoctor.convert content, opts
|
211
|
+
else
|
212
|
+
@logger.warn MessageTopic, %(Unknown AsciiDoc processor: #{@asciidoc_config['processor']}. Passing through unparsed content.)
|
213
|
+
content
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module AsciiDoc
|
3
|
+
module Filters
|
4
|
+
# A Liquid filter for converting an AsciiDoc string to HTML.
|
5
|
+
#
|
6
|
+
# input - The AsciiDoc String to convert.
|
7
|
+
# doctype - The target AsciiDoc doctype (optional, default: nil).
|
8
|
+
#
|
9
|
+
# Returns the HTML formatted String.
|
10
|
+
def asciidocify input, doctype = nil
|
11
|
+
(@context.registers[:cached_asciidoc_converter] ||= (Utils.get_converter @context.registers[:site]))
|
12
|
+
.convert(doctype ? %(:doctype: #{doctype}#{Utils::NewLine}#{input}) : (input || ''))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
::Liquid::Template.register_filter Filters
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Jekyll
|
2
|
+
module AsciiDoc
|
3
|
+
# Registers before and after render hooks to set contextual attributes,
|
4
|
+
# promotes eligible AsciiDoc attributes to page variables, and applies
|
5
|
+
# certain page-level settings.
|
6
|
+
class Integrator < ::Jekyll::Generator
|
7
|
+
NewLine = Utils::NewLine
|
8
|
+
StandaloneOptionLine = Utils::StandaloneOptionLine
|
9
|
+
|
10
|
+
# Enable plugin when running in safe mode
|
11
|
+
# jekyll-asciidoc gem must also be declared in whitelist
|
12
|
+
safe true
|
13
|
+
|
14
|
+
def generate site
|
15
|
+
@converter = converter = (Utils.get_converter site).setup
|
16
|
+
|
17
|
+
if defined? ::Jekyll::Hooks
|
18
|
+
before_render_callback = converter.method :before_render
|
19
|
+
after_render_callback = converter.method :after_render
|
20
|
+
[:pages, :documents].each do |collection_name|
|
21
|
+
::Jekyll::Hooks.register collection_name, :pre_render, &before_render_callback
|
22
|
+
::Jekyll::Hooks.register collection_name, :post_render, &after_render_callback
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
unless (@page_attr_prefix = site.config['asciidoc']['page_attribute_prefix']).empty?
|
27
|
+
@page_attr_prefix = %(#{@page_attr_prefix}-)
|
28
|
+
end
|
29
|
+
|
30
|
+
site.pages.select! do |page|
|
31
|
+
(converter.matches page.ext) ? (integrate page) : true
|
32
|
+
end
|
33
|
+
|
34
|
+
# NOTE posts were migrated to a collection named 'posts' in Jekyll 3
|
35
|
+
site.posts.select! do |post|
|
36
|
+
(converter.matches post.ext) ? (integrate post, 'posts') : true
|
37
|
+
end if site.respond_to? :posts=
|
38
|
+
|
39
|
+
site.collections.each do |name, collection|
|
40
|
+
next unless collection.write?
|
41
|
+
collection.docs.select! do |doc|
|
42
|
+
(converter.matches doc.extname) ? (integrate doc, name) : true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if (attrs = site.config['asciidoctor'][:attributes]) &&
|
47
|
+
((attrs['source-highlighter'] || '').chomp '@') == 'pygments' &&
|
48
|
+
((attrs['pygments-css'] || '').chomp '@') != 'style' && (attrs.fetch 'pygments-stylesheet', '')
|
49
|
+
generate_pygments_stylesheet site, attrs
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Integrate the page-related attributes from the AsciiDoc document header
|
54
|
+
# into the data Array of the specified {::Jekyll::Page}, {::Jekyll::Post}
|
55
|
+
# or {::Jekyll::Document}.
|
56
|
+
#
|
57
|
+
# document - the Page, Post or Document instance to integrate.
|
58
|
+
# collection_name - the String name of the collection to which this
|
59
|
+
# document belongs (optional, default: nil).
|
60
|
+
#
|
61
|
+
# Returns a [Boolean] indicating whether the document should be published.
|
62
|
+
def integrate document, collection_name = nil
|
63
|
+
document.extend Document
|
64
|
+
document.content = [%(:#{@page_attr_prefix}layout: _auto), document.content] * NewLine unless document.data.key? 'layout'
|
65
|
+
return unless (doc = @converter.load_header document)
|
66
|
+
|
67
|
+
document.data['title'] = doc.doctitle if doc.header?
|
68
|
+
document.data['author'] = doc.author if doc.author
|
69
|
+
document.data['date'] = (::DateTime.parse doc.revdate).to_time if collection_name == 'posts' && (doc.attr? 'revdate')
|
70
|
+
|
71
|
+
no_prefix = (prefix_size = @page_attr_prefix.length).zero?
|
72
|
+
unless (adoc_header_data = doc.attributes
|
73
|
+
.each_with_object({}) {|(key, val), accum|
|
74
|
+
if no_prefix || ((key.start_with? @page_attr_prefix) && key = key[prefix_size..-1])
|
75
|
+
accum[key] = ::String === val ? (Utils.parse_yaml_value val) : val
|
76
|
+
end
|
77
|
+
}).empty?
|
78
|
+
document.data.update adoc_header_data
|
79
|
+
end
|
80
|
+
|
81
|
+
case document.data['layout']
|
82
|
+
when nil
|
83
|
+
document.content = %(#{StandaloneOptionLine}#{document.content}) unless document.data.key? 'layout'
|
84
|
+
when '', '_auto'
|
85
|
+
layout = collection_name ? (collection_name.chomp 's') : 'page'
|
86
|
+
document.data['layout'] = (document.site.layouts.key? layout) ? layout : 'default'
|
87
|
+
when false
|
88
|
+
document.data.delete 'layout'
|
89
|
+
document.content = %(#{StandaloneOptionLine}#{document.content})
|
90
|
+
end
|
91
|
+
|
92
|
+
document.extend NoLiquid unless document.data['liquid']
|
93
|
+
document.data.fetch 'published', true
|
94
|
+
end
|
95
|
+
|
96
|
+
def generate_pygments_stylesheet site, attrs
|
97
|
+
css_base = site.source
|
98
|
+
unless (css_dir = (attrs['stylesdir'] || '').chomp '@').empty? || (css_dir.start_with? '/')
|
99
|
+
css_dir = %(/#{css_dir})
|
100
|
+
end
|
101
|
+
if (css_name = attrs['pygments-stylesheet']).nil_or_empty?
|
102
|
+
css_name = 'asciidoc-pygments.css'
|
103
|
+
end
|
104
|
+
css_file = ::File.join css_base, css_dir, css_name
|
105
|
+
css_style = (attrs['pygments-style'] || 'vs').chomp '@'
|
106
|
+
css = ::Asciidoctor::Stylesheets.instance.pygments_stylesheet_data css_style
|
107
|
+
# NOTE apply stronger CSS rule for general text color
|
108
|
+
css = css.sub '.listingblock .pygments {', '.listingblock .pygments, .listingblock .pygments code {'
|
109
|
+
if site.static_files.any? {|f| f.path == css_file }
|
110
|
+
::IO.write css_file, css unless css == (::IO.read css_file)
|
111
|
+
else
|
112
|
+
::Asciidoctor::Helpers.mkdir_p ::File.dirname css_file
|
113
|
+
::IO.write css_file, css
|
114
|
+
site.static_files << (::Jekyll::StaticFile.new site, css_base, css_dir, css_name)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|