asciidoctor 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of asciidoctor might be problematic. Click here for more details.

Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.adoc +387 -0
  3. data/README.adoc +358 -348
  4. data/asciidoctor.gemspec +30 -9
  5. data/bin/asciidoctor +3 -0
  6. data/bin/asciidoctor-safe +3 -0
  7. data/compat/asciidoc.conf +76 -4
  8. data/lib/asciidoctor.rb +174 -79
  9. data/lib/asciidoctor/abstract_block.rb +131 -101
  10. data/lib/asciidoctor/abstract_node.rb +108 -26
  11. data/lib/asciidoctor/attribute_list.rb +1 -1
  12. data/lib/asciidoctor/backends/_stylesheets.rb +204 -62
  13. data/lib/asciidoctor/backends/base_template.rb +11 -22
  14. data/lib/asciidoctor/backends/docbook45.rb +158 -163
  15. data/lib/asciidoctor/backends/docbook5.rb +103 -0
  16. data/lib/asciidoctor/backends/html5.rb +662 -445
  17. data/lib/asciidoctor/block.rb +54 -44
  18. data/lib/asciidoctor/cli/invoker.rb +41 -20
  19. data/lib/asciidoctor/cli/options.rb +66 -20
  20. data/lib/asciidoctor/debug.rb +1 -1
  21. data/lib/asciidoctor/document.rb +265 -100
  22. data/lib/asciidoctor/extensions.rb +443 -0
  23. data/lib/asciidoctor/helpers.rb +38 -6
  24. data/lib/asciidoctor/inline.rb +5 -5
  25. data/lib/asciidoctor/lexer.rb +532 -250
  26. data/lib/asciidoctor/{list_item.rb → list.rb} +33 -13
  27. data/lib/asciidoctor/path_resolver.rb +28 -2
  28. data/lib/asciidoctor/reader.rb +814 -455
  29. data/lib/asciidoctor/renderer.rb +128 -42
  30. data/lib/asciidoctor/section.rb +55 -41
  31. data/lib/asciidoctor/substituters.rb +380 -107
  32. data/lib/asciidoctor/table.rb +40 -30
  33. data/lib/asciidoctor/version.rb +1 -1
  34. data/man/asciidoctor.1 +32 -96
  35. data/man/{asciidoctor.ad → asciidoctor.adoc} +57 -48
  36. data/test/attributes_test.rb +200 -27
  37. data/test/blocks_test.rb +361 -22
  38. data/test/document_test.rb +496 -81
  39. data/test/extensions_test.rb +448 -0
  40. data/test/fixtures/basic-docinfo-footer.html +6 -0
  41. data/test/fixtures/basic-docinfo-footer.xml +8 -0
  42. data/test/fixtures/basic-docinfo.xml +3 -3
  43. data/test/fixtures/basic.asciidoc +1 -0
  44. data/test/fixtures/child-include.adoc +5 -0
  45. data/test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml +6 -0
  46. data/test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml +1 -0
  47. data/test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml +3 -0
  48. data/test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml +5 -0
  49. data/test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim +6 -0
  50. data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +3 -0
  51. data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +5 -0
  52. data/test/fixtures/docinfo-footer.html +1 -0
  53. data/test/fixtures/docinfo-footer.xml +9 -0
  54. data/test/fixtures/docinfo.xml +1 -0
  55. data/test/fixtures/grandchild-include.adoc +3 -0
  56. data/test/fixtures/parent-include-restricted.adoc +5 -0
  57. data/test/fixtures/parent-include.adoc +5 -0
  58. data/test/invoker_test.rb +82 -8
  59. data/test/lexer_test.rb +21 -3
  60. data/test/links_test.rb +34 -2
  61. data/test/lists_test.rb +304 -7
  62. data/test/options_test.rb +19 -3
  63. data/test/paragraphs_test.rb +13 -0
  64. data/test/paths_test.rb +22 -0
  65. data/test/preamble_test.rb +20 -0
  66. data/test/reader_test.rb +1096 -644
  67. data/test/renderer_test.rb +152 -12
  68. data/test/sections_test.rb +417 -76
  69. data/test/substitutions_test.rb +339 -138
  70. data/test/tables_test.rb +109 -4
  71. data/test/test_helper.rb +79 -13
  72. data/test/text_test.rb +111 -11
  73. metadata +54 -18
@@ -6,13 +6,13 @@ Gem::Specification.new do |s|
6
6
  ## name, version, date and rubyforge_project are updated automatically by the
7
7
  ## Rake build (see the validate task)
8
8
  s.name = 'asciidoctor'
9
- s.version = '0.1.3'
10
- s.date = '2013-05-30'
9
+ s.version = '0.1.4'
10
+ s.date = '2013-09-05'
11
11
  s.rubyforge_project = 'asciidoctor'
12
12
 
13
- s.summary = 'A native Ruby AsciiDoc syntax processor and publishing toolchain'
13
+ s.summary = 'An implementation of the AsciiDoc text processor and publishing toolchain in Ruby'
14
14
  s.description = <<-EOS
15
- An open source text processor and publishing toolchain written in Ruby for converting AsciiDoc markup into HTML 5, DocBook 4.5 and custom formats.
15
+ A fast, open source text processor and publishing toolchain, written in Ruby, for transforming AsciiDoc markup into HTML 5, DocBook 4.5, DocBook 5.0 and custom outupt formats.
16
16
  EOS
17
17
  s.license = 'MIT'
18
18
  s.authors = ['Dan Allen', 'Ryan Waldron', 'Jeremy McAnally', 'Jason Porter', 'Nick Hengeveld']
@@ -24,7 +24,7 @@ EOS
24
24
 
25
25
  s.has_rdoc = true
26
26
  s.rdoc_options = ['--charset=UTF-8']
27
- s.extra_rdoc_files = %w[LICENSE]
27
+ s.extra_rdoc_files = %w[LICENSE CHANGELOG.adoc]
28
28
 
29
29
  ## List your runtime dependencies here. Runtime dependencies are those
30
30
  ## that are needed for an end user to actually USE your code.
@@ -34,17 +34,20 @@ EOS
34
34
  ## testing
35
35
  s.add_development_dependency('coderay')
36
36
  s.add_development_dependency('erubis')
37
- s.add_development_dependency('nokogiri')
38
- s.add_development_dependency('pending')
37
+ s.add_development_dependency('nokogiri', '~> 1.5.10')
39
38
  s.add_development_dependency('rake')
40
39
  s.add_development_dependency('rdoc', '~> 3.12')
41
40
  s.add_development_dependency('tilt')
41
+ # slim and haml needed for testing custom templates
42
+ s.add_development_dependency('slim')
43
+ s.add_development_dependency('haml')
42
44
 
43
45
  ## The manifest section is automatically generated by the Rake build
44
46
  ## based on the contents of the Git repository (see the gemspec task).
45
47
  ## DO NOT REMOVE THE = MANIFEST = DELIMITERS!
46
48
  # = MANIFEST =
47
49
  s.files = %w[
50
+ CHANGELOG.adoc
48
51
  Gemfile
49
52
  Guardfile
50
53
  LICENSE
@@ -61,6 +64,7 @@ EOS
61
64
  lib/asciidoctor/backends/_stylesheets.rb
62
65
  lib/asciidoctor/backends/base_template.rb
63
66
  lib/asciidoctor/backends/docbook45.rb
67
+ lib/asciidoctor/backends/docbook5.rb
64
68
  lib/asciidoctor/backends/html5.rb
65
69
  lib/asciidoctor/block.rb
66
70
  lib/asciidoctor/callouts.rb
@@ -68,10 +72,11 @@ EOS
68
72
  lib/asciidoctor/cli/options.rb
69
73
  lib/asciidoctor/debug.rb
70
74
  lib/asciidoctor/document.rb
75
+ lib/asciidoctor/extensions.rb
71
76
  lib/asciidoctor/helpers.rb
72
77
  lib/asciidoctor/inline.rb
73
78
  lib/asciidoctor/lexer.rb
74
- lib/asciidoctor/list_item.rb
79
+ lib/asciidoctor/list.rb
75
80
  lib/asciidoctor/path_resolver.rb
76
81
  lib/asciidoctor/reader.rb
77
82
  lib/asciidoctor/renderer.rb
@@ -80,22 +85,38 @@ EOS
80
85
  lib/asciidoctor/table.rb
81
86
  lib/asciidoctor/version.rb
82
87
  man/asciidoctor.1
83
- man/asciidoctor.ad
88
+ man/asciidoctor.adoc
84
89
  test/attributes_test.rb
85
90
  test/blocks_test.rb
86
91
  test/document_test.rb
92
+ test/extensions_test.rb
87
93
  test/fixtures/asciidoc.txt
88
94
  test/fixtures/asciidoc_index.txt
89
95
  test/fixtures/ascshort.txt
96
+ test/fixtures/basic-docinfo-footer.html
97
+ test/fixtures/basic-docinfo-footer.xml
90
98
  test/fixtures/basic-docinfo.html
91
99
  test/fixtures/basic-docinfo.xml
92
100
  test/fixtures/basic.asciidoc
101
+ test/fixtures/child-include.adoc
102
+ test/fixtures/custom-backends/haml/docbook45/block_paragraph.xml.haml
103
+ test/fixtures/custom-backends/haml/html5-tweaks/block_paragraph.html.haml
104
+ test/fixtures/custom-backends/haml/html5/block_paragraph.html.haml
105
+ test/fixtures/custom-backends/haml/html5/block_sidebar.html.haml
106
+ test/fixtures/custom-backends/slim/docbook45/block_paragraph.xml.slim
107
+ test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim
108
+ test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim
109
+ test/fixtures/docinfo-footer.html
110
+ test/fixtures/docinfo-footer.xml
93
111
  test/fixtures/docinfo.html
94
112
  test/fixtures/docinfo.xml
95
113
  test/fixtures/dot.gif
96
114
  test/fixtures/encoding.asciidoc
115
+ test/fixtures/grandchild-include.adoc
97
116
  test/fixtures/include-file.asciidoc
98
117
  test/fixtures/list_elements.asciidoc
118
+ test/fixtures/parent-include-restricted.adoc
119
+ test/fixtures/parent-include.adoc
99
120
  test/fixtures/sample.asciidoc
100
121
  test/fixtures/stylesheets/custom.css
101
122
  test/fixtures/tip.gif
@@ -2,6 +2,9 @@
2
2
 
3
3
  $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
4
 
5
+ if RUBY_VERSION < '1.9'
6
+ require 'rubygems'
7
+ end
5
8
  require 'asciidoctor'
6
9
  require 'asciidoctor/cli/options'
7
10
  require 'asciidoctor/cli/invoker'
@@ -2,6 +2,9 @@
2
2
 
3
3
  $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
4
4
 
5
+ if RUBY_VERSION < '1.9'
6
+ require 'rubygems'
7
+ end
5
8
  require 'asciidoctor'
6
9
  require 'asciidoctor/cli/options'
7
10
  require 'asciidoctor/cli/invoker'
@@ -10,7 +10,6 @@ newline=\n
10
10
  [attributes]
11
11
  # make html5 the default html backend
12
12
  backend-alias-html=html5
13
- linkcss=
14
13
  apostrophe='
15
14
  asterisk=*
16
15
  caret=^
@@ -27,17 +26,26 @@ sect1=^(==|##) +(?P<title>[\S].*?)(?: +\1)?$
27
26
  sect2=^(===|###) +(?P<title>[\S].*?)(?: +\1)?$
28
27
  sect3=^(====|####) +(?P<title>[\S].*?)(?: +\1)?$
29
28
  sect4=^(=====|#####) +(?P<title>[\S].*?)(?: +\1)?$
29
+ sect5=^(======|######) +(?P<title>[\S].*?)(?: +\1)?$
30
30
 
31
31
  # enables fenced code blocks
32
32
  # FIXME I haven't sorted out yet how to do syntax highlighting
33
33
  [blockdef-fenced-code]
34
- delimiter=^```\w*$
35
- template::[blockdef-listing]
34
+ delimiter=^```(?:\w+(?:,numbered)?)?$
35
+ ifdef::language[]
36
+ style=source
37
+ template::[source-filter-style]
38
+ endif::language[]
39
+ ifndef::language[]
40
+ template=listingblock
41
+ subs=verbatim
42
+ posattrs=style
43
+ endif::language[]
36
44
 
37
45
  # enables blockquotes to be defined using two double quotes
38
46
  [blockdef-air-quote]
39
- delimiter=^""$
40
47
  template::[blockdef-quote]
48
+ delimiter=^""$
41
49
 
42
50
  # markdown-style blockquote (paragraph only)
43
51
  # FIXME does not strip leading > on subsequent lines
@@ -69,6 +77,12 @@ delimiter=^:={3,}$
69
77
  format=dsv
70
78
 
71
79
  [macros]
80
+ # additional callout match for XML
81
+ [\\]?&lt;!--(?P<index>\d+)--&gt;=callout
82
+
83
+ # --- or *** or ___ or - - - or * * * or _ _ _ (in addition to the built-in ''')
84
+ ^ {0,3}([-\*_])( *)\1\2\1$=#ruler
85
+
72
86
  # btn:[Save]
73
87
  (?su)(?<!\w)\\?btn:\[(?P<attrlist>(?:\\\]|[^\]])+?)\]=button
74
88
 
@@ -81,6 +95,12 @@ format=dsv
81
95
 
82
96
  ifdef::basebackend-html[]
83
97
 
98
+ [sect5]
99
+ <div class="sect5{style? {style}}{role? {role}}">
100
+ <h6{id? id="{id}"}>{title}</h6>
101
+ |
102
+ </div>
103
+
84
104
  [button-inlinemacro]
85
105
  <b class="button">{1}</b>
86
106
 
@@ -111,6 +131,23 @@ subscript=<sub{1? class="{1}"}>|</sub>
111
131
  [monospacedwords]
112
132
  <code>{words}</code>
113
133
 
134
+ ifdef::linkattrs[]
135
+ [http-inlinemacro]
136
+ <a href="{name}:{target}"{role? class="{role}"}{window? target="{window}"}>{1={name}:{target}}</a>
137
+ [https-inlinemacro]
138
+ <a href="{name}:{target}"{role? class="{role}"}{window? target="{window}"}>{1={name}:{target}}</a>
139
+ [ftp-inlinemacro]
140
+ <a href="{name}:{target}"{role? class="{role}"}{window? target="{window}"}>{1={name}:{target}}</a>
141
+ [file-inlinemacro]
142
+ <a href="{name}:{target}"{role? class="{role}"}{window? target="{window}"}>{1={name}:{target}}</a>
143
+ [irc-inlinemacro]
144
+ <a href="{name}:{target}"{role? class="{role}"}{window? target="{window}"}>{1={name}:{target}}</a>
145
+ [mailto-inlinemacro]
146
+ <a href="mailto:{target}"{role? class="{role}"}{window? target="{window}"}>{1={target}}</a>
147
+ [link-inlinemacro]
148
+ <a href="{target}"{role? class="{role}"}{window? target="{window}"}>{1={target}}</a>
149
+ endif::linkattrs[]
150
+
114
151
  [listtags-numbered]
115
152
  list=<div class="olist{style? {style}}{compact-option? compact}{role? {role}}"{id? id="{id}"}>{title?<div class="title">{title}</div>}<ol class="{style}"{style@loweralpha: type="a"}{style@lowerroman: type="i"}{style@upperalpha: type="A"}{style@upperroman: type="I"}{start? start="{start}"}>|</ol></div>
116
153
 
@@ -159,6 +196,35 @@ endif::[]
159
196
  </tr></table>
160
197
  </div>
161
198
 
199
+ # modified so that:
200
+ # a. imagesdir is only prepended if target is not a uri or absolute path (relative path only)
201
+ # b. automatic alt text is calculated from basename of target without extension
202
+ # note that the escaped_target attribute must be set in order to use a uri in the conditional attribute reference
203
+ [image-inlinemacro]
204
+ <span class="image{role? {role}}"{float? style="float: {float}"}>{set2:escaped_target:{eval:'{target}'.replace(':','\:')}}
205
+ <a class="image" href="{link}">
206
+ {data-uri%}<img src="{target@^(/|https?\://).*:{escaped_target}:{imagesdir?{imagesdir}}{imagesdir?/}{escaped_target}}" alt="{alt={eval:os.path.splitext(os.path.basename('{target}'))[0]}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"}>
207
+ {data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}{title? title="{title}"}
208
+ {data-uri#}{sys:"{python}" -u -c "import mimetypes,base64,sys; print 'src=\"data:'+mimetypes.guess_type(r'{target}')[0]+';base64,'; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}">
209
+ {link#}</a>
210
+ </span>
211
+
212
+ # modified so that:
213
+ # a. imagesdir is only prepended if target is not a uri or absolute path (relative path only)
214
+ # b. automatic alt text is calculated from basename of target without extension
215
+ # note that the escaped_target attribute must be set in order to use a uri in the conditional attribute reference
216
+ [image-blockmacro]
217
+ <div class="imageblock{style? {style}}{role? {role}}{unbreakable-option? unbreakable}"{id? id="{id}"}{align? style="text-align:{align};"}{float? style="float: {float}"}>
218
+ <div class="content">{set2:escaped_target:{eval:'{target}'.replace(':','\:')}}
219
+ <a class="image" href="{link}">
220
+ {data-uri%}<img src="{target@^(/|https?\://).*:{escaped_target}:{imagesdir?{imagesdir}}{imagesdir?/}{escaped_target}}" alt="{alt={eval:os.path.splitext(os.path.basename('{target}'))[0]}}"{width? width="{width}"}{height? height="{height}"}>
221
+ {data-uri#}<img alt="{alt={target}}"{width? width="{width}"}{height? height="{height}"}
222
+ {data-uri#}{sys:"{python}" -u -c "import mimetypes,base64,sys; print 'src=\"data:'+mimetypes.guess_type(r'{target}')[0]+';base64,'; base64.encode(sys.stdin,sys.stdout)" < "{eval:os.path.join(r"{indir={outdir}}",r"{imagesdir=}",r"{target}")}"}">
223
+ {link#}</a>
224
+ </div>
225
+ <div class="title">{caption={figure-caption} {counter:figure-number}. }{title}</div>
226
+ </div>
227
+
162
228
  # a common template for emitting the attribute for a quote or verse block
163
229
  # don't output attribution div if attribution or citetitle are both empty
164
230
  [attribution]
@@ -209,6 +275,12 @@ endif::basebackend-html[]
209
275
  # Override docinfo to support subtitle
210
276
  ifdef::basebackend-docbook[]
211
277
 
278
+ [sect5]
279
+ <section{id? id="{id}"}{role? role="{role}"}{reftext? xreflabel="{reftext}"}>
280
+ <title>{title}</title>
281
+ |
282
+ </section>
283
+
212
284
  [button-inlinemacro]
213
285
  <guibutton>{1}</guibutton>
214
286
 
@@ -1,6 +1,4 @@
1
- if RUBY_VERSION < '1.9'
2
- require 'rubygems'
3
- end
1
+ RUBY_ENGINE = 'unknown' unless defined? RUBY_ENGINE
4
2
  require 'strscan'
5
3
  require 'set'
6
4
 
@@ -12,20 +10,18 @@ $:.unshift(File.dirname(__FILE__))
12
10
  # Asciidoc documents comprise a header followed by zero or more sections.
13
11
  # Sections are composed of blocks of content. For example:
14
12
  #
15
- # Doc Title
16
- # =========
13
+ # = Doc Title
17
14
  #
18
- # SECTION 1
19
- # ---------
15
+ # == Section 1
20
16
  #
21
17
  # This is a paragraph block in the first section.
22
18
  #
23
- # SECTION 2
19
+ # == Section 2
24
20
  #
25
21
  # This section has a paragraph block and an olist block.
26
22
  #
27
- # 1. Item 1
28
- # 2. Item 2
23
+ # . Item 1
24
+ # . Item 2
29
25
  #
30
26
  # Examples:
31
27
  #
@@ -89,6 +85,27 @@ module Asciidoctor
89
85
 
90
86
  end
91
87
 
88
+ # Flags to control compliance with the behavior of AsciiDoc
89
+ module Compliance
90
+ # AsciiDoc supports both single-line and underlined
91
+ # section titles.
92
+ # This option disables the underlined variant.
93
+ # Compliance value: true
94
+ @underline_style_section_titles = true
95
+ class << self
96
+ attr_accessor :underline_style_section_titles
97
+ end
98
+
99
+ # Asciidoctor will recognize commonly-used Markdown syntax
100
+ # to the degree it does not interfere with existing
101
+ # AsciiDoc syntax and behavior.
102
+ # Compliance value: false
103
+ @markdown_syntax = true
104
+ class << self
105
+ attr_accessor :markdown_syntax
106
+ end
107
+ end
108
+
92
109
  # The root path of the Asciidoctor gem
93
110
  ROOT_PATH = File.expand_path(File.join(File.dirname(__FILE__), '..'))
94
111
 
@@ -98,6 +115,12 @@ module Asciidoctor
98
115
  # Ruby 1.8 doesn't seem to experience this problem (perhaps because it isn't validating the encodings)
99
116
  FORCE_ENCODING = RUBY_VERSION > '1.9' && Encoding.default_external != Encoding::UTF_8
100
117
 
118
+ # Flag to indicate that line length should be calculated using a unicode mode hint
119
+ FORCE_UNICODE_LINE_LENGTH = RUBY_VERSION < '1.9'
120
+
121
+ # The endline character to use when rendering output
122
+ EOL = "\n"
123
+
101
124
  # The default document type
102
125
  # Can influence markup generated by render templates
103
126
  DEFAULT_DOCTYPE = 'article'
@@ -128,6 +151,15 @@ module Asciidoctor
128
151
  'markdown' => '.md'
129
152
  }
130
153
 
154
+ # Set of file extensions recognized as AsciiDoc documents (stored as a truth hash)
155
+ ASCIIDOC_EXTENSIONS = {
156
+ '.asciidoc' => true,
157
+ '.adoc' => true,
158
+ '.ad' => true,
159
+ '.asc' => true,
160
+ '.txt' => true
161
+ }
162
+
131
163
  SECTION_LEVELS = {
132
164
  '=' => 0,
133
165
  '-' => 1,
@@ -160,23 +192,30 @@ module Asciidoctor
160
192
  '~~~' => [:fenced_code, Set.new]
161
193
  }
162
194
 
195
+ DELIMITED_BLOCK_LEADERS = DELIMITED_BLOCKS.keys.map {|key| key[0..1] }.to_set
196
+
163
197
  BREAK_LINES = {
164
- %q{'''} => :ruler,
165
- '<<<' => :page_break
198
+ '\'' => :ruler,
199
+ '-' => :ruler,
200
+ '*' => :ruler,
201
+ '_' => :ruler,
202
+ '<' => :page_break
166
203
  }
167
204
 
168
- LIST_CONTEXTS = [:ulist, :olist, :dlist, :colist]
205
+ #LIST_CONTEXTS = [:ulist, :olist, :dlist, :colist]
169
206
 
170
207
  NESTABLE_LIST_CONTEXTS = [:ulist, :olist, :dlist]
171
208
 
172
- ORDERED_LIST_STYLES = [:arabic, :loweralpha, :lowerroman, :upperalpha, :upperroman]
209
+ # TODO validate use of explicit style name above ordered list (this list is for selecting an implicit style)
210
+ ORDERED_LIST_STYLES = [:arabic, :loweralpha, :lowerroman, :upperalpha, :upperroman] #, :lowergreek]
173
211
 
174
212
  ORDERED_LIST_MARKER_PATTERNS = {
175
213
  :arabic => /\d+[.>]/,
176
214
  :loweralpha => /[a-z]\./,
177
- :upperalpha => /[A-Z]\./,
178
215
  :lowerroman => /[ivx]+\)/,
216
+ :upperalpha => /[A-Z]\./,
179
217
  :upperroman => /[IVX]+\)/
218
+ #:lowergreek => /[a-z]\]/
180
219
  }
181
220
 
182
221
  ORDERED_LIST_KEYWORDS = {
@@ -184,12 +223,19 @@ module Asciidoctor
184
223
  'lowerroman' => 'i',
185
224
  'upperalpha' => 'A',
186
225
  'upperroman' => 'I'
226
+ #'lowergreek' => 'a'
227
+ #'arabic' => '1'
228
+ #'decimal' => '1'
187
229
  }
188
230
 
189
231
  LIST_CONTINUATION = '+'
190
232
 
191
233
  LINE_BREAK = ' +'
192
234
 
235
+ # attributes which be changed within the content of the document (but not
236
+ # header) because it has semantic meaning; ex. numbered
237
+ FLEXIBLE_ATTRIBUTES = %w(numbered)
238
+
193
239
  # NOTE allows for empty space in line as it could be left by the template engine
194
240
  BLANK_LINE_PATTERN = /^[[:blank:]]*\n/
195
241
 
@@ -215,10 +261,15 @@ module Asciidoctor
215
261
  # Compliance value: false
216
262
  :congruent_block_delimiters => true,
217
263
 
218
- # AsciiDoc will recognize commonly-used Markdown syntax
219
- # to the degree it does not interfere with existing
220
- # AsciiDoc behavior.
221
- :markdown_syntax => true
264
+ # AsciiDoc drops lines that contain references to missing attributes.
265
+ # This behavior is not intuitive to most writers
266
+ # Compliance value: 'drop-line'
267
+ :attribute_missing => 'skip',
268
+
269
+ # AsciiDoc drops lines that contain an attribute unassignemnt.
270
+ # This behavior may need to be tuned depending on the circumstances.
271
+ # Compliance value: 'drop-line'
272
+ :attribute_undefined => 'drop-line',
222
273
  }
223
274
 
224
275
  # The following pattern, which appears frequently, captures the contents between square brackets,
@@ -251,27 +302,18 @@ module Asciidoctor
251
302
  # [[:graph:]] is a non-blank character
252
303
  :any_list => /^(?:
253
304
  <?\d+>[[:blank:]]+[[:graph:]]|
254
- [[:blank:]]*(?:(?:-|\*|\.){1,5}|\d+\.|[A-Za-z]\.|[IVXivx]+\))[[:blank:]]+[[:graph:]]|
305
+ [[:blank:]]*(?:-|(?:\*|\.){1,5}|\d+\.|[A-Za-z]\.|[IVXivx]+\))[[:blank:]]+[[:graph:]]|
255
306
  [[:blank:]]*.*?(?::{2,4}|;;)(?:[[:blank:]]+[[:graph:]]|$)
256
307
  )/x,
257
308
 
258
309
  # :foo: bar
259
310
  # :Author: Dan
260
311
  # :numbered!:
261
- :attr_entry => /^:(\w.*?):(?:[[:blank:]]+(.*))?$/,
262
-
263
- # {name?value}
264
- :attr_conditional => /^\s*\{([^\?]+)\?\s*([^\}]+)\s*\}/,
265
-
266
- # + Attribute values treat lines ending with ' +' as a continuation,
267
- # not a line-break as elsewhere in the document, where this is
268
- # a forced line break. This should be the same regexp as :line_break,
269
- # below, but it gets its own entry because readability ftw, even
270
- # though repeating regexps ftl.
271
- :attr_continue => /^[[:blank:]]*(.*)[[:blank:]]\+[[:blank:]]*$/,
272
-
273
- # :foo!:
274
- :attr_delete => /^:([^:]+)!:$/,
312
+ # :long-entry: Attribute value lines ending in ' +'
313
+ # are joined together as a single value,
314
+ # collapsing the line breaks and indentation to
315
+ # a single space.
316
+ :attr_entry => /^:(!?\w.*?):(?:[[:blank:]]+(.*))?$/,
275
317
 
276
318
  # An attribute list above a block element
277
319
  #
@@ -281,14 +323,16 @@ module Asciidoctor
281
323
  # [NOTE, caption="Good to know"]
282
324
  # Can be defined by an attribute
283
325
  # [{lead}]
284
- :blk_attr_list => /^\[(|[[:blank:]]*[\w\{,.#"'].*)\]$/,
326
+ :blk_attr_list => /^\[(|[[:blank:]]*[\w\{,.#"'%].*)\]$/,
285
327
 
286
328
  # block attribute list or block id (bulk query)
287
- :attr_line => /^\[(|[[:blank:]]*[\w\{,.#"'].*|\[[^\[\]]*\])\]$/,
329
+ :attr_line => /^\[(|[[:blank:]]*[\w\{,.#"'%].*|\[[^\[\]]*\])\]$/,
288
330
 
289
331
  # attribute reference
290
332
  # {foo}
291
333
  # {counter:pcount:1}
334
+ # {set:foo:bar}
335
+ # {set:name!}
292
336
  :attr_ref => /(\\)?\{((set|counter2?):.+?|\w+(?:[\-]\w+)*)(\\)?\}/,
293
337
 
294
338
  # The author info line the appears immediately following the document title
@@ -299,11 +343,14 @@ module Asciidoctor
299
343
  :biblio_macro => /\\?\[\[\[([\w:][\w:.-]*?)\]\]\]/,
300
344
 
301
345
  # callout reference inside literal text
302
- # <1>
303
- # special characters will already be replaced, hence their use in the regex
304
- :callout_render => /\\?&lt;(\d+)&gt;/,
346
+ # <1> (optionally prefixed by //, # or ;; line comment chars)
347
+ # <1> <2> (multiple callouts on one line)
348
+ # <!--1--> (for XML-based languages)
349
+ # special characters are already be replaced at this point during render
350
+ :callout_render => /(?:(?:\/\/|#|;;) ?)?(\\)?&lt;!?(--|)(\d+)\2&gt;(?=(?: ?\\?&lt;!?\2\d+\2&gt;)*$)/,
305
351
  # ...but not while scanning
306
- :callout_scan => /\\?<(\d+)>/,
352
+ :callout_quick_scan => /\\?<!?(--|)(\d+)\1>(?=(?: ?\\?<!?\1\d+\1>)*$)/,
353
+ :callout_scan => /(?:(?:\/\/|#|;;) ?)?(\\)?<!?(--|)(\d+)\2>(?=(?: ?\\?<!?\2\d+\2>)*$)/,
307
354
 
308
355
  # <1> Foo
309
356
  :colist => /^<?(\d+)>[[:blank:]]+(.*)/,
@@ -317,7 +364,7 @@ module Asciidoctor
317
364
  :comment => %r{^//(?:[^/]|$)},
318
365
 
319
366
  # one,two;three;four
320
- :ssv_or_csv_delim => /,|;/,
367
+ :ssv_or_csv_delim => /,|;/,
321
368
 
322
369
  # one two three
323
370
  :space_delim => /([^\\])[[:blank:]]+/,
@@ -340,21 +387,27 @@ module Asciidoctor
340
387
  # That which precedes 'bar' (see also, <<bar>>)
341
388
  # The term may be an attribute reference
342
389
  # {term_foo}:: {def_foo}
343
- # REVIEW leading space has already been stripped, so may not need in regex
344
- :dlist => /^[[:blank:]]*(.*?)(:{2,4}|;;)(?:[[:blank:]]+(.*))?$/,
390
+ # NOTE negative match for comment line is intentional since that isn't handled when looking for next list item
391
+ # QUESTION should we check for line comment in regex or when scanning the lines?
392
+ :dlist => /^(?!\/\/)[[:blank:]]*(.*?)(:{2,4}|;;)(?:[[:blank:]]+(.*))?$/,
345
393
  :dlist_siblings => {
346
394
  # (?:.*?[^:])? - a non-capturing group which grabs longest sequence of characters that doesn't end w/ colon
347
- '::' => /^[[:blank:]]*((?:.*[^:])?)(::)(?:[[:blank:]]+(.*))?$/,
348
- ':::' => /^[[:blank:]]*((?:.*[^:])?)(:::)(?:[[:blank:]]+(.*))?$/,
349
- '::::' => /^[[:blank:]]*((?:.*[^:])?)(::::)(?:[[:blank:]]+(.*))?$/,
350
- ';;' => /^[[:blank:]]*(.*)(;;)(?:[[:blank:]]+(.*))?$/
395
+ '::' => /^(?!\/\/)[[:blank:]]*((?:.*[^:])?)(::)(?:[[:blank:]]+(.*))?$/,
396
+ ':::' => /^(?!\/\/)[[:blank:]]*((?:.*[^:])?)(:::)(?:[[:blank:]]+(.*))?$/,
397
+ '::::' => /^(?!\/\/)[[:blank:]]*((?:.*[^:])?)(::::)(?:[[:blank:]]+(.*))?$/,
398
+ ';;' => /^(?!\/\/)[[:blank:]]*(.*)(;;)(?:[[:blank:]]+(.*))?$/
351
399
  },
352
400
 
401
+ :illegal_sectid_chars => /&(?:[[:alpha:]]+|#[[:digit:]]+|#x[[:alnum:]]+);|\W+?/,
402
+
353
403
  # footnote:[text]
354
404
  # footnoteref:[id,text]
355
405
  # footnoteref:[id]
356
406
  :footnote_macro => /\\?(footnote|footnoteref):\[((?:\\\]|[^\]])*?)\]/,
357
407
 
408
+ # gist::123456[]
409
+ :generic_blk_macro => /^(\w[\w\-]*)::(\S+?)\[((?:\\\]|[^\]])*?)\]$/,
410
+
358
411
  # kbd:[F3]
359
412
  # kbd:[Ctrl+Shift+T]
360
413
  # kbd:[Ctrl+\]]
@@ -375,8 +428,10 @@ module Asciidoctor
375
428
  :media_blk_macro => /^(image|video|audio)::(\S+?)\[((?:\\\]|[^\]])*?)\]$/,
376
429
 
377
430
  # image:filename.png[Alt Text]
431
+ # image:http://example.com/images/filename.png[Alt Text]
378
432
  # image:filename.png[More [Alt\] Text] (alt text becomes "More [Alt] Text")
379
- :image_macro => /\\?image:([^:\[]+)\[((?:\\\]|[^\]])*?)\]/,
433
+ # icon:github[large]
434
+ :image_macro => /\\?(?:image|icon):([^:\[][^\[]*)\[((?:\\\]|[^\]])*?)\]/,
380
435
 
381
436
  # indexterm:[Tigers,Big cats]
382
437
  # (((Tigers,Big cats)))
@@ -403,7 +458,7 @@ module Asciidoctor
403
458
 
404
459
  # inline link and some inline link macro
405
460
  # FIXME revisit!
406
- :link_inline => %r{(^|link:|\s|>|&lt;|[\(\)\[\]])(\\?(?:https?|ftp|irc)://[^\s\[<]*[^\s.,\[<])(?:\[((?:\\\]|[^\]])*?)\])?},
461
+ :link_inline => %r{(^|link:|\s|>|&lt;|[\(\)\[\]])(\\?(?:https?|ftp|irc)://[^\s\[\]<]*[^\s.,\[\]<])(?:\[((?:\\\]|[^\]])*?)\])?},
407
462
 
408
463
  # inline link macro
409
464
  # link:path[label]
@@ -429,6 +484,12 @@ module Asciidoctor
429
484
  # <<< (pagebreak)
430
485
  :break_line => /^('|<){3,}$/,
431
486
 
487
+ # ''' or ' ' ' (ruler)
488
+ # --- or - - - (ruler)
489
+ # *** or * * * (ruler)
490
+ # <<< (pagebreak)
491
+ :break_line_plus => /^(?:'|<){3,}$|^ {0,3}([-\*_])( *)\1\2\1$/,
492
+
432
493
  # inline passthrough macros
433
494
  # +++text+++
434
495
  # $$text$$
@@ -441,7 +502,7 @@ module Asciidoctor
441
502
 
442
503
  # inline literal passthrough macro
443
504
  # `text`
444
- :pass_lit => /(^|[^`\w])(\\?`([^`\s]|[^`\s].*?\S)`)(?![`\w])/m,
505
+ :pass_lit => /(^|[^`\w])(?:\[([^\]]+?)\])?(\\?`([^`\s]|[^`\s].*?\S)`)(?![`\w])/m,
445
506
 
446
507
  # placeholder for extracted passthrough text
447
508
  :pass_placeholder => /\e(\d+)\e/,
@@ -460,7 +521,7 @@ module Asciidoctor
460
521
  :illegal_attr_name_chars => /[^\w\-]/,
461
522
 
462
523
  # 1*h,2*,^3e
463
- :table_colspec => /^(?:(\d+)\*)?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?(\d+)?([a-z])?$/,
524
+ :table_colspec => /^(?:(\d+)\*)?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?(\d+%?)?([a-z])?$/,
464
525
 
465
526
  # 2.3+<.>m
466
527
  # TODO might want to use step-wise scan rather than this mega-regexp
@@ -469,6 +530,10 @@ module Asciidoctor
469
530
  :end => /[[:blank:]]+(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
470
531
  },
471
532
 
533
+ # docbook45
534
+ # html5
535
+ :trailing_digit => /[[:digit:]]+$/,
536
+
472
537
  # .Foo but not . Foo or ..Foo
473
538
  :blk_title => /^\.([^\s.].*)$/,
474
539
 
@@ -535,9 +600,13 @@ module Asciidoctor
535
600
  # http://domain
536
601
  # https://domain
537
602
  # data:info
538
- :uri_sniff => /^[[:alpha:]][[:alnum:].+-]*:/i,
603
+ :uri_sniff => %r{\A[[:alpha:]][[:alnum:].+-]*:/*},
604
+
605
+ :uri_encode_chars => /[^\w\-.!~*';:@=+$,()\[\]]/,
539
606
 
540
- :uri_encode_chars => /[^\w\-.!~*';:@=+$,()\[\]]/
607
+ :mantitle_manvolnum => /^(.*)\((.*)\)$/,
608
+
609
+ :manname_manpurpose => /^(.*?)[[:blank:]]+-[[:blank:]]+(.*)$/
541
610
  }
542
611
 
543
612
  INTRINSICS = Hash.new{|h,k| STDERR.puts "Missing intrinsic: #{k.inspect}"; "{#{k}}"}.merge(
@@ -668,16 +737,15 @@ module Asciidoctor
668
737
  # options - a String, Array or Hash of options to control processing (default: {})
669
738
  # String and Array values are converted into a Hash.
670
739
  # See Asciidoctor::Document#initialize for details about options.
671
- # block - a callback block for handling include::[] directives
672
740
  #
673
741
  # returns the Asciidoctor::Document
674
- def self.load(input, options = {}, &block)
742
+ def self.load(input, options = {})
675
743
  if (monitor = options.fetch(:monitor, false))
676
744
  start = Time.now
677
745
  end
678
746
 
679
747
  attrs = (options[:attributes] ||= {})
680
- if attrs.is_a? Hash
748
+ if attrs.is_a?(Hash) || (RUBY_ENGINE == 'jruby' && attrs.is_a?(Java::JavaUtil::Map))
681
749
  # all good; placed here as optimization
682
750
  elsif attrs.is_a? Array
683
751
  attrs = options[:attributes] = attrs.inject({}) do |accum, entry|
@@ -695,8 +763,15 @@ module Asciidoctor
695
763
  accum[k] = v || ''
696
764
  accum
697
765
  end
766
+ elsif attrs.respond_to?('keys') && attrs.respond_to?('[]')
767
+ # convert it to a Hash as we know it
768
+ original_attrs = attrs
769
+ attrs = options[:attributes] = {}
770
+ original_attrs.keys.each do |key|
771
+ attrs[key] = original_attrs[key]
772
+ end
698
773
  else
699
- raise ArgumentError, 'illegal type for attributes option'
774
+ raise ArgumentError, "illegal type for attributes option: #{attrs.class.ancestors}"
700
775
  end
701
776
 
702
777
  lines = nil
@@ -727,7 +802,7 @@ module Asciidoctor
727
802
  start = Time.now
728
803
  end
729
804
 
730
- doc = Document.new(lines, options, &block)
805
+ doc = Document.new(lines, options)
731
806
  if monitor
732
807
  parse_time = Time.now - start
733
808
  monitor[:read] = read_time
@@ -747,11 +822,10 @@ module Asciidoctor
747
822
  # options - a String, Array or Hash of options to control processing (default: {})
748
823
  # String and Array values are converted into a Hash.
749
824
  # See Asciidoctor::Document#initialize for details about options.
750
- # block - a callback block for handling include::[] directives
751
825
  #
752
826
  # returns the Asciidoctor::Document
753
- def self.load_file(filename, options = {}, &block)
754
- Asciidoctor.load(File.new(filename), options, &block)
827
+ def self.load_file(filename, options = {})
828
+ Asciidoctor.load(File.new(filename), options)
755
829
  end
756
830
 
757
831
  # Public: Parse the AsciiDoc source input into an Asciidoctor::Document and render it
@@ -780,11 +854,10 @@ module Asciidoctor
780
854
  # options - a String, Array or Hash of options to control processing (default: {})
781
855
  # String and Array values are converted into a Hash.
782
856
  # See Asciidoctor::Document#initialize for details about options.
783
- # block - a callback block for handling include::[] directives
784
857
  #
785
858
  # returns the Document object if the rendered result String is written to a
786
859
  # file, otherwise the rendered result String
787
- def self.render(input, options = {}, &block)
860
+ def self.render(input, options = {})
788
861
  in_place = options.delete(:in_place) || false
789
862
  to_file = options.delete(:to_file)
790
863
  to_dir = options.delete(:to_dir)
@@ -803,7 +876,7 @@ module Asciidoctor
803
876
  options[:header_footer] = true
804
877
  end
805
878
 
806
- doc = Asciidoctor.load(input, options, &block)
879
+ doc = Asciidoctor.load(input, options)
807
880
 
808
881
  if to_file == '/dev/null'
809
882
  return doc
@@ -852,7 +925,7 @@ module Asciidoctor
852
925
  if stream_output
853
926
  to_file.write output.rstrip
854
927
  # ensure there's a trailing endline
855
- to_file.write "\n"
928
+ to_file.write EOL
856
929
  else
857
930
  File.open(to_file, 'w') {|file| file.write output }
858
931
  # these assignments primarily for testing, diagnostics or reporting
@@ -866,16 +939,39 @@ module Asciidoctor
866
939
  end
867
940
 
868
941
  # NOTE document cannot control this behavior if safe >= SafeMode::SERVER
869
- if !stream_output && doc.attr?('basebackend-html') && doc.attr?('copycss') &&
870
- doc.attr?('linkcss') && DEFAULT_STYLESHEET_KEYS.include?(doc.attr('stylesheet'))
871
- Helpers.require_library 'fileutils'
872
- outdir = doc.attr('outdir')
873
- stylesdir = doc.normalize_system_path(doc.attr('stylesdir'), outdir,
874
- doc.safe >= SafeMode::SAFE ? outdir : nil)
875
- Helpers.mkdir_p stylesdir
876
- File.open(File.join(stylesdir, DEFAULT_STYLESHEET_NAME), 'w') {|f|
877
- f.write Asciidoctor::HTML5.default_asciidoctor_stylesheet
878
- }
942
+ if !stream_output && doc.safe < SafeMode::SECURE && (doc.attr? 'basebackend-html') &&
943
+ (doc.attr? 'linkcss') && (doc.attr? 'copycss')
944
+ copy_asciidoctor_stylesheet = DEFAULT_STYLESHEET_KEYS.include?(stylesheet = (doc.attr 'stylesheet'))
945
+ #copy_user_stylesheet = !copy_asciidoctor_stylesheet && (doc.attr? 'copycss')
946
+ copy_coderay_stylesheet = (doc.attr? 'source-highlighter', 'coderay') && (doc.attr 'coderay-css', 'class') == 'class'
947
+ copy_pygments_stylesheet = (doc.attr? 'source-highlighter', 'pygments') && (doc.attr 'pygments-css', 'class') == 'class'
948
+ if copy_asciidoctor_stylesheet || copy_coderay_stylesheet || copy_pygments_stylesheet
949
+ Helpers.require_library 'fileutils'
950
+ outdir = doc.attr('outdir')
951
+ stylesdir = doc.normalize_system_path(doc.attr('stylesdir'), outdir,
952
+ doc.safe >= SafeMode::SAFE ? outdir : nil)
953
+ Helpers.mkdir_p stylesdir if mkdirs
954
+ if copy_asciidoctor_stylesheet
955
+ File.open(File.join(stylesdir, DEFAULT_STYLESHEET_NAME), 'w') {|f|
956
+ f.write Asciidoctor::HTML5.default_asciidoctor_stylesheet
957
+ }
958
+ end
959
+
960
+ #if copy_user_stylesheet
961
+ #end
962
+
963
+ if copy_coderay_stylesheet
964
+ File.open(File.join(stylesdir, 'asciidoctor-coderay.css'), 'w') {|f|
965
+ f.write Asciidoctor::HTML5.default_coderay_stylesheet
966
+ }
967
+ end
968
+
969
+ if copy_pygments_stylesheet
970
+ File.open(File.join(stylesdir, 'asciidoctor-pygments.css'), 'w') {|f|
971
+ f.write Asciidoctor::HTML5.pygments_stylesheet(doc.attr 'pygments-style')
972
+ }
973
+ end
974
+ end
879
975
  end
880
976
  doc
881
977
  else
@@ -890,12 +986,11 @@ module Asciidoctor
890
986
  # options - a String, Array or Hash of options to control processing (default: {})
891
987
  # String and Array values are converted into a Hash.
892
988
  # See Asciidoctor::Document#initialize for details about options.
893
- # block - a callback block for handling include::[] directives
894
989
  #
895
990
  # returns the Document object if the rendered result String is written to a
896
991
  # file, otherwise the rendered result String
897
- def self.render_file(filename, options = {}, &block)
898
- Asciidoctor.render(File.new(filename), options, &block)
992
+ def self.render_file(filename, options = {})
993
+ Asciidoctor.render(File.new(filename), options)
899
994
  end
900
995
 
901
996
  # modules
@@ -915,7 +1010,7 @@ module Asciidoctor
915
1010
  require 'asciidoctor/document'
916
1011
  require 'asciidoctor/inline'
917
1012
  require 'asciidoctor/lexer'
918
- require 'asciidoctor/list_item'
1013
+ require 'asciidoctor/list'
919
1014
  require 'asciidoctor/path_resolver'
920
1015
  require 'asciidoctor/reader'
921
1016
  require 'asciidoctor/renderer'