asciidoctor 2.0.12 → 2.0.13
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 +39 -1
- data/LICENSE +1 -1
- data/README-de.adoc +15 -6
- data/README-fr.adoc +14 -8
- data/README-jp.adoc +15 -6
- data/README-zh_CN.adoc +14 -5
- data/README.adoc +128 -124
- data/asciidoctor.gemspec +5 -5
- data/data/locale/attributes-be.adoc +23 -0
- data/data/locale/attributes-it.adoc +4 -4
- data/data/locale/attributes-nl.adoc +6 -6
- data/data/reference/syntax.adoc +14 -7
- data/data/stylesheets/asciidoctor-default.css +1 -4
- data/lib/asciidoctor.rb +2 -2
- data/lib/asciidoctor/abstract_node.rb +1 -1
- data/lib/asciidoctor/attribute_list.rb +5 -5
- data/lib/asciidoctor/cli/options.rb +7 -6
- data/lib/asciidoctor/converter/html5.rb +1 -1
- data/lib/asciidoctor/converter/manpage.rb +49 -27
- data/lib/asciidoctor/document.rb +3 -1
- data/lib/asciidoctor/extensions.rb +0 -2
- data/lib/asciidoctor/helpers.rb +3 -6
- data/lib/asciidoctor/load.rb +2 -2
- data/lib/asciidoctor/parser.rb +8 -5
- data/lib/asciidoctor/reader.rb +7 -7
- data/lib/asciidoctor/syntax_highlighter/pygments.rb +2 -2
- data/lib/asciidoctor/syntax_highlighter/rouge.rb +31 -25
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +7 -7
- data/man/asciidoctor.adoc +3 -3
- metadata +14 -13
data/asciidoctor.gemspec
CHANGED
|
@@ -34,21 +34,21 @@ Gem::Specification.new do |s|
|
|
|
34
34
|
#s.test_files = files.grep %r/^(?:features|test)\/.+$/
|
|
35
35
|
|
|
36
36
|
# asciimath is needed for testing AsciiMath in DocBook backend
|
|
37
|
-
s.add_development_dependency 'asciimath', '~>
|
|
37
|
+
s.add_development_dependency 'asciimath', '~> 2.0.0'
|
|
38
38
|
# coderay is needed for testing syntax highlighting
|
|
39
39
|
s.add_development_dependency 'coderay', '~> 1.1.0'
|
|
40
40
|
# concurrent-ruby, haml, slim, and tilt are needed for testing custom templates
|
|
41
41
|
s.add_development_dependency 'concurrent-ruby', '~> 1.1.0'
|
|
42
42
|
s.add_development_dependency 'cucumber', '~> 3.1.0'
|
|
43
43
|
# erubi is needed for testing alternate eRuby impls
|
|
44
|
-
s.add_development_dependency 'erubi', '~> 1.
|
|
45
|
-
s.add_development_dependency 'haml', '~> 5.
|
|
44
|
+
s.add_development_dependency 'erubi', '~> 1.10.0'
|
|
45
|
+
s.add_development_dependency 'haml', '~> 5.2.0'
|
|
46
46
|
s.add_development_dependency 'minitest', '~> 5.11.0'
|
|
47
47
|
s.add_development_dependency 'nokogiri', '~> 1.10.0'
|
|
48
48
|
s.add_development_dependency 'rake', '~> 12.3.0'
|
|
49
49
|
# Asciidoctor supports Rouge >= 2
|
|
50
|
-
s.add_development_dependency 'rouge', '~> 3.
|
|
50
|
+
s.add_development_dependency 'rouge', '~> 3.26.0'
|
|
51
51
|
s.add_development_dependency 'rspec-expectations', '~> 3.8.0'
|
|
52
|
-
s.add_development_dependency 'slim', '~> 4.
|
|
52
|
+
s.add_development_dependency 'slim', '~> 4.1.0'
|
|
53
53
|
s.add_development_dependency 'tilt', '~> 2.0.0'
|
|
54
54
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Belarusian translation, courtesy of Dexter Morganov <dexter.morganov@gmail.com>
|
|
2
|
+
:appendix-caption: Дадатак
|
|
3
|
+
:appendix-refsig: {appendix-caption}
|
|
4
|
+
:caution-caption: Увага
|
|
5
|
+
:chapter-signifier: Глава
|
|
6
|
+
:chapter-refsig: {chapter-signifier}
|
|
7
|
+
:example-caption: Прыклад
|
|
8
|
+
:figure-caption: Малюнак
|
|
9
|
+
:important-caption: Важна
|
|
10
|
+
:last-update-label: Апошняе абнаўленне
|
|
11
|
+
ifdef::listing-caption[:listing-caption: Лістынг]
|
|
12
|
+
ifdef::manname-title[:manname-title: Назва]
|
|
13
|
+
:note-caption: Заўвага
|
|
14
|
+
:part-signifier: Частка
|
|
15
|
+
:part-refsig: {part-signifier}
|
|
16
|
+
ifdef::preface-title[:preface-title: Прадмова]
|
|
17
|
+
:section-refsig: Раздзел
|
|
18
|
+
:table-caption: Табліца
|
|
19
|
+
:tip-caption: Падказка
|
|
20
|
+
:toc-title: Змест
|
|
21
|
+
:untitled-label: Без назвы
|
|
22
|
+
:version-label: Версія
|
|
23
|
+
:warning-caption: Папярэджанне
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Italian translation, courtesy of Marco Ciampa <ciampix@
|
|
1
|
+
// Italian translation, courtesy of Marco Ciampa <ciampix@posteo.net>
|
|
2
2
|
:appendix-caption: Appendice
|
|
3
3
|
:appendix-refsig: {appendix-caption}
|
|
4
4
|
:caution-caption: Attenzione
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
ifdef::listing-caption[:listing-caption: Elenco]
|
|
12
12
|
ifdef::manname-title[:manname-title: Nome]
|
|
13
13
|
:note-caption: Nota
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
:part-signifier: Parte
|
|
15
|
+
:part-refsig: {part-signifier}
|
|
16
16
|
ifdef::preface-title[:preface-title: Prefazione]
|
|
17
|
-
|
|
17
|
+
:section-refsig: Sezione
|
|
18
18
|
:table-caption: Tabella
|
|
19
19
|
:tip-caption: Suggerimento
|
|
20
20
|
:toc-title: Indice
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
:appendix-caption: Bijlage
|
|
3
3
|
:appendix-refsig: {appendix-caption}
|
|
4
4
|
:caution-caption: Opgelet
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
:chapter-signifier: Hoofdstuk
|
|
6
|
+
:chapter-refsig: {chapter-signifier}
|
|
7
7
|
:example-caption: Voorbeeld
|
|
8
8
|
:figure-caption: Figuur
|
|
9
9
|
:important-caption: Belangrijk
|
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
ifdef::listing-caption[:listing-caption: Lijst]
|
|
12
12
|
ifdef::manname-title[:manname-title: Naam]
|
|
13
13
|
:note-caption: Noot
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
:part-signifier: Deel
|
|
15
|
+
:part-refsig: {part-signifier}
|
|
16
16
|
ifdef::preface-title[:preface-title: Inleiding]
|
|
17
|
-
|
|
17
|
+
:section-refsig: Paragraaf
|
|
18
18
|
:table-caption: Tabel
|
|
19
19
|
:tip-caption: Tip
|
|
20
|
-
:toc-title:
|
|
20
|
+
:toc-title: Inhoudsopgave
|
|
21
21
|
:untitled-label: Naamloos
|
|
22
22
|
:version-label: Versie
|
|
23
23
|
:warning-caption: Waarschuwing
|
data/data/reference/syntax.adoc
CHANGED
|
@@ -17,7 +17,7 @@ Line breaks are not preserved.
|
|
|
17
17
|
A blank line separates paragraphs.
|
|
18
18
|
|
|
19
19
|
[%hardbreaks]
|
|
20
|
-
This paragraph
|
|
20
|
+
This paragraph is marked with the `hardbreaks` option.
|
|
21
21
|
Notice how line breaks are now preserved.
|
|
22
22
|
|
|
23
23
|
An indented (literal) paragraph disables text formatting,
|
|
@@ -25,14 +25,14 @@ Notice how line breaks are now preserved.
|
|
|
25
25
|
monospaced font.
|
|
26
26
|
|
|
27
27
|
[sidebar#id.role]
|
|
28
|
-
|
|
28
|
+
Adding a style, ID, and/or role gives a paragraph (or block) special meaning, like this sidebar.
|
|
29
29
|
|
|
30
30
|
NOTE: An admonition paragraph, like this note, grabs the reader's attention.
|
|
31
31
|
|
|
32
32
|
TIP: Convert this document using the `asciidoctor` command to see the output produced from it.
|
|
33
33
|
|
|
34
34
|
== Text Formatting
|
|
35
|
-
:hardbreaks:
|
|
35
|
+
:hardbreaks-option:
|
|
36
36
|
|
|
37
37
|
.Constrained (applied at word boundaries)
|
|
38
38
|
*strong importance* (aka bold)
|
|
@@ -41,17 +41,24 @@ _stress emphasis_ (aka italic)
|
|
|
41
41
|
"`double`" and '`single`' typographic quotes
|
|
42
42
|
+passthrough text+ (substitutions disabled)
|
|
43
43
|
`+literal text+` (monospaced with substitutions disabled)
|
|
44
|
+
a #mark# to remember (highlighted for notation)
|
|
44
45
|
|
|
45
46
|
.Unconstrained (applied anywhere)
|
|
46
|
-
**C**reate
|
|
47
|
+
**C**reate, **R**ead, **U**pdate, and **D**elete (CRUD)
|
|
47
48
|
fan__freakin__tastic
|
|
48
49
|
``mono``culture
|
|
50
|
+
##mark##up your text
|
|
49
51
|
|
|
50
52
|
.Replacements
|
|
51
53
|
A long time ago in a galaxy far, far away...
|
|
52
54
|
(C) 1976 Arty Artisan
|
|
53
55
|
I believe I shall--no, actually I won't.
|
|
54
56
|
|
|
57
|
+
.ID and roles for phrases
|
|
58
|
+
[.line-through]#delete me#
|
|
59
|
+
the [.path]_images_ directory
|
|
60
|
+
a [#wibble.term]*wibble* does wobble
|
|
61
|
+
|
|
55
62
|
.Macros
|
|
56
63
|
// where c=specialchars, q=quotes, a=attributes, r=replacements, m=macros, p=post_replacements, etc.
|
|
57
64
|
The European icon:flag[role=blue] is blue & contains pass:[************] arranged in a icon:circle-o[role=yellow].
|
|
@@ -60,7 +67,7 @@ Since `pass:[++]` has strong priority in AsciiDoc, you can rewrite pass:c,a,r[C+
|
|
|
60
67
|
// activate stem support by adding `:stem:` to the document header
|
|
61
68
|
stem:[sqrt(4) = 2]
|
|
62
69
|
|
|
63
|
-
:!hardbreaks:
|
|
70
|
+
:!hardbreaks-option:
|
|
64
71
|
== Attributes
|
|
65
72
|
|
|
66
73
|
// define attributes in the document header; must be flush with left margin
|
|
@@ -242,7 +249,7 @@ comment - content which is not included in the output document
|
|
|
242
249
|
== Tables
|
|
243
250
|
|
|
244
251
|
.Table Attributes
|
|
245
|
-
[cols=>1h;2d,width=50%,frame=
|
|
252
|
+
[cols=>1h;2d,width=50%,frame=ends]
|
|
246
253
|
|===
|
|
247
254
|
| Attribute Name | Values
|
|
248
255
|
|
|
@@ -256,7 +263,7 @@ comment - content which is not included in the output document
|
|
|
256
263
|
| all \| cols \| rows \| none
|
|
257
264
|
|
|
258
265
|
| frame
|
|
259
|
-
| all \| sides \|
|
|
266
|
+
| all \| sides \| ends \| none
|
|
260
267
|
|
|
261
268
|
| stripes
|
|
262
269
|
| all \| even \| odd \| none
|
|
@@ -84,9 +84,6 @@ dl dd{margin-bottom:1.25em}
|
|
|
84
84
|
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
|
|
85
85
|
abbr{text-transform:none}
|
|
86
86
|
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
|
87
|
-
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
|
|
88
|
-
blockquote cite::before{content:"\2014 \0020"}
|
|
89
|
-
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
|
|
90
87
|
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
|
91
88
|
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
|
92
89
|
h1{font-size:2.75em}
|
|
@@ -251,7 +248,7 @@ pre.pygments .lineno::before{content:"";margin-right:-.125em}
|
|
|
251
248
|
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
|
252
249
|
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
|
|
253
250
|
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
|
254
|
-
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;text-align:left;margin-right:0}
|
|
251
|
+
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
|
|
255
252
|
p.tableblock:last-child{margin-bottom:0}
|
|
256
253
|
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
|
|
257
254
|
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
|
data/lib/asciidoctor.rb
CHANGED
|
@@ -136,8 +136,8 @@ module Asciidoctor
|
|
|
136
136
|
# Compliance value: true
|
|
137
137
|
define :underline_style_section_titles, true
|
|
138
138
|
|
|
139
|
-
# Asciidoctor will unwrap the content in a preamble
|
|
140
|
-
#
|
|
139
|
+
# Asciidoctor will unwrap the content in a preamble if the document has a
|
|
140
|
+
# title and no sections, then discard the empty preamble.
|
|
141
141
|
# Compliance value: false
|
|
142
142
|
define :unwrap_standalone_preamble, true
|
|
143
143
|
|
|
@@ -216,7 +216,7 @@ class AbstractNode
|
|
|
216
216
|
(val = @attributes['role']) ? (%( #{val} ).include? %( #{name} )) : false
|
|
217
217
|
end
|
|
218
218
|
|
|
219
|
-
# Public: Sets the value of the role attribute on this
|
|
219
|
+
# Public: Sets the value of the role attribute on this node.
|
|
220
220
|
#
|
|
221
221
|
# names - A single role name, a space-separated String of role names, or an Array of role names
|
|
222
222
|
#
|
|
@@ -27,7 +27,7 @@ class AttributeList
|
|
|
27
27
|
QUOT = '"'
|
|
28
28
|
|
|
29
29
|
# Public: Regular expressions for detecting the boundary of a value
|
|
30
|
-
|
|
30
|
+
BoundaryRx = {
|
|
31
31
|
QUOT => /.*?[^\\](?=")/,
|
|
32
32
|
APOS => /.*?[^\\](?=')/,
|
|
33
33
|
',' => /.*?(?=[ \t]*(,|$))/
|
|
@@ -46,7 +46,7 @@ class AttributeList
|
|
|
46
46
|
BlankRx = /[ \t]+/
|
|
47
47
|
|
|
48
48
|
# Public: Regular expressions for skipping delimiters
|
|
49
|
-
|
|
49
|
+
SkipRx = {
|
|
50
50
|
',' => /[ \t]*(,|$)/
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -54,8 +54,8 @@ class AttributeList
|
|
|
54
54
|
@scanner = ::StringScanner.new source
|
|
55
55
|
@block = block
|
|
56
56
|
@delimiter = delimiter
|
|
57
|
-
@delimiter_skip_pattern =
|
|
58
|
-
@delimiter_boundary_pattern =
|
|
57
|
+
@delimiter_skip_pattern = SkipRx[delimiter]
|
|
58
|
+
@delimiter_boundary_pattern = BoundaryRx[delimiter]
|
|
59
59
|
@attributes = nil
|
|
60
60
|
end
|
|
61
61
|
|
|
@@ -214,7 +214,7 @@ class AttributeList
|
|
|
214
214
|
end
|
|
215
215
|
|
|
216
216
|
def scan_to_quote quote
|
|
217
|
-
@scanner.scan
|
|
217
|
+
@scanner.scan BoundaryRx[quote]
|
|
218
218
|
end
|
|
219
219
|
end
|
|
220
220
|
end
|
|
@@ -39,14 +39,15 @@ module Asciidoctor
|
|
|
39
39
|
# NOTE don't use squiggly heredoc to maintain compatibility with Ruby < 2.3
|
|
40
40
|
opts.banner = <<-'EOS'.gsub ' ', ''
|
|
41
41
|
Usage: asciidoctor [OPTION]... FILE...
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
Convert the AsciiDoc input FILE(s) to the backend output format (e.g., HTML 5, DocBook 5, etc.)
|
|
43
|
+
Unless specified otherwise, the output is written to a file whose name is derived from the input file.
|
|
44
|
+
Application log messages are printed to STDERR.
|
|
45
|
+
Example: asciidoctor input.adoc
|
|
45
46
|
|
|
46
47
|
EOS
|
|
47
48
|
|
|
48
|
-
opts.on('-b', '--backend BACKEND', 'set output format
|
|
49
|
-
'additional backends are supported via
|
|
49
|
+
opts.on('-b', '--backend BACKEND', 'set backend output format: [html5, xhtml5, docbook5, manpage] (default: html5)',
|
|
50
|
+
'additional backends are supported via extended converters (e.g., pdf, epub3)') do |backend|
|
|
50
51
|
self[:attributes]['backend'] = backend
|
|
51
52
|
end
|
|
52
53
|
opts.on('-d', '--doctype DOCTYPE', ['article', 'book', 'manpage', 'inline'],
|
|
@@ -128,7 +129,7 @@ module Asciidoctor
|
|
|
128
129
|
opts.on('--trace', 'include backtrace information when reporting errors (default: false)') do |trace|
|
|
129
130
|
self[:trace] = true
|
|
130
131
|
end
|
|
131
|
-
opts.on('-v', '--verbose', '
|
|
132
|
+
opts.on('-v', '--verbose', 'directs application messages logged at DEBUG or INFO level to STDERR (default: false)') do |verbose|
|
|
132
133
|
self[:verbose] = 2
|
|
133
134
|
end
|
|
134
135
|
opts.on('-w', '--warnings', 'turn on script warnings (default: false)') do |warnings|
|
|
@@ -1310,7 +1310,7 @@ Your browser does not support the video tag.
|
|
|
1310
1310
|
manname_id_attr = (manname_id = node.attr 'manname-id') ? %( id="#{manname_id}") : ''
|
|
1311
1311
|
%(<h2#{manname_id_attr}>#{manname_title}</h2>
|
|
1312
1312
|
<div class="sectionbody">
|
|
1313
|
-
<p>#{node.attr '
|
|
1313
|
+
<p>#{(node.attr 'mannames').join ', '} - #{node.attr 'manpurpose'}</p>
|
|
1314
1314
|
</div>)
|
|
1315
1315
|
end
|
|
1316
1316
|
|
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
module Asciidoctor
|
|
3
3
|
# A built-in {Converter} implementation that generates the man page (troff) format.
|
|
4
4
|
#
|
|
5
|
-
# The output
|
|
6
|
-
#
|
|
5
|
+
# The output of this converter adheres to the man definition as defined by
|
|
6
|
+
# groff and uses the manpage output of the DocBook toolchain as a foundation.
|
|
7
|
+
# That means if you've previously been generating man pages using the a2x tool
|
|
8
|
+
# from AsciiDoc Python, you should be able to achieve a very similar result
|
|
9
|
+
# using this converter. Though you'll also get to enjoy some notable
|
|
10
|
+
# enhancements that have been added since, such as the customizable linkstyle.
|
|
7
11
|
#
|
|
8
12
|
# See http://www.gnu.org/software/groff/manual/html_node/Man-usage.html#Man-usage
|
|
9
13
|
class Converter::ManPageConverter < Converter::Base
|
|
@@ -18,10 +22,13 @@ class Converter::ManPageConverter < Converter::Base
|
|
|
18
22
|
LiteralBackslashRx = /\A\\|(#{ESC})?\\/
|
|
19
23
|
LeadingPeriodRx = /^\./
|
|
20
24
|
EscapedMacroRx = /^(?:#{ESC}\\c\n)?#{ESC}\.((?:URL|MTO) "#{CC_ANY}*?" "#{CC_ANY}*?" )( |[^\s]*)(#{CC_ANY}*?)(?: *#{ESC}\\c)?$/
|
|
21
|
-
|
|
25
|
+
MalformedEscapedMacroRx = /(#{ESC}\\c) (#{ESC}\.(?:URL|MTO) )/
|
|
26
|
+
MockMacroRx = /<\/?(#{ESC}\\[^>]+)>/
|
|
22
27
|
EmDashCharRefRx = /—(?:​)?/
|
|
23
28
|
EllipsisCharRefRx = /…(?:​)?/
|
|
24
29
|
WrappedIndentRx = /#{CG_BLANK}*#{LF}#{CG_BLANK}*/
|
|
30
|
+
XMLMarkupRx = /&#?[a-z\d]+;|</
|
|
31
|
+
PCDATAFilterRx = /(&#?[a-z\d]+;|<[^>]+>)|([^&<]+)/
|
|
25
32
|
|
|
26
33
|
def initialize backend, opts = {}
|
|
27
34
|
@backend = backend
|
|
@@ -91,17 +98,14 @@ class Converter::ManPageConverter < Converter::Base
|
|
|
91
98
|
if node.attr? 'manpurpose'
|
|
92
99
|
mannames = node.attr 'mannames', [manname]
|
|
93
100
|
result << %(.SH "#{(node.attr 'manname-title', 'NAME').upcase}"
|
|
94
|
-
#{mannames.map {|n| manify n }.join ', '} \\- #{manify node.attr('manpurpose'), whitespace: :normalize})
|
|
101
|
+
#{mannames.map {|n| (manify n).gsub '\-', '-' }.join ', '} \\- #{manify node.attr('manpurpose'), whitespace: :normalize})
|
|
95
102
|
end
|
|
96
103
|
end
|
|
97
104
|
|
|
98
105
|
result << node.content
|
|
99
106
|
|
|
100
107
|
# QUESTION should NOTES come after AUTHOR(S)?
|
|
101
|
-
|
|
102
|
-
result << '.SH "NOTES"'
|
|
103
|
-
result.concat(node.footnotes.map {|fn| %(#{fn.index}. #{fn.text}) })
|
|
104
|
-
end
|
|
108
|
+
append_footnotes result, node
|
|
105
109
|
|
|
106
110
|
unless (authors = node.authors).empty?
|
|
107
111
|
if authors.size > 1
|
|
@@ -124,10 +128,7 @@ class Converter::ManPageConverter < Converter::Base
|
|
|
124
128
|
def convert_embedded node
|
|
125
129
|
result = [node.content]
|
|
126
130
|
|
|
127
|
-
|
|
128
|
-
result << '.SH "NOTES"'
|
|
129
|
-
result.concat(node.footnotes.map {|fn| %(#{fn.index}. #{fn.text}) })
|
|
130
|
-
end
|
|
131
|
+
append_footnotes result, node
|
|
131
132
|
|
|
132
133
|
# QUESTION should we add an AUTHOR(S) section?
|
|
133
134
|
|
|
@@ -142,7 +143,7 @@ class Converter::ManPageConverter < Converter::Base
|
|
|
142
143
|
stitle = node.captioned_title
|
|
143
144
|
else
|
|
144
145
|
macro = 'SH'
|
|
145
|
-
stitle = node.title
|
|
146
|
+
stitle = uppercase_pcdata node.title
|
|
146
147
|
end
|
|
147
148
|
result << %(.#{macro} "#{manify stitle}"
|
|
148
149
|
#{node.content})
|
|
@@ -315,8 +316,9 @@ r lw(\n(.lu*75u/100u).'
|
|
|
315
316
|
end
|
|
316
317
|
end
|
|
317
318
|
|
|
318
|
-
|
|
319
|
-
|
|
319
|
+
def convert_page_break node
|
|
320
|
+
'.bp'
|
|
321
|
+
end
|
|
320
322
|
|
|
321
323
|
def convert_paragraph node
|
|
322
324
|
if node.title?
|
|
@@ -531,12 +533,13 @@ allbox tab(:);'
|
|
|
531
533
|
result.join LF
|
|
532
534
|
end
|
|
533
535
|
|
|
534
|
-
# FIXME git uses [verse] for the synopsis; detect this special case
|
|
535
536
|
def convert_verse node
|
|
536
537
|
result = []
|
|
537
|
-
|
|
538
|
+
if node.title?
|
|
539
|
+
result << %(.sp
|
|
538
540
|
.B #{manify node.title}
|
|
539
|
-
.br)
|
|
541
|
+
.br)
|
|
542
|
+
end
|
|
540
543
|
attribution_line = (node.attr? 'citetitle') ? %(#{node.attr 'citetitle'} ) : nil
|
|
541
544
|
attribution_line = (node.attr? 'attribution') ? %[#{attribution_line}\\(em #{node.attr 'attribution'}] : nil
|
|
542
545
|
result << %(.sp
|
|
@@ -609,7 +612,6 @@ allbox tab(:);'
|
|
|
609
612
|
%(#{ESC_BS}fB(#{node.text})#{ESC_BS}fP)
|
|
610
613
|
end
|
|
611
614
|
|
|
612
|
-
# TODO supposedly groff has footnotes, but we're in search of an example
|
|
613
615
|
def convert_inline_footnote node
|
|
614
616
|
if (index = node.attr 'index')
|
|
615
617
|
%([#{index}])
|
|
@@ -647,19 +649,19 @@ allbox tab(:);'
|
|
|
647
649
|
end
|
|
648
650
|
end
|
|
649
651
|
|
|
650
|
-
# NOTE use fake
|
|
652
|
+
# NOTE use fake XML elements to prevent creating artificial word boundaries
|
|
651
653
|
def convert_inline_quoted node
|
|
652
654
|
case node.type
|
|
653
655
|
when :emphasis
|
|
654
|
-
%(
|
|
656
|
+
%(<#{ESC_BS}fI>#{node.text}</#{ESC_BS}fP>)
|
|
655
657
|
when :strong
|
|
656
|
-
%(
|
|
658
|
+
%(<#{ESC_BS}fB>#{node.text}</#{ESC_BS}fP>)
|
|
657
659
|
when :monospaced
|
|
658
|
-
%[
|
|
660
|
+
%[<#{ESC_BS}f(CR>#{node.text}</#{ESC_BS}fP>]
|
|
659
661
|
when :single
|
|
660
|
-
%[
|
|
662
|
+
%[<#{ESC_BS}(oq>#{node.text}</#{ESC_BS}(cq>]
|
|
661
663
|
when :double
|
|
662
|
-
%[
|
|
664
|
+
%[<#{ESC_BS}(lq>#{node.text}</#{ESC_BS}(rq>]
|
|
663
665
|
else
|
|
664
666
|
node.text
|
|
665
667
|
end
|
|
@@ -678,6 +680,22 @@ allbox tab(:);'
|
|
|
678
680
|
|
|
679
681
|
private
|
|
680
682
|
|
|
683
|
+
def append_footnotes result, node
|
|
684
|
+
if node.footnotes? && !(node.attr? 'nofootnotes')
|
|
685
|
+
result << '.SH "NOTES"'
|
|
686
|
+
node.footnotes.each_with_index do |fn, idx|
|
|
687
|
+
result << %(.IP [#{fn.index}])
|
|
688
|
+
# NOTE restore newline in escaped macro that gets removed by normalize_text in substitutor
|
|
689
|
+
if (text = fn.text).include? %(#{ESC}\\c #{ESC}.)
|
|
690
|
+
text = (manify %(#{text.gsub MalformedEscapedMacroRx, %(\\1#{LF}\\2)} ), whitespace: :normalize).chomp ' '
|
|
691
|
+
else
|
|
692
|
+
text = manify text, whitespace: :normalize
|
|
693
|
+
end
|
|
694
|
+
result << text
|
|
695
|
+
end
|
|
696
|
+
end
|
|
697
|
+
end
|
|
698
|
+
|
|
681
699
|
# Converts HTML entity references back to their original form, escapes
|
|
682
700
|
# special man characters and strips trailing whitespace.
|
|
683
701
|
#
|
|
@@ -704,7 +722,7 @@ allbox tab(:);'
|
|
|
704
722
|
gsub(EllipsisCharRefRx, '...'). # horizontal ellipsis
|
|
705
723
|
gsub(LeadingPeriodRx, '\\\&.'). # leading . is used in troff for macro call or other formatting; replace with \&.
|
|
706
724
|
# drop orphaned \c escape lines, unescape troff macro, quote adjacent character, isolate macro line
|
|
707
|
-
gsub(EscapedMacroRx) { (rest = $3.lstrip).empty? ? %(.#$1"#$2") : %(.#$1"
|
|
725
|
+
gsub(EscapedMacroRx) { (rest = $3.lstrip).empty? ? %(.#$1"#$2") : %(.#$1"#{$2.rstrip}"#{LF}#{rest}) }.
|
|
708
726
|
gsub('-', '\-').
|
|
709
727
|
gsub('<', '<').
|
|
710
728
|
gsub('>', '>').
|
|
@@ -726,13 +744,17 @@ allbox tab(:);'
|
|
|
726
744
|
gsub('​', '\:'). # zero width space
|
|
727
745
|
gsub('&', '&'). # literal ampersand (NOTE must take place after any other replacement that includes &)
|
|
728
746
|
gsub('\'', '\(aq'). # apostrophe-quote
|
|
729
|
-
gsub(
|
|
747
|
+
gsub(MockMacroRx, '\1'). # mock boundary
|
|
730
748
|
gsub(ESC_BS, '\\'). # unescape troff backslash (NOTE update if more escapes are added)
|
|
731
749
|
gsub(ESC_FS, '.'). # unescape full stop in troff commands (NOTE must take place after gsub(LeadingPeriodRx))
|
|
732
750
|
rstrip # strip trailing space
|
|
733
751
|
opts[:append_newline] ? %(#{str}#{LF}) : str
|
|
734
752
|
end
|
|
735
753
|
|
|
754
|
+
def uppercase_pcdata string
|
|
755
|
+
(XMLMarkupRx.match? string) ? string.gsub(PCDATAFilterRx) { $2 ? $2.upcase : $1 } : string.upcase
|
|
756
|
+
end
|
|
757
|
+
|
|
736
758
|
def enclose_content node
|
|
737
759
|
node.content_model == :compound ? node.content : %(.sp#{LF}#{manify node.content, whitespace: :normalize})
|
|
738
760
|
end
|