asciidoctor 0.0.7 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/Gemfile +2 -0
  2. data/README.asciidoc +35 -26
  3. data/Rakefile +9 -6
  4. data/asciidoctor.gemspec +27 -8
  5. data/bin/asciidoctor +1 -1
  6. data/lib/asciidoctor.rb +351 -63
  7. data/lib/asciidoctor/abstract_block.rb +218 -0
  8. data/lib/asciidoctor/abstract_node.rb +249 -0
  9. data/lib/asciidoctor/attribute_list.rb +211 -0
  10. data/lib/asciidoctor/backends/base_template.rb +99 -0
  11. data/lib/asciidoctor/backends/docbook45.rb +510 -0
  12. data/lib/asciidoctor/backends/html5.rb +585 -0
  13. data/lib/asciidoctor/block.rb +27 -254
  14. data/lib/asciidoctor/callouts.rb +117 -0
  15. data/lib/asciidoctor/debug.rb +7 -4
  16. data/lib/asciidoctor/document.rb +229 -77
  17. data/lib/asciidoctor/inline.rb +29 -0
  18. data/lib/asciidoctor/lexer.rb +1330 -502
  19. data/lib/asciidoctor/list_item.rb +33 -34
  20. data/lib/asciidoctor/reader.rb +305 -142
  21. data/lib/asciidoctor/renderer.rb +115 -19
  22. data/lib/asciidoctor/section.rb +100 -189
  23. data/lib/asciidoctor/substituters.rb +468 -0
  24. data/lib/asciidoctor/table.rb +499 -0
  25. data/lib/asciidoctor/version.rb +1 -1
  26. data/test/attributes_test.rb +301 -87
  27. data/test/blocks_test.rb +568 -0
  28. data/test/document_test.rb +221 -24
  29. data/test/fixtures/dot.gif +0 -0
  30. data/test/fixtures/encoding.asciidoc +1 -0
  31. data/test/fixtures/include-file.asciidoc +1 -0
  32. data/test/fixtures/tip.gif +0 -0
  33. data/test/headers_test.rb +411 -43
  34. data/test/lexer_test.rb +265 -45
  35. data/test/links_test.rb +144 -3
  36. data/test/lists_test.rb +2252 -74
  37. data/test/paragraphs_test.rb +21 -30
  38. data/test/preamble_test.rb +24 -0
  39. data/test/reader_test.rb +248 -12
  40. data/test/renderer_test.rb +22 -0
  41. data/test/substitutions_test.rb +414 -0
  42. data/test/tables_test.rb +484 -0
  43. data/test/test_helper.rb +70 -6
  44. data/test/text_test.rb +30 -6
  45. metadata +64 -10
  46. data/lib/asciidoctor/render_templates.rb +0 -317
  47. data/lib/asciidoctor/string.rb +0 -12
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
@@ -1,7 +1,11 @@
1
1
  [float]
2
2
  Asciidoctor
3
3
  ===========
4
+ :asciidoctor: http://github.com/erebor/asciidoctor
5
+ :asciidoc: http://www.methods.co.nz/asciidoc/index.html
4
6
  :gitscm-next: https://github.com/github/gitscm-next
7
+ :asciidoctorseed: https://github.com/github/gitscm-next/commits/master/lib/asciidoc.rb
8
+ :templates: https://github.com/erebor/asciidoctor/blob/master/lib/asciidoctor/render_templates.rb
5
9
  :tilt: https://github.com/rtomayko/tilt
6
10
  :freesoftware: http://www.fsf.org/licensing/essays/free-sw.html
7
11
  :issues: https://github.com/erebor/asciidoctor/issues
@@ -11,11 +15,11 @@ Asciidoctor
11
15
  :pr: http://help.github.com/send-pull-requests/
12
16
  :license: https://github.com/erebor/asciidoctor/blob/master/LICENSE
13
17
 
14
- http://github.com/erebor/asciidoctor[Asciidoctor] is a pure-Ruby
15
- processor for turning
16
- http://www.methods.co.nz/asciidoc/index.html[AsciiDoc] documents or
17
- strings into HTML (and, eventually other formats as well...'stay
18
- tuned!').
18
+ {asciidoctor}[Asciidoctor] is a pure-Ruby processor for turning
19
+ {asciidoc}[AsciiDoc] documents or strings into HTML (and, eventually
20
+ other formats as well...'stay tuned!').
21
+
22
+ image::https://travis-ci.org/erebor/asciidoctor.png?branch=master["Build Status", link="https://travis-ci.org/erebor/asciidoctor"]
19
23
 
20
24
  Asciidoctor uses simple built-in ERB templates to style the output in
21
25
  a way that roughly matches the default HTML output of the native
@@ -28,14 +32,15 @@ know of any reason it shouldn't work with more exotic Ruby versions,
28
32
  and would welcome help in testing that out.
29
33
 
30
34
  The initial code from which Asciidoctor started was from the
31
- {gitscm-next}[Git SCM site repo].
35
+ {gitscm-next}[Git SCM site repo]. Refer to commit history of
36
+ {asciidoctorseed}[asciidoc.rb] to view the initial contributions.
32
37
 
33
38
  == Installation
34
39
 
35
- NOTE: This gem is very immature, and as yet only supports a small
36
- subset of AsciiDoc features. Thus, you should only use it if you have
37
- a high tolerance for bugs, failures, and generally bad and intemperate
38
- behavior.
40
+ NOTE: This gem is very immature, and as yet only supports a small subset
41
+ of AsciiDoc features (but it's getting better!). Thus, you should only
42
+ use it if you have a high tolerance for bugs, failures, and generally
43
+ bad and intemperate behavior.
39
44
 
40
45
  To install the gem:
41
46
 
@@ -61,27 +66,29 @@ To render an AsciiDoc-formatted string:
61
66
  doc = Asciidoctor::Document.new("*This* is it.")
62
67
  puts doc.render
63
68
 
64
- Asciidoctor allows you to override the default template used to render
65
- almost any individual AsciiDoc element. If you provide a directory of
66
- {tilt}[Tilt]-compatible templates, named in such a way that Asciidoctor
67
- can figure out which template goes with which element, Asciidoctor will
68
- use the templates in this directory instead of its built-in templates
69
- for any elements for which it finds a matching template. It will
70
- fallback to its default templates for everything else.
69
+ Asciidoctor allows you to override the {templates}[built-in templates]
70
+ used to render almost any individual AsciiDoc element. If you provide a
71
+ directory of {tilt}[Tilt]-compatible templates, named in such a way that
72
+ Asciidoctor can figure out which template goes with which element,
73
+ Asciidoctor will use the templates in this directory instead of its
74
+ built-in templates for any elements for which it finds a matching
75
+ template. It will fallback to its default templates for everything else.
71
76
 
72
77
  doc = Asciidoctor::Document.new("*This* is it.", :template_dir => 'templates')
73
78
  puts doc.render
74
79
 
75
80
  The Document and Section templates should begin with `document.` and
76
- `section.`, respectively. The file extension will depend on which
77
- Tilt-compatible format you've chosen. For ERB, the template names would be
78
- `document.html.erb` and `section.html.erb`, for instance. For Haml, they
79
- would be `document.html.haml` and `section.html.haml`.
80
-
81
- Templates for specific elements, like a Paragraph or Anchor, would begin
82
- with `section_<element>.`. For instance, to override the default Paragraph
83
- template with an ERB template, put a file called `section_paragraph.html.erb`
84
- in the template directory you pass in to `Document.new`.
81
+ `section.`, respectively. The file extension is used by Tilt to
82
+ determine which view framework it will use to use to render the
83
+ template. For instance, if you want to write the template in ERB, you'd
84
+ name these two templates `document.html.erb` and `section.html.erb`. To
85
+ use Haml, you'd name them `document.html.haml` and `section.html.haml`.
86
+
87
+ Templates for block elements, like a Paragraph or Sidebar, would begin
88
+ with `block_<style>.`. For instance, to override the default Paragraph
89
+ template with an ERB template, put a file named
90
+ `block_paragraph.html.erb` in the template directory you pass to the
91
+ `Document` constructor using the `template_dir` option.
85
92
 
86
93
  For more usage examples, see the test suite.
87
94
 
@@ -154,3 +161,5 @@ support for that Ruby version may be dropped.
154
161
 
155
162
  Copyright (c) 2012 Ryan Waldron.
156
163
  See {license}[LICENSE] for details.
164
+
165
+ // vim: tw=72
data/Rakefile CHANGED
@@ -60,12 +60,15 @@ task :coverage do
60
60
  sh "open coverage/index.html"
61
61
  end
62
62
 
63
- require 'rdoc/task'
64
- Rake::RDocTask.new do |rdoc|
65
- rdoc.rdoc_dir = 'rdoc'
66
- rdoc.title = "#{name} #{version}"
67
- rdoc.rdoc_files.include('README*')
68
- rdoc.rdoc_files.include('lib/**/*.rb')
63
+ begin
64
+ require 'rdoc/task'
65
+ Rake::RDocTask.new do |rdoc|
66
+ rdoc.rdoc_dir = 'rdoc'
67
+ rdoc.title = "#{name} #{version}"
68
+ rdoc.rdoc_files.include('README*')
69
+ rdoc.rdoc_files.include('lib/**/*.rb')
70
+ end
71
+ rescue LoadError
69
72
  end
70
73
 
71
74
  desc "Open an irb session preloaded with this library"
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
13
13
  ## If your rubyforge_project name is different, then edit it and comment out
14
14
  ## the sub! line in the Rakefile
15
15
  s.name = 'asciidoctor'
16
- s.version = '0.0.7'
17
- s.date = '2012-12-17'
16
+ s.version = '0.0.9'
17
+ s.date = '2013-01-16'
18
18
  s.rubyforge_project = 'asciidoctor'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -25,7 +25,7 @@ Gem::Specification.new do |s|
25
25
  ## List the primary authors. If there are a bunch of authors, it's probably
26
26
  ## better to set the email to an email list or something. If you don't have
27
27
  ## a custom homepage, consider using your GitHub URL or the like.
28
- s.authors = ["Ryan Waldron", "Jeremy McAnally"]
28
+ s.authors = ["Ryan Waldron", "Dan Allen", "Jeremy McAnally"]
29
29
  s.email = 'rew@erebor.com'
30
30
  s.homepage = 'http://github.com/erebor/asciidoctor'
31
31
 
@@ -43,46 +43,62 @@ Gem::Specification.new do |s|
43
43
 
44
44
  ## List your runtime dependencies here. Runtime dependencies are those
45
45
  ## that are needed for an end user to actually USE your code.
46
- s.add_dependency('json')
47
- s.add_dependency('tilt')
48
46
 
49
47
  ## List your development dependencies here. Development dependencies are
50
48
  ## those that are only needed during development
49
+ s.add_development_dependency('coderay')
50
+ s.add_development_dependency('erubis')
51
+ s.add_development_dependency('htmlentities')
51
52
  s.add_development_dependency('mocha')
52
53
  s.add_development_dependency('nokogiri')
53
- s.add_development_dependency('htmlentities')
54
54
  s.add_development_dependency('pending')
55
+ s.add_development_dependency('rake')
56
+ s.add_development_dependency('tilt')
55
57
 
56
58
  ## Leave this section as-is. It will be automatically generated from the
57
59
  ## contents of your Git repository via the gemspec task. DO NOT REMOVE
58
60
  ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
59
61
  # = MANIFEST =
60
62
  s.files = %w[
63
+ Gemfile
61
64
  LICENSE
62
65
  README.asciidoc
63
66
  Rakefile
64
67
  asciidoctor.gemspec
65
68
  bin/asciidoctor
66
69
  lib/asciidoctor.rb
70
+ lib/asciidoctor/abstract_block.rb
71
+ lib/asciidoctor/abstract_node.rb
72
+ lib/asciidoctor/attribute_list.rb
73
+ lib/asciidoctor/backends/base_template.rb
74
+ lib/asciidoctor/backends/docbook45.rb
75
+ lib/asciidoctor/backends/html5.rb
67
76
  lib/asciidoctor/block.rb
77
+ lib/asciidoctor/callouts.rb
68
78
  lib/asciidoctor/debug.rb
69
79
  lib/asciidoctor/document.rb
70
80
  lib/asciidoctor/errors.rb
81
+ lib/asciidoctor/inline.rb
71
82
  lib/asciidoctor/lexer.rb
72
83
  lib/asciidoctor/list_item.rb
73
84
  lib/asciidoctor/reader.rb
74
- lib/asciidoctor/render_templates.rb
75
85
  lib/asciidoctor/renderer.rb
76
86
  lib/asciidoctor/section.rb
77
- lib/asciidoctor/string.rb
87
+ lib/asciidoctor/substituters.rb
88
+ lib/asciidoctor/table.rb
78
89
  lib/asciidoctor/version.rb
79
90
  noof.rb
80
91
  test/attributes_test.rb
92
+ test/blocks_test.rb
81
93
  test/document_test.rb
82
94
  test/fixtures/asciidoc.txt
83
95
  test/fixtures/asciidoc_index.txt
84
96
  test/fixtures/ascshort.txt
97
+ test/fixtures/dot.gif
98
+ test/fixtures/encoding.asciidoc
99
+ test/fixtures/include-file.asciidoc
85
100
  test/fixtures/list_elements.asciidoc
101
+ test/fixtures/tip.gif
86
102
  test/headers_test.rb
87
103
  test/lexer_test.rb
88
104
  test/links_test.rb
@@ -90,6 +106,9 @@ Gem::Specification.new do |s|
90
106
  test/paragraphs_test.rb
91
107
  test/preamble_test.rb
92
108
  test/reader_test.rb
109
+ test/renderer_test.rb
110
+ test/substitutions_test.rb
111
+ test/tables_test.rb
93
112
  test/test_helper.rb
94
113
  test/text_test.rb
95
114
  ]
@@ -1,4 +1,4 @@
1
- #!/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
 
3
3
  $:.unshift File.dirname(__FILE__) + '/../lib'
4
4
 
@@ -1,13 +1,11 @@
1
1
  require 'rubygems'
2
- require 'cgi'
3
- require 'erb'
4
- require 'tilt'
2
+ require 'strscan'
5
3
 
6
4
  $:.unshift(File.dirname(__FILE__))
7
- $:.unshift(File.join(File.dirname(__FILE__), '..', 'vendor'))
5
+ #$:.unshift(File.join(File.dirname(__FILE__), '..', 'vendor'))
8
6
 
9
7
  # Public: Methods for parsing Asciidoc input files and rendering documents
10
- # using erb templates.
8
+ # using eRuby templates.
11
9
  #
12
10
  # Asciidoc documents comprise a header followed by zero or more sections.
13
11
  # Sections are composed of blocks of content. For example:
@@ -47,27 +45,104 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'vendor'))
47
45
  # file.puts html
48
46
  # end
49
47
  module Asciidoctor
48
+
49
+ module SafeMode
50
+
51
+ # A safe mode level that disables any of the security features enforced
52
+ # by Asciidoctor (Ruby is still subject to its own restrictions).
53
+ UNSAFE = 0;
54
+
55
+ # A safe mode level that closely parallels safe mode in AsciiDoc. This value
56
+ # prevents access to files which reside outside of the parent directory of
57
+ # the source file and disables any macro other than the include::[] macro.
58
+ SAFE = 1;
59
+
60
+ # A safe mode level that disallows the document from attempting to read files
61
+ # from the file system and including the contents of them into the document.
62
+ # This value disallows use of the include::[] macro and the embedding of
63
+ # binary content (data uri), stylesheets and JavaScripts referenced by the
64
+ # document. (Asciidoctor and trusted extensions may still be allowed to embed
65
+ # trusted content into the document). Since Asciidoctor is aiming for wide
66
+ # adoption, this value is the default and is recommended for server-side
67
+ # deployments.
68
+ SECURE = 10;
69
+
70
+ # A planned safe mode level that disallows the use of passthrough macros and
71
+ # prevents the document from setting any known attributes, in addition to all
72
+ # the security features of SafeMode::SECURE
73
+ #
74
+ # Please note that this level is not currently implemented (and therefore not
75
+ # enforced)!
76
+ #PARANOID = 100;
77
+
78
+ end
79
+
50
80
  # The default document type
51
81
  # Can influence markup generated by render templates
52
82
  DEFAULT_DOCTYPE = 'article'
53
83
 
54
- LIST_CONTEXTS = [:ulist, :olist, :dlist]
84
+ # Backend determines the format of the rendered output, default to html5
85
+ DEFAULT_BACKEND = 'html5'
86
+
87
+ # Default page widths for calculating absolute widths
88
+ DEFAULT_PAGE_WIDTHS = {
89
+ 'docbook' => 425
90
+ }
91
+
92
+ LIST_CONTEXTS = [:ulist, :olist, :dlist, :colist]
93
+
94
+ NESTABLE_LIST_CONTEXTS = [:ulist, :olist, :dlist]
95
+
96
+ ORDERED_LIST_STYLES = [:arabic, :loweralpha, :lowerroman, :upperalpha, :upperroman]
97
+
98
+ ORDERED_LIST_MARKER_PATTERNS = {
99
+ :arabic => /\d+[\.>]/,
100
+ :loweralpha => /[a-z]\./,
101
+ :upperalpha => /[A-Z]\./,
102
+ :lowerroman => /[ivx]+\)/,
103
+ :upperroman => /[IVX]+\)/
104
+ }
55
105
 
56
106
  LIST_CONTINUATION = '+'
57
107
 
108
+ BLANK_LINES_PATTERN = /^\s*\n/
109
+
110
+ LINE_FEED_ENTITY = '&#10;' # or &#x0A;
111
+
58
112
  REGEXP = {
59
- # [[Foo]] (also allows, say, [[[]] or [[[Foo[f]], but I don't think it is supposed to (TODO))
60
- :anchor => /^\[(\[.+\])\]\s*$/,
113
+ # [[Foo]]
114
+ :anchor => /^\[\[([^\[\]]+)\]\]\s*$/,
61
115
 
62
116
  # Foowhatevs [[Bar]]
63
- :anchor_embedded => /^(.*)\[\[([^\]]+)\]\]\s*$/,
117
+ :anchor_embedded => /^(.*?)\s*\[\[([^\[\]]+)\]\]\s*$/,
118
+
119
+ # [[ref]] (anywhere inline)
120
+ :anchor_macro => /\\?\[\[([\w":].*?)\]\]/,
121
+
122
+ # matches any block delimiter:
123
+ # open, listing, example, literal, comment, quote, sidebar, passthrough, table
124
+ # NOTE position the most common blocks towards the front of the pattern
125
+ :any_blk => %r{^(?:\-\-|(?:\-|=|\.|/|_|\*|\+){4,}|[\|!]={3,})\s*$},
126
+
127
+ # optimization when scanning lines for blocks
128
+ # NOTE accessing the first element before calling ord is first Ruby 1.8.7 compat
129
+ :any_blk_ord => %w(- = . / _ * + | !).map {|c| c[0].ord },
130
+
131
+ # :foo: bar
132
+ :attr_assign => /^:([^:!]+):\s*(.*)\s*$/,
133
+
134
+ # {name?value}
135
+ :attr_conditional => /^\s*\{([^\?]+)\?\s*([^\}]+)\s*\}/,
64
136
 
65
137
  # + Attribute values treat lines ending with ' +' as a continuation,
66
138
  # not a line-break as elsewhere in the document, where this is
67
139
  # a forced line break. This should be the same regexp as :line_break,
68
140
  # below, but it gets its own entry because readability ftw, even
69
141
  # though repeating regexps ftl.
70
- :attr_continue => /^(.*)[[:blank:]]\+[[:blank:]]*$/,
142
+ :attr_continue => /^[[:blank:]]*(.*)[[:blank:]]\+[[:blank:]]*$/,
143
+
144
+ # :foo!:
145
+ :attr_delete => /^:([^:]+)!:\s*$/,
71
146
 
72
147
  # An attribute list above a block element
73
148
  #
@@ -75,33 +150,60 @@ module Asciidoctor
75
150
  # [quote, Adam Smith, Wealth of Nations]
76
151
  # Or can have name/value pairs
77
152
  # [NOTE, caption="Good to know"]
78
- :attr_list_blk => /^\[(\w.*)\]$/,
153
+ # Can be defined by an attribute
154
+ # [{lead}]
155
+ :blk_attr_list => /^\[([\w\{].*)\]$/,
156
+
157
+ # attribute list or anchor (indicates a paragraph break)
158
+ :attr_line => /^\[([\w\{].*|\[[^\[\]]+\])\]$/,
159
+
160
+ # attribute reference
161
+ # {foo}
162
+ :attr_ref => /(\\?)\{(\w|\w[\w\-]*\w)(\\?)\}/,
163
+
164
+ # The author info line the appears immediately following the document title
165
+ # John Doe <john@anonymous.com>
166
+ :author_info => /^\s*([\w\-]+)(?: +([\w\-]+))?(?: +([\w\-]+))?(?: +<([^>]+)>)?\s*$/,
79
167
 
80
168
  # [[[Foo]]] (does not suffer quite the same malady as :anchor, but almost. Allows [ but not ] in internal capture
81
- :biblio => /\[\[\[([^\]]+)\]\]\]/,
169
+ :biblio => /\[\[\[([^\[\]]+)\]\]\]/,
170
+
171
+ # callout reference inside literal text
172
+ # <1>
173
+ # special characters will already be replaced, hence their use in the regex
174
+ :callout_render => /\\?&lt;(\d+)&gt;/,
175
+ # ...but not while scanning
176
+ :callout_scan => /\\?<(\d+)>/,
82
177
 
83
178
  # <1> Foo
84
- :colist => /^(\<\d+\>)\s*(.*)/,
179
+ :colist => /^<?(\d+)> (.*)/,
85
180
 
86
181
  # ////
87
182
  # comment block
88
183
  # ////
89
- :comment_blk => /^\/{4,}\s*$/,
184
+ :comment_blk => %r{^/{4,}\s*$},
90
185
 
91
186
  # // (and then whatever)
92
- :comment => /^\/\/([^\/]|$)/,
187
+ :comment => %r{^//([^/].*|)$},
188
+
189
+ # 29
190
+ :digits => /^\d+$/,
93
191
 
94
- # foo:: || foo;;
95
- # Should be followed by a definition line, e.g.,
192
+ # foo:: || foo::: || foo:::: || foo;;
193
+ # Should be followed by a definition, on the same line...
194
+ # foo:: That which precedes 'bar' (see also, <<bar>>)
195
+ # ...or on a separate line
96
196
  # foo::
97
- # That which precedes 'bar' (see also, bar)
98
- :dlist => /^\s*(?:\[\[([^\]]*)\]\])?(\w.*?)(:{2,4}|;;)(\s+(.*))?$/,
197
+ # That which precedes 'bar' (see also, <<bar>>)
198
+ # The term may be an attribute reference
199
+ # {term_foo}:: {def_foo}
200
+ :dlist => /^\s*(.*?)(:{2,4}|;;)(?:[[:blank:]]+(.*))?$/,
99
201
  :dlist_siblings => {
100
202
  # (?:.*?[^:])? - a non-capturing group which grabs longest sequence of characters that doesn't end w/ colon
101
- '::' => /^\s*(?:\[\[([^\]]*)\]\])?(\w(?:.*[^:])?)(::)(\s+(.*))?$/,
102
- ':::' => /^\s*(?:\[\[([^\]]*)\]\])?(\w(?:.*[^:])?)(:::)(\s+(.*))?$/,
103
- '::::' => /^\s*(?:\[\[([^\]]*)\]\])?(\w(?:.*[^:])?)(::::)(\s+(.*))?$/,
104
- ';;' => /^\s*(?:\[\[([^\]]*)\]\])?(\w.*)(;;)(\s+(.*))?$/
203
+ '::' => /^\s*((?:.*[^:])?)(::)(?:[[:blank:]]+(.*))?$/,
204
+ ':::' => /^\s*((?:.*[^:])?)(:::)(?:[[:blank:]]+(.*))?$/,
205
+ '::::' => /^\s*((?:.*[^:])?)(::::)(?:[[:blank:]]+(.*))?$/,
206
+ ';;' => /^\s*(.*)(;;)(?:[[:blank:]]+(.*))?$/
105
207
  },
106
208
  # ====
107
209
  :example => /^={4,}\s*$/,
@@ -109,23 +211,11 @@ module Asciidoctor
109
211
  # image::filename.png[Caption]
110
212
  :image_blk => /^image::(\S+?)\[(.*?)\]$/,
111
213
 
112
- # == Foo
113
- # ^ yields a level 2 title
114
- #
115
- # == Foo ==
116
- # ^ also yields a level 2 title
117
- #
118
- # both equivalent to this two-line version:
119
- # Foo
120
- # ~~~
121
- #
122
- # match[1] is the delimiter, whose length determines the level
123
- # match[2] is the title itself
124
- # match[3] is an optional repeat of the delimiter, which is dropped
125
- :level_title => /^(={1,5})\s+(\S.*?)\s*(\s\1)?$/,
214
+ # image:filename.png[Alt]
215
+ :image_macro => /\\?image:([^\[]+)(?:\[([^\]]*)\])/,
126
216
 
127
- # ====== || ------ || ~~~~~~ || ^^^^^^ || ++++++
128
- :line => /^([=\-~^\+])+\s*$/,
217
+ # whitespace at the beginning of the line
218
+ :leading_blanks => /^([[:blank:]]*)/,
129
219
 
130
220
  # + From the Asciidoc User Guide: "A plus character preceded by at
131
221
  # least one space character at the end of a non-blank line forces
@@ -134,44 +224,138 @@ module Asciidoctor
134
224
  # + (would not match because there's no space before +)
135
225
  # + (would match and capture '')
136
226
  # Foo + (would and capture 'Foo')
137
- :line_break => /([[:blank:]])\+[[:blank:]]*$/,
227
+ :line_break => /^(.*)[[:blank:]]\+[[:blank:]]*$/,
228
+
229
+ # inline link and some inline link macro
230
+ # FIXME revisit!
231
+ :link_inline => %r{(^|link:|\s|>|&lt;|[\(\)\]])(\\?https?://[^\[ ]*[^\. \)\[])(?:\[((?:\\\]|[^\]])*?)\])?},
232
+
233
+ # inline link macro
234
+ # link:path[label]
235
+ :link_macro => /\\?link:([^\[ ]+)(?:\[((?:\\\]|[^\]])*?)\])/,
138
236
 
139
237
  # ----
140
238
  :listing => /^\-{4,}\s*$/,
141
239
 
142
240
  # ....
143
- :lit_blk => /^\.{4,}\s*$/,
241
+ :literal => /^\.{4,}\s*$/,
144
242
 
145
243
  # <TAB>Foo or one-or-more-spaces-or-tabs then whatever
146
- :lit_par => /^([ \t]+.*)$/,
147
-
148
- # "Wooble" || Wooble
149
- :name => /^(["A-Za-z].*)\s*$/, # I believe this fails to require " chars to be paired (TODO)
244
+ :lit_par => /^([[:blank:]]+.*)$/,
150
245
 
151
246
  # --
152
- :oblock => /^\-\-\s*$/,
247
+ :open_blk => /^\-\-\s*$/,
248
+
249
+ # . Foo (up to 5 consecutive dots)
250
+ # 1. Foo (arabic, default)
251
+ # a. Foo (loweralpha)
252
+ # A. Foo (upperalpha)
253
+ # i. Foo (lowerroman)
254
+ # I. Foo (upperroman)
255
+ :olist => /^\s*(\d+\.|[a-z]\.|[ivx]+\)|\.{1,5}) +(.*)$/i,
153
256
 
154
- # 1.Foo || 1. Foo || . Foo
155
- :olist => /^\s*(\d+\.|\. )(.*)$/,
257
+ # ++++
258
+ :pass => /^\+{4,}\s*$/,
259
+
260
+ # inline passthrough macros
261
+ # +++text+++
262
+ # $$text$$
263
+ # pass:quotes[text]
264
+ :pass_macro => /\\?(?:(\+{3}|\${2})(.*?)\1|pass:([a-z,]*)\[((?:\\\]|[^\]])*?)\])/m,
265
+
266
+ # passthrough macro allowed in value of attribute assignment
267
+ # pass:[text]
268
+ :pass_macro_basic => /^pass:([a-z,]*)\[(.*)\]$/,
269
+
270
+ # inline literal passthrough macro
271
+ # `text`
272
+ :pass_lit => /(^|[^`\w])(\\?`([^`\s]|[^`\s].*?\S)`)(?![`\w])/m,
273
+
274
+ # placeholder for extracted passthrough text
275
+ :pass_placeholder => /\x0(\d+)\x0/,
156
276
 
157
277
  # ____
158
278
  :quote => /^_{4,}\s*$/,
159
279
 
280
+ # The document revision info line the appears immediately following the
281
+ # document title author info line, if present
282
+ # v1.0, 2013-01-01: Ring in the new year release
283
+ :revision_info => /^\s*(?:\D*(.*?),)?(?:\s*(.*?))(?:\s*:\s*(.*)\s*)?$/,
284
+
160
285
  # '''
161
286
  :ruler => /^'{3,}\s*$/,
162
287
 
163
288
  # ****
164
289
  :sidebar_blk => /^\*{4,}\s*$/,
165
290
 
166
- # and blah blah blah
167
- # ^^^^ <--- whitespace
168
- :starts_with_whitespace => /\s+(.+)\s+\+\s*$/,
291
+ # \' within a word
292
+ :single_quote_esc => /(\w)\\'(\w)/,
293
+ # an alternative if our backend generated single-quoted html/xml attributes
294
+ #:single_quote_esc => /(\w|=)\\'(\w)/,
295
+
296
+ # |===
297
+ # |table
298
+ # |===
299
+ :table => /^\|={3,}\s*$/,
300
+
301
+ # !===
302
+ # !table
303
+ # !===
304
+ :table_nested => /^!={3,}\s*$/,
305
+
306
+ # 1*h,2*,^3e
307
+ :table_colspec => /^(?:(\d+)\*)?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?(\d+)?([a-z])?$/,
308
+
309
+ # 2.3+<.>m
310
+ # TODO might want to use step-wise scan rather than this mega-regexp
311
+ :table_cellspec => {
312
+ :start => /^[[:blank:]]*(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?\|/,
313
+ :end => /[[:blank:]]+(?:(\d+(?:\.\d*)?|(?:\d*\.)?\d+)([*+]))?([<^>](?:\.[<^>]?)?|(?:[<^>]?\.)?[<^>])?([a-z])?$/
314
+ },
169
315
 
170
316
  # .Foo but not . Foo or ..Foo
171
- :title => /^\.([^\s\.].*)\s*$/,
317
+ :blk_title => /^\.([^\s\.].*)\s*$/,
172
318
 
173
- # * Foo || - Foo
174
- :ulist => /^ \s* (- | \*{1,5}) \s+ (.*) $/x
319
+ # == Foo
320
+ # ^ yields a level 2 title
321
+ #
322
+ # == Foo ==
323
+ # ^ also yields a level 2 title
324
+ #
325
+ # both equivalent to this two-line version:
326
+ # Foo
327
+ # ~~~
328
+ #
329
+ # match[1] is the delimiter, whose length determines the level
330
+ # match[2] is the title itself
331
+ # match[3] is an optional repeat of the delimiter, which is dropped
332
+ :section_title => /^(={1,5})\s+(\S.*?)\s*(?:\[\[([^\[]+)\]\]\s*)?(\s\1)?$/,
333
+
334
+ # does not begin with a dot and has at least one alphanumeric character
335
+ :section_name => /^((?=.*\w+.*)[^\.].*?)\s*$/,
336
+
337
+ # ====== || ------ || ~~~~~~ || ^^^^^^ || ++++++
338
+ :section_underline => /^([=\-~^\+])+\s*$/,
339
+
340
+ # * Foo (up to 5 consecutive asterisks)
341
+ # - Foo
342
+ :ulist => /^ \s* (- | \*{1,5}) \s+ (.*) $/x,
343
+
344
+ # inline xref macro
345
+ # <<id,reftext>> (special characters have already been escaped, hence the entity references)
346
+ # xref:id[reftext]
347
+ :xref_macro => /\\?(?:&lt;&lt;([\w":].*?)&gt;&gt;|xref:([\w":].*?)\[(.*?)\])/m,
348
+
349
+ # ifdef::basebackend-html[]
350
+ # ifndef::theme[]
351
+ :ifdef_macro => /^(ifdef|ifndef)::([^\[]+)\[\]/,
352
+
353
+ # endif::theme[]
354
+ # endif::basebackend-html[]
355
+ :endif_macro => /^endif::/,
356
+
357
+ # include::chapter1.ad[]
358
+ :include_macro => /^\\?include::([^\[]+)\[\]\s*\n?\z/
175
359
  }
176
360
 
177
361
  ADMONITION_STYLES = ['NOTE', 'TIP', 'IMPORTANT', 'WARNING', 'CAUTION']
@@ -184,18 +368,20 @@ module Asciidoctor
184
368
  'caret' => '^',
185
369
  'asterisk' => '*',
186
370
  'tilde' => '~',
187
- 'litdd' => '--',
188
- 'plus' => '+',
371
+ 'plus' => '&#43;',
189
372
  'apostrophe' => '\'',
190
373
  'backslash' => '\\',
191
374
  'backtick' => '`',
192
375
  'empty' => '',
193
376
  'sp' => ' ',
377
+ 'space' => ' ',
194
378
  'two-colons' => '::',
195
379
  'two-semicolons' => ';;',
196
380
  'nbsp' => '&#160;',
197
381
  'deg' => '&#176;',
198
382
  'zwsp' => '&#8203;',
383
+ 'quot' => '&#34;',
384
+ 'apos' => '&#39;',
199
385
  'lsquo' => '&#8216;',
200
386
  'rsquo' => '&#8217;',
201
387
  'ldquo' => '&#8220;',
@@ -203,7 +389,7 @@ module Asciidoctor
203
389
  'wj' => '&#8288;',
204
390
  'amp' => '&',
205
391
  'lt' => '<',
206
- 'gt' => '>',
392
+ 'gt' => '>'
207
393
  }
208
394
  )
209
395
 
@@ -213,20 +399,122 @@ module Asciidoctor
213
399
  '&' => '&amp;'
214
400
  }
215
401
 
216
- HTML_ELEMENTS = {
217
- 'br-asciidoctor' => '<br/>'
218
- }
219
-
402
+ SPECIAL_CHARS_PATTERN = /[#{SPECIAL_CHARS.keys.join}]/
403
+
404
+ # unconstrained quotes:: can appear anywhere
405
+ # constrained quotes:: must be bordered by non-word characters
406
+ # NOTE these substituions are processed in the order they appear here and
407
+ # the order in which they are replaced is important
408
+ QUOTE_SUBS = [
409
+
410
+ # **strong**
411
+ [:strong, :unconstrained, /\\?(?:\[([^\]]+?)\])?\*\*(.+?)\*\*/m],
412
+
413
+ # *strong*
414
+ [:strong, :constrained, /(^|[^\w;:}])(?:\[([^\]]+?)\])?\*(\S|\S.*?\S)\*(?=\W|$)/m],
415
+
416
+ # ``double-quoted''
417
+ [:double, :constrained, /(^|[^\w;:}])(?:\[([^\]]+?)\])?``(\S|\S.*?\S)''(?=\W|$)/m],
418
+
419
+ # 'emphasis'
420
+ [:emphasis, :constrained, /(^|[^\w;:}])(?:\[([^\]]+?)\])?'(\S|\S.*?\S)'(?=\W|$)/m],
421
+
422
+ # `single-quoted'
423
+ [:single, :constrained, /(^|[^\w;:}])(?:\[([^\]]+?)\])?`(\S|\S.*?\S)'(?=\W|$)/m],
424
+
425
+ # ++monospaced++
426
+ [:monospaced, :unconstrained, /\\?(?:\[([^\]]+?)\])?\+\+(.+?)\+\+/m],
427
+
428
+ # +monospaced+
429
+ [:monospaced, :constrained, /(^|[^\w;:}])(?:\[([^\]]+?)\])?\+(\S|\S.*?\S)\+(?=\W|$)/m],
430
+
431
+ # __emphasis__
432
+ [:emphasis, :unconstrained, /\\?(?:\[([^\]]+?)\])?\_\_(.+?)\_\_/m],
433
+
434
+ # _emphasis_
435
+ [:emphasis, :constrained, /(^|[^\w;:}])(?:\[([^\]]+?)\])?_(\S|\S.*?\S)_(?=\W|$)/m],
436
+
437
+ # ##unquoted##
438
+ [:none, :unconstrained, /\\?(?:\[([^\]]+?)\])?##(.+?)##/m],
439
+
440
+ # #unquoted#
441
+ [:none, :constrained, /(^|[^\w;:}])(?:\[([^\]]+?)\])?#(\S|\S.*?\S)#(?=\W|$)/m],
442
+
443
+ # ^superscript^
444
+ [:superscript, :unconstrained, /\\?(?:\[([^\]]+?)\])?\^(.+?)\^/m],
445
+
446
+ # ~subscript~
447
+ [:subscript, :unconstrained, /\\?(?:\[([^\]]+?)\])?\~(.+?)\~/m]
448
+ ]
449
+
450
+ # NOTE in Ruby 1.8.7, [^\\] does not match start of line,
451
+ # so we need to match it explicitly
452
+ # order is significant
453
+ REPLACEMENTS = [
454
+ # (C)
455
+ [/(^|[^\\])\(C\)/, '\1&#169;'],
456
+ # (R)
457
+ [/(^|[^\\])\(R\)/, '\1&#174;'],
458
+ # (TM)
459
+ [/(^|[^\\])\(TM\)/, '\1&#8482;'],
460
+ # foo -- bar
461
+ [/ -- /, '&#8201;&#8212;&#8201;'],
462
+ # foo--bar
463
+ [/(\w)--(?=\w)/, '\1&#8212;'],
464
+ # ellipsis
465
+ [/(^|[^\\])\.\.\./, '\1&#8230;'],
466
+ # single quotes
467
+ [/(\w)'(\w)/, '\1&#8217;\2'],
468
+ # escaped single quotes
469
+ [/(\w)\\'(\w)/, '\1\'\2'],
470
+ # and so on...
471
+
472
+ # restore entities; TODO needs cleanup
473
+ [/&amp;(#[a-z0-9]+;)/i, '&\1']
474
+ ]
475
+
476
+ # Internal: Prior to invoking Kernel#require, issues a warning urging a
477
+ # manual require if running in a threaded environment.
478
+ #
479
+ # name - the String name of the library to require.
480
+ #
481
+ # returns nothing
482
+ def self.require_library(name)
483
+ if Thread.list.size > 1
484
+ main_script = "#{name}.rb"
485
+ main_script_path_segment = "/#{name}.rb"
486
+ if !$LOADED_FEATURES.detect {|p| p == main_script || p.end_with?(main_script_path_segment) }.nil?
487
+ return
488
+ else
489
+ warn "WARN: asciidoctor is autoloading '#{name}' in threaded environment. " +
490
+ "The use of an explicit require '#{name}' statement is recommended."
491
+ end
492
+ end
493
+ require name
494
+ nil
495
+ end
496
+
497
+ # modules
498
+ require 'asciidoctor/substituters'
499
+
500
+ # abstract classes
501
+ require 'asciidoctor/abstract_node'
502
+ require 'asciidoctor/abstract_block'
503
+
504
+ # concrete classes
505
+ require 'asciidoctor/attribute_list'
506
+ require 'asciidoctor/backends/base_template'
220
507
  require 'asciidoctor/block'
508
+ require 'asciidoctor/callouts'
221
509
  require 'asciidoctor/debug'
222
510
  require 'asciidoctor/document'
223
511
  require 'asciidoctor/errors'
512
+ require 'asciidoctor/inline'
224
513
  require 'asciidoctor/lexer'
225
514
  require 'asciidoctor/list_item'
226
515
  require 'asciidoctor/reader'
227
- require 'asciidoctor/render_templates'
228
516
  require 'asciidoctor/renderer'
229
517
  require 'asciidoctor/section'
230
- require 'asciidoctor/string'
518
+ require 'asciidoctor/table'
231
519
  require 'asciidoctor/version'
232
520
  end