asciidoctor 1.5.8 → 2.0.0.rc.1
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/CHANGELOG.adoc +162 -17
- data/LICENSE +1 -1
- data/README-de.adoc +12 -13
- data/README-fr.adoc +11 -12
- data/README-jp.adoc +11 -12
- data/README-zh_CN.adoc +12 -13
- data/README.adoc +6 -7
- data/asciidoctor.gemspec +19 -24
- data/bin/asciidoctor +5 -4
- data/data/reference/syntax.adoc +283 -0
- data/data/stylesheets/asciidoctor-default.css +56 -52
- data/data/stylesheets/coderay-asciidoctor.css +7 -9
- data/lib/asciidoctor.rb +171 -232
- data/lib/asciidoctor/abstract_block.rb +96 -105
- data/lib/asciidoctor/abstract_node.rb +118 -139
- data/lib/asciidoctor/attribute_list.rb +10 -14
- data/lib/asciidoctor/block.rb +20 -19
- data/lib/asciidoctor/callouts.rb +4 -2
- data/lib/asciidoctor/cli.rb +3 -2
- data/lib/asciidoctor/cli/invoker.rb +14 -21
- data/lib/asciidoctor/cli/options.rb +64 -54
- data/lib/asciidoctor/converter.rb +357 -185
- data/lib/asciidoctor/converter/composite.rb +40 -48
- data/lib/asciidoctor/converter/docbook5.rb +604 -640
- data/lib/asciidoctor/converter/html5.rb +949 -963
- data/lib/asciidoctor/converter/manpage.rb +569 -548
- data/lib/asciidoctor/converter/template.rb +231 -272
- data/lib/asciidoctor/core_ext.rb +5 -18
- data/lib/asciidoctor/core_ext/float/truncate.rb +19 -0
- data/lib/asciidoctor/core_ext/match_data/names.rb +7 -0
- data/lib/asciidoctor/core_ext/nil_or_empty.rb +1 -0
- data/lib/asciidoctor/core_ext/regexp/is_match.rb +4 -2
- data/lib/asciidoctor/document.rb +399 -377
- data/lib/asciidoctor/extensions.rb +72 -140
- data/lib/asciidoctor/helpers.rb +122 -83
- data/lib/asciidoctor/inline.rb +5 -1
- data/lib/asciidoctor/list.rb +13 -11
- data/lib/asciidoctor/logging.rb +17 -16
- data/lib/asciidoctor/parser.rb +390 -423
- data/lib/asciidoctor/path_resolver.rb +10 -5
- data/lib/asciidoctor/reader.rb +286 -263
- data/lib/asciidoctor/rouge_ext.rb +39 -0
- data/lib/asciidoctor/section.rb +9 -8
- data/lib/asciidoctor/stylesheets.rb +19 -37
- data/lib/asciidoctor/substitutors.rb +364 -509
- data/lib/asciidoctor/syntax_highlighter.rb +238 -0
- data/lib/asciidoctor/syntax_highlighter/coderay.rb +87 -0
- data/lib/asciidoctor/syntax_highlighter/highlightjs.rb +26 -0
- data/lib/asciidoctor/syntax_highlighter/html_pipeline.rb +10 -0
- data/lib/asciidoctor/syntax_highlighter/prettify.rb +27 -0
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +149 -0
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +129 -0
- data/lib/asciidoctor/table.rb +73 -66
- data/lib/asciidoctor/timings.rb +4 -2
- data/lib/asciidoctor/version.rb +2 -1
- data/lib/asciidoctor/writer.rb +30 -0
- data/man/asciidoctor.1 +19 -15
- data/man/asciidoctor.adoc +14 -12
- metadata +69 -216
- data/CONTRIBUTING.adoc +0 -185
- data/Gemfile +0 -60
- data/Rakefile +0 -129
- data/bin/asciidoctor-safe +0 -15
- data/features/open_block.feature +0 -92
- data/features/pass_block.feature +0 -66
- data/features/step_definitions.rb +0 -49
- data/features/text_formatting.feature +0 -57
- data/features/xref.feature +0 -1039
- data/lib/asciidoctor/converter/base.rb +0 -59
- data/lib/asciidoctor/converter/docbook45.rb +0 -93
- data/lib/asciidoctor/converter/factory.rb +0 -226
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/concurrent/hash.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/hash/key.rb +0 -4
- data/lib/asciidoctor/core_ext/1.8.7/io/binread.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/io/write.rb +0 -5
- data/lib/asciidoctor/core_ext/1.8.7/string/chr.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/string/limit_bytesize.rb +0 -29
- data/lib/asciidoctor/core_ext/1.8.7/symbol/empty.rb +0 -6
- data/lib/asciidoctor/core_ext/1.8.7/symbol/length.rb +0 -6
- data/lib/asciidoctor/core_ext/string/limit_bytesize.rb +0 -10
- data/test/api_test.rb +0 -1240
- data/test/attribute_list_test.rb +0 -242
- data/test/attributes_test.rb +0 -1623
- data/test/blocks_test.rb +0 -3870
- data/test/converter_test.rb +0 -470
- data/test/document_test.rb +0 -1853
- data/test/extensions_test.rb +0 -1560
- data/test/fixtures/asciidoc_index.txt +0 -521
- data/test/fixtures/basic-docinfo-footer.html +0 -6
- data/test/fixtures/basic-docinfo-footer.xml +0 -8
- data/test/fixtures/basic-docinfo.html +0 -1
- data/test/fixtures/basic-docinfo.xml +0 -4
- data/test/fixtures/basic.asciidoc +0 -5
- data/test/fixtures/chapter-a.adoc +0 -3
- data/test/fixtures/child-include.adoc +0 -5
- data/test/fixtures/circle.svg +0 -9
- data/test/fixtures/custom-backends/erb/html5/block_paragraph.html.erb +0 -6
- data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +0 -6
- data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +0 -1
- data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +0 -3
- data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +0 -5
- data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +0 -6
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +0 -3
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +0 -5
- data/test/fixtures/custom-docinfodir/basic-docinfo.html +0 -1
- data/test/fixtures/custom-docinfodir/docinfo.html +0 -1
- data/test/fixtures/docinfo-footer.html +0 -1
- data/test/fixtures/docinfo-footer.xml +0 -9
- data/test/fixtures/docinfo.html +0 -1
- data/test/fixtures/docinfo.xml +0 -3
- data/test/fixtures/doctime-localtime.adoc +0 -2
- data/test/fixtures/dot.gif +0 -0
- data/test/fixtures/encoding.asciidoc +0 -13
- data/test/fixtures/file-with-missing-include.adoc +0 -1
- data/test/fixtures/grandchild-include.adoc +0 -3
- data/test/fixtures/hello-asciidoctor.pdf +0 -69
- data/test/fixtures/include-file.asciidoc +0 -24
- data/test/fixtures/include-file.jsx +0 -8
- data/test/fixtures/include-file.ml +0 -3
- data/test/fixtures/include-file.xml +0 -5
- data/test/fixtures/lists.adoc +0 -96
- data/test/fixtures/master.adoc +0 -5
- data/test/fixtures/mismatched-end-tag.adoc +0 -7
- data/test/fixtures/other-chapters.adoc +0 -11
- data/test/fixtures/outer-include.adoc +0 -5
- data/test/fixtures/parent-include-restricted.adoc +0 -5
- data/test/fixtures/parent-include.adoc +0 -5
- data/test/fixtures/sample.asciidoc +0 -30
- data/test/fixtures/section-a.adoc +0 -4
- data/test/fixtures/stylesheets/custom.css +0 -3
- data/test/fixtures/subdir/index.adoc +0 -3
- data/test/fixtures/subdir/inner-include.adoc +0 -3
- data/test/fixtures/subdir/middle-include.adoc +0 -5
- data/test/fixtures/subs-docinfo.html +0 -2
- data/test/fixtures/subs.adoc +0 -6
- data/test/fixtures/tagged-class-enclosed.rb +0 -25
- data/test/fixtures/tagged-class.rb +0 -23
- data/test/fixtures/tip.gif +0 -0
- data/test/fixtures/unclosed-tag.adoc +0 -3
- data/test/fixtures/unexpected-end-tag.adoc +0 -4
- data/test/invoker_test.rb +0 -745
- data/test/links_test.rb +0 -855
- data/test/lists_test.rb +0 -5151
- data/test/logger_test.rb +0 -211
- data/test/manpage_test.rb +0 -660
- data/test/options_test.rb +0 -262
- data/test/paragraphs_test.rb +0 -562
- data/test/parser_test.rb +0 -742
- data/test/paths_test.rb +0 -395
- data/test/preamble_test.rb +0 -173
- data/test/reader_test.rb +0 -2161
- data/test/sections_test.rb +0 -3575
- data/test/substitutions_test.rb +0 -2066
- data/test/tables_test.rb +0 -2036
- data/test/test_helper.rb +0 -447
- data/test/text_test.rb +0 -309
@@ -0,0 +1,238 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Asciidoctor
|
3
|
+
# Public: A pluggable adapter for integrating a syntax (aka code) highlighter into AsciiDoc processing.
|
4
|
+
#
|
5
|
+
# There are two types of syntax highlighter adapters. The first performs syntax highlighting during the convert phase.
|
6
|
+
# This adapter type must define a highlight? method that returns true. The companion highlight method will then be
|
7
|
+
# called to handle the :specialcharacters substitution for source blocks. The second assumes syntax highlighting is
|
8
|
+
# performed on the client (e.g., when the HTML document is loaded). This adapter type must define a docinfo? method
|
9
|
+
# that returns true. The companion docinfo method will then be called to insert markup into the output document. The
|
10
|
+
# docinfo functionality is available to both adapter types.
|
11
|
+
#
|
12
|
+
# Asciidoctor provides several built-in adapters, including coderay, pygments, rouge, highlight.js, html-pipeline, and
|
13
|
+
# prettify. Additional adapters can be registered using SyntaxHighlighter.register or by supplying a custom factory.
|
14
|
+
module SyntaxHighlighter
|
15
|
+
# Public: Returns the String name of this syntax highlighter for referencing it in messages and option names.
|
16
|
+
attr_reader :name
|
17
|
+
|
18
|
+
def initialize name, backend = 'html5', opts = {}
|
19
|
+
@name = @pre_class = name
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: Indicates whether this syntax highlighter has docinfo (i.e., markup) to insert into the output document at
|
23
|
+
# the specified location.
|
24
|
+
#
|
25
|
+
# location - The Symbol representing the location slot (:head or :footer).
|
26
|
+
#
|
27
|
+
# Returns a [Boolean] indicating whether the docinfo method should be called for this location.
|
28
|
+
def docinfo? location; end
|
29
|
+
|
30
|
+
# Public: Generates docinfo markup to insert in the output document at the specified location.
|
31
|
+
#
|
32
|
+
# location - The Symbol representing the location slot (:head or :footer).
|
33
|
+
#
|
34
|
+
# Return the [String] markup to insert.
|
35
|
+
def docinfo location
|
36
|
+
raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method since #docinfo? returns true)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Public: Indicates whether highlighting is handled by this syntax highlighter or by the client.
|
40
|
+
#
|
41
|
+
# Returns a [Boolean] indicating whether the highlight method should be used to handle the :specialchars substitution.
|
42
|
+
def highlight?; end
|
43
|
+
|
44
|
+
# Public: Highlights the specified source when this source block is being converted.
|
45
|
+
#
|
46
|
+
# If the source contains callout marks, the caller assumes the source remains on the same lines and no closing tags
|
47
|
+
# are added to the end of each line. If the source gets shifted by one or more lines, this method must return a
|
48
|
+
# tuple containing the highlighted source and the number of lines by which the source was shifted.
|
49
|
+
#
|
50
|
+
# node - The source Block to syntax highlight.
|
51
|
+
# source - The raw source text String of this source block (after preprocessing).
|
52
|
+
# lang - The source language String specified on this block (e.g., ruby).
|
53
|
+
# opts - A Hash of options that configure the syntax highlighting:
|
54
|
+
# :callouts - A Hash of callouts extracted from the source, indexed by line number (1-based) (optional).
|
55
|
+
# :css_mode - The Symbol CSS mode (:class or :inline).
|
56
|
+
# :highlight_lines - A 1-based Array of Integer line numbers to highlight (aka emphasize) (optional).
|
57
|
+
# :number_lines - A Symbol indicating whether lines should be numbered (:table or :inline) (optional).
|
58
|
+
# :start_line_number - The starting Integer (1-based) line number (optional, default: 1).
|
59
|
+
# :style - The String style (aka theme) to use for colorizing the code (optional).
|
60
|
+
#
|
61
|
+
# Returns the highlighted source String or a tuple of the highlighted source String and an Integer line offset.
|
62
|
+
def highlight node, source, lang, opts
|
63
|
+
raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method since #highlight? returns true)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Public: Format the highlighted source for inclusion in an HTML document.
|
67
|
+
#
|
68
|
+
# node - The source Block being processed.
|
69
|
+
# lang - The source language String for this Block (e.g., ruby).
|
70
|
+
# opts - A Hash of options that control syntax highlighting:
|
71
|
+
# :nowrap - A Boolean that indicates whether wrapping should be disabled (optional).
|
72
|
+
#
|
73
|
+
# Returns the highlighted source [String] wrapped in preformatted tags (e.g., pre and code)
|
74
|
+
def format node, lang, opts
|
75
|
+
raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Public: Indicates whether this syntax highlighter wants to write a stylesheet to disk. Only called if both the
|
79
|
+
# linkcss and copycss attributes are set on the document.
|
80
|
+
#
|
81
|
+
# doc - The Document in which this syntax highlighter is being used.
|
82
|
+
#
|
83
|
+
# Returns a [Boolean] indicating whether the write_stylesheet method should be called.
|
84
|
+
def write_stylesheet? doc; end
|
85
|
+
|
86
|
+
# Public: Writes the stylesheet to support the highlighted source(s) to disk.
|
87
|
+
#
|
88
|
+
# doc - The Document in which this syntax highlighter is being used.
|
89
|
+
# to_dir - The absolute String path of the stylesheet output directory.
|
90
|
+
#
|
91
|
+
# Returns nothing.
|
92
|
+
def write_stylesheet doc, to_dir
|
93
|
+
raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method since #write_stylesheet? returns true)
|
94
|
+
end
|
95
|
+
|
96
|
+
private_class_method def self.included into
|
97
|
+
into.extend Config
|
98
|
+
end
|
99
|
+
|
100
|
+
module Config
|
101
|
+
# Public: Statically register the current class in the registry for the specified names.
|
102
|
+
#
|
103
|
+
# Returns nothing.
|
104
|
+
private def register_for *names
|
105
|
+
SyntaxHighlighter.register self, *names
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
module Factory
|
110
|
+
# Public: Associates the syntax highlighter class or object with the specified names.
|
111
|
+
#
|
112
|
+
# Returns nothing.
|
113
|
+
def register syntax_highlighter, *names
|
114
|
+
names.each {|name| registry[name] = syntax_highlighter }
|
115
|
+
end
|
116
|
+
|
117
|
+
# Public: Retrieves the syntax highlighter class or object registered for the specified name.
|
118
|
+
#
|
119
|
+
# name - The String name of the syntax highlighter to retrieve.
|
120
|
+
#
|
121
|
+
# Returns the SyntaxHighlighter Class or Object instance registered for this name.
|
122
|
+
def for name
|
123
|
+
registry[name]
|
124
|
+
end
|
125
|
+
|
126
|
+
# Public: Resolves the name to a syntax highlighter instance, if found in the registry.
|
127
|
+
#
|
128
|
+
# name - The String name of the syntax highlighter to create.
|
129
|
+
# backend - The String name of the backend for which this syntax highlighter is being used (default: 'html5').
|
130
|
+
# opts - A Hash of options providing information about the context in which this syntax highlighter is used:
|
131
|
+
# :doc - The Document for which this syntax highlighter was created.
|
132
|
+
#
|
133
|
+
# Returns a [SyntaxHighlighter] instance for the specified name.
|
134
|
+
def create name, backend = 'html5', opts = {}
|
135
|
+
if (syntax_hl = self.for name)
|
136
|
+
syntax_hl = syntax_hl.new name, backend, opts if ::Class === syntax_hl
|
137
|
+
raise ::NameError, %(#{syntax_hl.class} must specify a value for `name') unless syntax_hl.name
|
138
|
+
syntax_hl
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
private def registry
|
143
|
+
raise ::NotImplementedError, %(#{Factory} subclass #{self.class} must implement the ##{__method__} method)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class CustomFactory
|
148
|
+
include Factory
|
149
|
+
|
150
|
+
def initialize seed_registry = nil
|
151
|
+
@registry = seed_registry || {}
|
152
|
+
end
|
153
|
+
|
154
|
+
private def registry
|
155
|
+
@registry
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
module DefaultFactory
|
160
|
+
include Factory
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
@@registry = {}
|
165
|
+
|
166
|
+
def registry
|
167
|
+
@@registry
|
168
|
+
end
|
169
|
+
|
170
|
+
unless RUBY_ENGINE == 'opal'
|
171
|
+
public
|
172
|
+
|
173
|
+
def register syntax_highlighter, *names
|
174
|
+
@@mutex.owned? ? names.each {|name| @@registry = @@registry.merge name => syntax_highlighter } :
|
175
|
+
@@mutex.synchronize { register syntax_highlighter, *names }
|
176
|
+
end
|
177
|
+
|
178
|
+
# This method will lazy require and register additional built-in implementations, which include coderay,
|
179
|
+
# pygments, rouge, and prettify. Refer to {Factory#for} for parameters and return value.
|
180
|
+
def for name
|
181
|
+
@@registry.fetch name do
|
182
|
+
@@mutex.synchronize do
|
183
|
+
@@registry.fetch name do
|
184
|
+
if (require_path = PROVIDED[name])
|
185
|
+
require require_path
|
186
|
+
@@registry[name]
|
187
|
+
else
|
188
|
+
@@registry = @@registry.merge name => nil
|
189
|
+
nil
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
PROVIDED = {
|
197
|
+
'coderay' => %(#{__dir__}/syntax_highlighter/coderay),
|
198
|
+
'prettify' => %(#{__dir__}/syntax_highlighter/prettify),
|
199
|
+
'pygments' => %(#{__dir__}/syntax_highlighter/pygments),
|
200
|
+
'rouge' => %(#{__dir__}/syntax_highlighter/rouge),
|
201
|
+
}
|
202
|
+
|
203
|
+
private
|
204
|
+
|
205
|
+
@@mutex = ::Mutex.new
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class DefaultFactoryProxy < CustomFactory
|
210
|
+
include DefaultFactory # inserts module into ancestors immediately after superclass
|
211
|
+
|
212
|
+
def for name
|
213
|
+
@registry.fetch(name) { super }
|
214
|
+
end unless RUBY_ENGINE == 'opal'
|
215
|
+
end
|
216
|
+
|
217
|
+
class Base
|
218
|
+
include SyntaxHighlighter
|
219
|
+
|
220
|
+
def format node, lang, opts
|
221
|
+
class_attr_val = opts[:nowrap] ? %(#{@pre_class} highlight nowrap) : %(#{@pre_class} highlight)
|
222
|
+
if (transform = opts[:transform])
|
223
|
+
pre = { 'class' => class_attr_val }
|
224
|
+
code = lang ? { 'data-lang' => lang } : {}
|
225
|
+
transform[pre, code]
|
226
|
+
%(<pre#{pre.map {|k, v| %[ #{k}="#{v}"] }.join}><code#{code.map {|k, v| %[ #{k}="#{v}"] }.join}>#{node.content}</code></pre>)
|
227
|
+
else
|
228
|
+
%(<pre class="#{class_attr_val}"><code#{lang ? %[ data-lang="#{lang}"] : ''}>#{node.content}</code></pre>)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
extend DefaultFactory # exports static methods
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
require_relative 'syntax_highlighter/highlightjs'
|
238
|
+
require_relative 'syntax_highlighter/html_pipeline' unless RUBY_ENGINE == 'opal'
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Asciidoctor
|
3
|
+
class SyntaxHighlighter::CodeRayAdapter < SyntaxHighlighter::Base
|
4
|
+
register_for 'coderay'
|
5
|
+
|
6
|
+
def initialize *args
|
7
|
+
super
|
8
|
+
@pre_class = 'CodeRay'
|
9
|
+
@requires_stylesheet = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def highlight?
|
13
|
+
library_available?
|
14
|
+
end
|
15
|
+
|
16
|
+
def highlight node, source, lang, opts
|
17
|
+
@requires_stylesheet = true if (css_mode = opts[:css_mode]) == :class
|
18
|
+
# NOTE CodeRay::Duo gracefully falls back to no highlighting if lang isn't recognized
|
19
|
+
highlighted = ::CodeRay::Duo[lang ? lang.to_sym : :text, :html,
|
20
|
+
css: css_mode,
|
21
|
+
line_numbers: (line_numbers = opts[:number_lines]),
|
22
|
+
line_number_start: opts[:start_line_number],
|
23
|
+
line_number_anchors: false,
|
24
|
+
highlight_lines: opts[:highlight_lines],
|
25
|
+
bold_every: false,
|
26
|
+
].highlight source
|
27
|
+
if line_numbers == :table && opts[:callouts]
|
28
|
+
[highlighted, (idx = highlighted.index CodeCellStartTagCs) ? idx + CodeCellStartTagCs.length : nil]
|
29
|
+
else
|
30
|
+
highlighted
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def docinfo? location
|
35
|
+
@requires_stylesheet && location == :footer
|
36
|
+
end
|
37
|
+
|
38
|
+
def docinfo location, doc, opts
|
39
|
+
if opts[:linkcss]
|
40
|
+
%(<link rel="stylesheet" href="#{doc.normalize_web_path stylesheet_basename, (doc.attr 'stylesdir', ''), false}"#{opts[:self_closing_tag_slash]}>)
|
41
|
+
else
|
42
|
+
%(<style>
|
43
|
+
#{read_stylesheet}
|
44
|
+
</style>)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def write_stylesheet? doc
|
49
|
+
@requires_stylesheet
|
50
|
+
end
|
51
|
+
|
52
|
+
def write_stylesheet doc, to_dir
|
53
|
+
::File.write (::File.join to_dir, stylesheet_basename), read_stylesheet, mode: FILE_WRITE_MODE
|
54
|
+
end
|
55
|
+
|
56
|
+
module Loader
|
57
|
+
private
|
58
|
+
|
59
|
+
def library_available?
|
60
|
+
(@@library_status ||= load_library) == :loaded ? true : nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def load_library
|
64
|
+
(defined? ::CodeRay::Duo) ? :loaded : (Helpers.require_library 'coderay', true, :warn).nil? ? :unavailable : :loaded
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module Styles
|
69
|
+
include Loader
|
70
|
+
|
71
|
+
def read_stylesheet
|
72
|
+
@@stylesheet_cache ||= (::File.read (::File.join Stylesheets::STYLESHEETS_DIR, stylesheet_basename), mode: FILE_READ_MODE).rstrip
|
73
|
+
end
|
74
|
+
|
75
|
+
def stylesheet_basename
|
76
|
+
'coderay-asciidoctor.css'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
extend Styles # exports static methods
|
81
|
+
include Loader, Styles # adds methods to instance
|
82
|
+
|
83
|
+
CodeCellStartTagCs = '<td class="code"><pre>'
|
84
|
+
|
85
|
+
private_constant :CodeCellStartTagCs
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Asciidoctor
|
3
|
+
class SyntaxHighlighter::HighlightJsAdapter < SyntaxHighlighter::Base
|
4
|
+
register_for 'highlightjs', 'highlight.js'
|
5
|
+
|
6
|
+
def initialize *args
|
7
|
+
super
|
8
|
+
@name = @pre_class = 'highlightjs'
|
9
|
+
end
|
10
|
+
|
11
|
+
def format node, lang, opts
|
12
|
+
super node, lang, (opts.merge transform: proc {|_, code| code['class'] = %(language-#{lang || 'none'} hljs) } )
|
13
|
+
end
|
14
|
+
|
15
|
+
def docinfo? location
|
16
|
+
location == :footer
|
17
|
+
end
|
18
|
+
|
19
|
+
def docinfo location, doc, opts
|
20
|
+
base_url = doc.attr 'highlightjsdir', %(#{opts[:cdn_base_url]}/highlight.js/#{HIGHLIGHT_JS_VERSION})
|
21
|
+
%(<link rel="stylesheet" href="#{base_url}/styles/#{doc.attr 'highlightjs-theme', 'github'}.min.css"#{opts[:self_closing_tag_slash]}>
|
22
|
+
<script src="#{base_url}/highlight.min.js"></script>
|
23
|
+
<script>hljs.initHighlighting()</script>)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Asciidoctor
|
3
|
+
class SyntaxHighlighter::HtmlPipelineAdapter < SyntaxHighlighter::Base
|
4
|
+
register_for 'html-pipeline'
|
5
|
+
|
6
|
+
def format node, lang, opts
|
7
|
+
%(<pre#{lang ? %[ lang="#{lang}"] : ''}><code>#{node.content}</code></pre>)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Asciidoctor
|
3
|
+
class SyntaxHighlighter::PrettifyAdapter < SyntaxHighlighter::Base
|
4
|
+
register_for 'prettify'
|
5
|
+
|
6
|
+
def initialize *args
|
7
|
+
super
|
8
|
+
@pre_class = 'prettyprint'
|
9
|
+
end
|
10
|
+
|
11
|
+
def format node, lang, opts
|
12
|
+
opts[:transform] = proc {|pre| pre['class'] += %( #{(start = node.attr 'start') ? %[linenums:#{start}] : 'linenums'}) } if node.attr? 'linenums'
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def docinfo? location
|
17
|
+
location == :footer
|
18
|
+
end
|
19
|
+
|
20
|
+
def docinfo location, doc, opts
|
21
|
+
base_url = doc.attr 'prettifydir', %(#{opts[:cdn_base_url]}/prettify/r298)
|
22
|
+
prettify_theme_url = ((prettify_theme = doc.attr 'prettify-theme', 'prettify').start_with? 'http://', 'https://') ? prettify_theme : %(#{base_url}/#{prettify_theme}.min.css)
|
23
|
+
%(<link rel="stylesheet" href="#{prettify_theme_url}"#{opts[:self_closing_tag_slash]}>
|
24
|
+
<script src="#{base_url}/run_prettify.min.js"></script>)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Asciidoctor
|
3
|
+
class SyntaxHighlighter::PygmentsAdapter < SyntaxHighlighter::Base
|
4
|
+
register_for 'pygments'
|
5
|
+
|
6
|
+
def initialize *args
|
7
|
+
super
|
8
|
+
@requires_stylesheet = nil
|
9
|
+
@style = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def highlight?
|
13
|
+
library_available?
|
14
|
+
end
|
15
|
+
|
16
|
+
def highlight node, source, lang, opts
|
17
|
+
lexer = (::Pygments::Lexer.find_by_alias lang) || (::Pygments::Lexer.find_by_mimetype 'text/plain')
|
18
|
+
@requires_stylesheet = true unless (noclasses = opts[:css_mode] != :class)
|
19
|
+
highlight_opts = {
|
20
|
+
classprefix: TOKEN_CLASS_PREFIX,
|
21
|
+
cssclass: WRAPPER_CLASS,
|
22
|
+
nobackground: true,
|
23
|
+
noclasses: noclasses,
|
24
|
+
startinline: lexer.name == 'PHP' && !(node.option? 'mixed'),
|
25
|
+
stripnl: false,
|
26
|
+
style: (@style ||= (style = opts[:style]) && (style_available? style) || DEFAULT_STYLE),
|
27
|
+
}
|
28
|
+
if (highlight_lines = opts[:highlight_lines])
|
29
|
+
highlight_opts[:hl_lines] = highlight_lines.join ' '
|
30
|
+
end
|
31
|
+
if (linenos = opts[:number_lines]) && (highlight_opts[:linenostart] = opts[:start_line_number]) && (highlight_opts[:linenos] = linenos) == :table
|
32
|
+
if (highlighted = lexer.highlight source, options: highlight_opts)
|
33
|
+
highlighted = highlighted.sub StyledLinenoColumnStartTagsRx, LinenoColumnStartTagsCs if noclasses
|
34
|
+
highlighted = highlighted.sub WrapperTagRx, PreTagCs
|
35
|
+
opts[:callouts] ? [highlighted, (idx = highlighted.index CodeCellStartTagCs) ? idx + CodeCellStartTagCs.length : nil] : highlighted
|
36
|
+
else
|
37
|
+
node.sub_specialchars source # handles nil response from ::Pygments::Lexer#highlight
|
38
|
+
end
|
39
|
+
elsif (highlighted = lexer.highlight source, options: highlight_opts)
|
40
|
+
highlighted = highlighted.gsub StyledLinenoSpanTagRx, LinenoSpanTagCs if linenos && noclasses
|
41
|
+
highlighted.sub WrapperTagRx, '\1'
|
42
|
+
else
|
43
|
+
node.sub_specialchars source # handles nil response from ::Pygments::Lexer#highlight
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def format node, lang, opts
|
48
|
+
if opts[:css_mode] != :class && (@style = (style = opts[:style]) && (style_available? style) || DEFAULT_STYLE) &&
|
49
|
+
(pre_style_attr_val = base_style @style)
|
50
|
+
opts[:transform] = proc {|pre| pre['style'] = pre_style_attr_val }
|
51
|
+
end
|
52
|
+
super
|
53
|
+
end
|
54
|
+
|
55
|
+
def docinfo? location
|
56
|
+
@requires_stylesheet && location == :footer
|
57
|
+
end
|
58
|
+
|
59
|
+
def docinfo location, doc, opts
|
60
|
+
if opts[:linkcss]
|
61
|
+
%(<link rel="stylesheet" href="#{doc.normalize_web_path (stylesheet_basename @style), (doc.attr 'stylesdir', ''), false}"#{opts[:self_closing_tag_slash]}>)
|
62
|
+
else
|
63
|
+
%(<style>
|
64
|
+
#{read_stylesheet @style}
|
65
|
+
</style>)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_stylesheet? doc
|
70
|
+
@requires_stylesheet
|
71
|
+
end
|
72
|
+
|
73
|
+
def write_stylesheet doc, to_dir
|
74
|
+
::File.write (::File.join to_dir, (stylesheet_basename @style)), (read_stylesheet @style), mode: FILE_WRITE_MODE
|
75
|
+
end
|
76
|
+
|
77
|
+
module Loader
|
78
|
+
private
|
79
|
+
|
80
|
+
def library_available?
|
81
|
+
(@@library_status ||= load_library) == :loaded ? true : nil
|
82
|
+
end
|
83
|
+
|
84
|
+
def load_library
|
85
|
+
(defined? ::Pygments::Lexer) ? :loaded : (Helpers.require_library 'pygments', 'pygments.rb', :warn).nil? ? :unavailable : :loaded
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
module Styles
|
90
|
+
include Loader
|
91
|
+
|
92
|
+
def read_stylesheet style
|
93
|
+
library_available? ? @@stylesheet_cache[style || DEFAULT_STYLE] || '/* Failed to load Pygments CSS. */' : '/* Pygments CSS disabled because Pygments is not available. */'
|
94
|
+
end
|
95
|
+
|
96
|
+
def stylesheet_basename style
|
97
|
+
%(pygments-#{style || DEFAULT_STYLE}.css)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def base_style style
|
103
|
+
library_available? ? @@base_style_cache[style || DEFAULT_STYLE] : nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def style_available? style
|
107
|
+
(((@@available_styles ||= ::Pygments.styles.to_set).include? style) rescue nil) && style
|
108
|
+
end
|
109
|
+
|
110
|
+
@@base_style_cache = ::Hash.new do |cache, key|
|
111
|
+
if BaseStyleRx =~ @@stylesheet_cache[key]
|
112
|
+
@@base_style_cache = cache.merge key => (style = $1.strip)
|
113
|
+
style
|
114
|
+
end
|
115
|
+
end
|
116
|
+
@@stylesheet_cache = ::Hash.new do |cache, key|
|
117
|
+
if (stylesheet = ::Pygments.css BASE_SELECTOR, classprefix: TOKEN_CLASS_PREFIX, style: key)
|
118
|
+
@@stylesheet_cache = cache.merge key => stylesheet
|
119
|
+
stylesheet
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
DEFAULT_STYLE = 'default'
|
124
|
+
BASE_SELECTOR = 'pre.pygments'
|
125
|
+
TOKEN_CLASS_PREFIX = 'tok-'
|
126
|
+
|
127
|
+
BaseStyleRx = /^#{BASE_SELECTOR.gsub '.', '\\.'} +\{([^}]+?)\}/
|
128
|
+
|
129
|
+
private_constant :BASE_SELECTOR, :TOKEN_CLASS_PREFIX, :BaseStyleRx
|
130
|
+
end
|
131
|
+
|
132
|
+
extend Styles # exports static methods
|
133
|
+
include Loader, Styles # adds methods to instance
|
134
|
+
|
135
|
+
CodeCellStartTagCs = '<td class="code">'
|
136
|
+
LinenoColumnStartTagsCs = '<td class="linenos"><div class="linenodiv"><pre>'
|
137
|
+
LinenoSpanTagCs = '<span class="lineno">\1</span>'
|
138
|
+
PreTagCs = '<pre>\1</pre>'
|
139
|
+
StyledLinenoColumnStartTagsRx = /<td><div class="linenodiv" style="[^"]+?"><pre style="[^"]+?">/
|
140
|
+
StyledLinenoSpanTagRx = %r(<span style="background-color: #f0f0f0; padding: 0 5px 0 5px">( *\d+ )</span>)
|
141
|
+
WRAPPER_CLASS = 'lineno' # doesn't appear in output; Pygments appends "table" to this value to make nested table class
|
142
|
+
# NOTE <pre> has style attribute when pygments-css=style
|
143
|
+
# NOTE <div> has trailing newline when pygments-linenums-mode=table
|
144
|
+
# NOTE initial <span></span> preserves leading blank lines
|
145
|
+
WrapperTagRx = %r(<div class="#{WRAPPER_CLASS}"><pre\b[^>]*?>(.*)</pre></div>\n*)m
|
146
|
+
|
147
|
+
private_constant :CodeCellStartTagCs, :LinenoColumnStartTagsCs, :LinenoSpanTagCs, :PreTagCs, :StyledLinenoColumnStartTagsRx, :StyledLinenoSpanTagRx, :WrapperTagRx, :WRAPPER_CLASS
|
148
|
+
end
|
149
|
+
end
|