asciidoctor 0.0.5 → 0.0.6

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.

data/README.asciidoc ADDED
@@ -0,0 +1,156 @@
1
+ [float]
2
+ Asciidoctor
3
+ ===========
4
+ :gitscm-next: https://github.com/github/gitscm-next
5
+ :tilt: https://github.com/rtomayko/tilt
6
+ :freesoftware: http://www.fsf.org/licensing/essays/free-sw.html
7
+ :issues: https://github.com/erebor/asciidoctor/issues
8
+ :gist: https://gist.github.com
9
+ :fork: http://help.github.com/fork-a-repo/
10
+ :branch: http://learn.github.com/p/branching.html
11
+ :pr: http://help.github.com/send-pull-requests/
12
+ :license: https://github.com/erebor/asciidoctor/blob/master/LICENSE
13
+
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!').
19
+
20
+ Asciidoctor uses simple built-in ERB templates to style the output in
21
+ a way that roughly matches the default HTML output of the native
22
+ Python processor. You can override this behavior by providing
23
+ {tilt}[Tilt]-compatible templates. See the xref:usage[Usage section]
24
+ for more details.
25
+
26
+ Asciidoctor currently works with Ruby 1.8.7 and 1.9.3, though I don't
27
+ know of any reason it shouldn't work with more exotic Ruby versions,
28
+ and would welcome help in testing that out.
29
+
30
+ The initial code from which Asciidoctor started was from the
31
+ {gitscm-next}[Git SCM site repo].
32
+
33
+ == Installation
34
+
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.
39
+
40
+ To install the gem:
41
+
42
+ gem install asciidoctor
43
+
44
+ Or if you prefer bundler:
45
+
46
+ bundle install asciidoctor
47
+
48
+ == Usage
49
+
50
+ To render a file containing AsciiDoc markup to HTML:
51
+
52
+ lines = File.readlines('your_file.asciidoc')
53
+ doc = Asciidoctor::Document.new(lines)
54
+ html = doc.render
55
+ File.open('your_file.html', 'w+') do |file|
56
+ file.puts html
57
+ end
58
+
59
+ To render an AsciiDoc-formatted string:
60
+
61
+ doc = Asciidoctor::Document.new("*This* is it.")
62
+ puts doc.render
63
+
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.
71
+
72
+ doc = Asciidoctor::Document.new("*This* is it.", :template_dir => 'templates')
73
+ puts doc.render
74
+
75
+ 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`.
85
+
86
+ For more usage examples, see the test suite.
87
+
88
+ == Contributing
89
+
90
+ In the spirit of {freesoftware}[free software], 'everyone' is
91
+ encouraged to help improve this project.
92
+
93
+ Here are some ways *you* can contribute:
94
+
95
+ * by using alpha, beta, and prerelease versions
96
+ * by reporting bugs
97
+ * by suggesting new features
98
+ * by writing or editing documentation
99
+ * by writing specifications
100
+ * by writing code ('No patch is too small.' Fix typos, add comments,
101
+ clean up inconsistent whitespace, etc.)
102
+ * by refactoring code
103
+ * by fixing {issues}[issues]
104
+ * by reviewing patches
105
+
106
+ == Submitting an Issue
107
+
108
+ We use the {issues}[GitHub issue tracker] associated with this project
109
+ to track bugs and features. Before submitting a bug report or feature
110
+ request, check to make sure it hasn't already been submitted. When
111
+ submitting a bug report, please include a {gist}[Gist] that includes
112
+ any details that may help reproduce the bug, including your gem
113
+ version, Ruby version, and operating system.
114
+
115
+ Most importantly, since Asciidoctor is a text processor, reproducing
116
+ most bugs requires that we have some snippet of text on which
117
+ Asciidoctor exhibits the bad behavior.
118
+
119
+ An ideal bug report would include a pull request with failing specs.
120
+
121
+ == Submitting a Pull Request
122
+
123
+ . {fork}[Fork the repository].
124
+ . {branch}[Create a topic branch].
125
+ . Add tests for your unimplemented feature or bug fix.
126
+ . Run `bundle exec rake`. If your tests pass, return to step 3.
127
+ . Implement your feature or bug fix.
128
+ . Run `bundle exec rake`. If your tests fail, return to step 5.
129
+ . Add documentation for your feature or bug fix.
130
+ . If your changes are not 100% documented, go back to step 7.
131
+ . Add, commit, and push your changes.
132
+ . {pr}[Submit a pull request].
133
+
134
+
135
+ == Supported Ruby Versions
136
+
137
+ This library aims to support the following Ruby implementations:
138
+
139
+ * Ruby 1.8.7
140
+ * Ruby 1.9.3
141
+
142
+ If something doesn't work on one of these interpreters, it should be
143
+ considered a bug.
144
+
145
+ If you would like this library to support another Ruby version, you
146
+ may volunteer to be a maintainer. Being a maintainer entails making
147
+ sure all tests run and pass on that implementation. When something
148
+ breaks on your implementation, you will be personally responsible for
149
+ providing patches in a timely fashion. If critical issues for a
150
+ particular implementation exist at the time of a major release,
151
+ support for that Ruby version may be dropped.
152
+
153
+ == Copyright
154
+
155
+ Copyright (c) 2012 Ryan Waldron.
156
+ See {license}[LICENSE] for details.
data/asciidoctor.gemspec CHANGED
@@ -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.5'
17
- s.date = '2012-12-11'
16
+ s.version = '0.0.6'
17
+ s.date = '2012-12-17'
18
18
  s.rubyforge_project = 'asciidoctor'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -59,7 +59,7 @@ Gem::Specification.new do |s|
59
59
  # = MANIFEST =
60
60
  s.files = %w[
61
61
  LICENSE
62
- README.md
62
+ README.asciidoc
63
63
  Rakefile
64
64
  asciidoctor.gemspec
65
65
  bin/asciidoctor
@@ -86,8 +86,9 @@ Gem::Specification.new do |s|
86
86
  test/headers_test.rb
87
87
  test/lexer_test.rb
88
88
  test/links_test.rb
89
- test/list_elements_test.rb
89
+ test/lists_test.rb
90
90
  test/paragraphs_test.rb
91
+ test/preamble_test.rb
91
92
  test/reader_test.rb
92
93
  test/test_helper.rb
93
94
  test/text_test.rb
data/lib/asciidoctor.rb CHANGED
@@ -47,6 +47,14 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'vendor'))
47
47
  # file.puts html
48
48
  # end
49
49
  module Asciidoctor
50
+ # The default document type
51
+ # Can influence markup generated by render templates
52
+ DEFAULT_DOCTYPE = 'article'
53
+
54
+ LIST_CONTEXTS = [:ulist, :olist, :dlist]
55
+
56
+ LIST_CONTINUATION = '+'
57
+
50
58
  REGEXP = {
51
59
  # [[Foo]] (also allows, say, [[[]] or [[[Foo[f]], but I don't think it is supposed to (TODO))
52
60
  :anchor => /^\[(\[.+\])\]\s*$/,
@@ -59,14 +67,19 @@ module Asciidoctor
59
67
  # a forced line break. This should be the same regexp as :line_break,
60
68
  # below, but it gets its own entry because readability ftw, even
61
69
  # though repeating regexps ftl.
62
- :attr_continue => /(.*)(?:^|\s)\+$/,
70
+ :attr_continue => /^(.*)[[:blank:]]\+[[:blank:]]*$/,
71
+
72
+ # An attribute list above a block element
73
+ #
74
+ # Can be strictly positional:
75
+ # [quote, Adam Smith, Wealth of Nations]
76
+ # Or can have name/value pairs
77
+ # [NOTE, caption="Good to know"]
78
+ :attr_list_blk => /^\[(\w.*)\]$/,
63
79
 
64
80
  # [[[Foo]]] (does not suffer quite the same malady as :anchor, but almost. Allows [ but not ] in internal capture
65
81
  :biblio => /\[\[\[([^\]]+)\]\]\]/,
66
82
 
67
- # [caption="Foo"]
68
- :caption => /^\[caption=\"([^\"]+)\"\]/,
69
-
70
83
  # <1> Foo
71
84
  :colist => /^(\<\d+\>)\s*(.*)/,
72
85
 
@@ -76,25 +89,40 @@ module Asciidoctor
76
89
  :comment_blk => /^\/{4,}\s*$/,
77
90
 
78
91
  # // (and then whatever)
79
- :comment => /^\/\/[^\/]/,
92
+ :comment => /^\/\/([^\/]|$)/,
80
93
 
81
94
  # foo:: || foo;;
82
95
  # Should be followed by a definition line, e.g.,
83
96
  # foo::
84
97
  # That which precedes 'bar' (see also, bar)
85
- :dlist => /^(\s*)(\S.*)(::|;;)\s*$/,
86
-
98
+ :dlist => /^\s*(?:\[\[([^\]]*)\]\])?(\w.*?)(:{2,4}|;;)(\s+(.*))?$/,
99
+ :dlist_siblings => {
100
+ # (?:.*?[^:])? - 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+(.*))?$/
105
+ },
87
106
  # ====
88
107
  :example => /^={4,}\s*$/,
89
108
 
109
+ # image::filename.png[Caption]
110
+ :image_blk => /^image::(\S+?)\[(.*?)\]$/,
111
+
90
112
  # == Foo
91
- # Yields a Level 2 title, so exactly the same as
92
- # Foo
93
- # ~~~
94
- # would yield. match[1] is the == sequence, whose
95
- # length determines the level, and match[2] is the
96
- # title itself.
97
- :level_title => /^(={2,5})\s+(\S.*)\s*$/,
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)?$/,
98
126
 
99
127
  # ====== || ------ || ~~~~~~ || ^^^^^^ || ++++++
100
128
  :line => /^([=\-~^\+])+\s*$/,
@@ -103,26 +131,14 @@ module Asciidoctor
103
131
  # least one space character at the end of a non-blank line forces
104
132
  # a line break. It generates a line break (br) tag for HTML outputs.
105
133
  #
106
- # This is the correct regexp to match what the User Guide actually
107
- # says to do:
108
- # :line_break => /^(.*(?:\S+)+.*)\s\+$/,
109
- #
110
- # But the regexp we're using (below), is what asciidoc *actually*
111
- # does for HTML output, courtesy of the default html4.conf file (under
112
- # the [replacements2] section).
113
- #
114
134
  # + (would not match because there's no space before +)
115
135
  # + (would match and capture '')
116
136
  # Foo + (would and capture 'Foo')
117
- :line_break => /^(.*)\s\+$/,
137
+ :line_break => /([[:blank:]])\+[[:blank:]]*$/,
118
138
 
119
139
  # ----
120
140
  :listing => /^\-{4,}\s*$/,
121
141
 
122
- # [source, ruby]
123
- # Treats the next paragraph as a :listing block
124
- :listing_source => /^\[source,\s*([^\]]+)\]\s*$/,
125
-
126
142
  # ....
127
143
  :lit_blk => /^\.{4,}\s*$/,
128
144
 
@@ -132,9 +148,6 @@ module Asciidoctor
132
148
  # "Wooble" || Wooble
133
149
  :name => /^(["A-Za-z].*)\s*$/, # I believe this fails to require " chars to be paired (TODO)
134
150
 
135
- # [NOTE]
136
- :note => /^\[NOTE\]\s*$/,
137
-
138
151
  # --
139
152
  :oblock => /^\-\-\s*$/,
140
153
 
@@ -158,12 +171,11 @@ module Asciidoctor
158
171
  :title => /^\.([^\s\.].*)\s*$/,
159
172
 
160
173
  # * Foo || - Foo
161
- :ulist => /^ \s* (- | \*{1,5}) \s+ (.*) $/x,
162
-
163
- # [verse]
164
- :verse => /^\[verse\]\s*$/
174
+ :ulist => /^ \s* (- | \*{1,5}) \s+ (.*) $/x
165
175
  }
166
176
 
177
+ ADMONITION_STYLES = ['NOTE', 'TIP', 'IMPORTANT', 'WARNING', 'CAUTION']
178
+
167
179
  INTRINSICS = Hash.new{|h,k| STDERR.puts "Missing intrinsic: #{k.inspect}"; "{#{k}}"}.merge(
168
180
  'startsb' => '[',
169
181
  'endsb' => ']',
@@ -9,6 +9,12 @@ class Asciidoctor::Block
9
9
  # Public: Get the Symbol context for this section block.
10
10
  attr_reader :context
11
11
 
12
+ # Public: Create alias for context to be consistent w/ AsciiDoc
13
+ alias :blockname :context
14
+
15
+ # Public: Get the Hash of attributes for this block
16
+ attr_reader :attributes
17
+
12
18
  # Public: Get the Array of sub-blocks for this section block.
13
19
  attr_reader :blocks
14
20
 
@@ -17,6 +23,7 @@ class Asciidoctor::Block
17
23
 
18
24
  # Public: Get/Set the String section anchor name.
19
25
  attr_accessor :anchor
26
+ alias :id :anchor
20
27
 
21
28
  # Public: Get/Set the Integer block level (for nested elements, like
22
29
  # list elements).
@@ -41,7 +48,7 @@ class Asciidoctor::Block
41
48
  @parent = parent
42
49
  @context = context
43
50
  @buffer = buffer
44
-
51
+ @attributes = {}
45
52
  @blocks = []
46
53
  end
47
54
 
@@ -51,9 +58,23 @@ class Asciidoctor::Block
51
58
  @document = (@parent.is_a?(Asciidoctor::Document) ? @parent : @parent.document)
52
59
  end
53
60
 
61
+ def attr(name, default = nil)
62
+ default.nil? ? @attributes.fetch(name.to_s, self.document.attr(name)) :
63
+ @attributes.fetch(name.to_s, self.document.attr(name, default))
64
+ end
65
+
66
+ def attr?(name)
67
+ @attributes.has_key?(name.to_s) || self.document.attr?(name)
68
+ end
69
+
70
+ def update_attributes(attributes)
71
+ @attributes.update(attributes)
72
+ end
73
+
54
74
  # Public: Get the Asciidoctor::Renderer instance being used for the ancestor
55
75
  # Asciidoctor::Document instance.
56
76
  def renderer
77
+ # wouldn't @parent.renderer work here? I believe so
57
78
  document.renderer
58
79
  end
59
80
 
@@ -128,48 +149,30 @@ class Asciidoctor::Block
128
149
  # * super/sub script
129
150
  def content
130
151
 
131
- Asciidoctor.debug "For the record, buffer is:"
132
- Asciidoctor.debug @buffer.inspect
152
+ #Asciidoctor.debug "For the record, buffer is:"
153
+ #Asciidoctor.debug @buffer.inspect
133
154
 
134
155
  case @context
135
- when :dlist
136
- @buffer.map do |dt, dd|
137
- if !dt.anchor.nil? && !dt.anchor.empty?
138
- html_dt = "<a id=#{dt.anchor}></a>" + htmlify(dt.content)
139
- else
140
- html_dt = htmlify(dt.content)
141
- end
142
- if dd.content.empty?
143
- html_dd = ''
144
- else
145
- html_dd = "<p>#{htmlify(dd.content)}</p>"
146
- end
147
- html_dd += dd.blocks.map{|block| block.render}.join
148
-
149
- [html_dt, html_dd]
150
- end
151
- when :oblock, :quote
156
+ when :preamble, :oblock, :example, :sidebar
152
157
  blocks.map{|block| block.render}.join
153
- when :olist, :colist
158
+ when :colist
154
159
  @buffer.map do |li|
155
- htmlify(li.content) + li.blocks.map{|block| block.render}.join
156
- end
157
- when :ulist
158
- @buffer.map do |element|
159
- if element.is_a? Asciidoctor::ListItem
160
- element.content = sub_attributes(element.content)
161
- end
162
- # TODO - not sure why tests work the same whether or not this is commented out.
163
- # I think that I am likely not yet testing unordered list items with no block
164
- # content. Still and all, it seems like this should be all done by list_item.render .
165
- element.render # + element.blocks.map{|block| block.render}.join
160
+ htmlify(li.text) + li.blocks.map{|block| block.render}.join
166
161
  end
162
+ # lists get iterated in template
163
+ # list items recurse into this block when their text and content methods are called
164
+ when :ulist, :olist, :dlist
165
+ @buffer
167
166
  when :listing
168
- @buffer.map{|l| CGI.escapeHTML(l).gsub(/(<\d+>)/,'<b>\1</b>')}.join
167
+ sub_special_chars(@buffer.join).gsub(/&lt;(\d+)&gt;/, '<b>\1</b>')
169
168
  when :literal
170
- htmlify( @buffer.join.gsub( '*', '{asterisk}' ).gsub( '\'', '{apostrophe}' ))
171
- when :verse
172
- htmlify( sub_attributes(@buffer).map{ |l| l.strip }.join( "\n" ) )
169
+ sub_special_chars(@buffer.join)
170
+ when :quote, :verse, :admonition
171
+ if !@buffer.nil?
172
+ htmlify(sub_attributes(@buffer).map{ |l| l.strip }.join( "\n" ))
173
+ else
174
+ blocks.map{|block| block.render}.join
175
+ end
173
176
  else
174
177
  lines = sub_attributes(@buffer).map do |line|
175
178
  line.strip
@@ -195,9 +198,9 @@ class Asciidoctor::Block
195
198
  f = sub_special_chars(line)
196
199
  # gsub! doesn't have lookbehind, so we have to capture and re-insert
197
200
  f = f.gsub(/ (^|[^\\]) \{ (\w([\w\-_]+)?\w) \} /x) do
198
- if self.document.defines.has_key?($2)
199
- # Substitute from user defines first
200
- $1 + self.document.defines[$2]
201
+ if self.document.attributes.has_key?($2)
202
+ # Substitute from user attributes first
203
+ $1 + self.document.attributes[$2]
201
204
  elsif Asciidoctor::INTRINSICS.has_key?($2)
202
205
  # Then do intrinsics
203
206
  $1 + Asciidoctor::INTRINSICS[$2]
@@ -215,7 +218,7 @@ class Asciidoctor::Block
215
218
  Asciidoctor.debug "#{__method__} -> Processed line: #{f}"
216
219
  f
217
220
  end
218
- Asciidoctor.debug "#{__method__} -> result looks like #{result.inspect}"
221
+ #Asciidoctor.debug "#{__method__} -> result looks like #{result.inspect}"
219
222
  result.reject! {|l| l =~ /\{ZZZZZ\}/}
220
223
 
221
224
  if return_string
@@ -242,7 +245,7 @@ class Asciidoctor::Block
242
245
  end
243
246
  end
244
247
  end
245
- Asciidoctor.debug "#{__method__} -> result looks like #{result.inspect}"
248
+ #Asciidoctor.debug "#{__method__} -> result looks like #{result.inspect}"
246
249
  result.reject! {|l| l =~ /\{ZZZZZ\}/}
247
250
 
248
251
  if return_string
@@ -251,6 +254,20 @@ class Asciidoctor::Block
251
254
  result
252
255
  end
253
256
 
257
+ # Public: Append a sub-block to this section block
258
+ #
259
+ # block - The new sub-block.
260
+ #
261
+ # block = Block.new(parent, :preamble)
262
+ #
263
+ # block << Block.new(block, :paragraph, 'p1')
264
+ # block << Block.new(block, :paragraph, 'p2')
265
+ # block.blocks
266
+ # => ["p1", "p2"]
267
+ def <<(block)
268
+ @blocks << block
269
+ end
270
+
254
271
  private
255
272
 
256
273
  # Private: Return a String HTML version of the source string, with
@@ -284,7 +301,7 @@ class Asciidoctor::Block
284
301
  end
285
302
 
286
303
  html.gsub!(Asciidoctor::REGEXP[:biblio], '<a name="\1">[\1]</a>')
287
- html.gsub!(Asciidoctor::REGEXP[:ruler], '<hr>\n')
304
+ html.gsub!(Asciidoctor::REGEXP[:ruler], "<hr>\n")
288
305
  html.gsub!(/``([^`']*)''/m, '&ldquo;\1&rdquo;')
289
306
  html.gsub!(/(?:\s|^)`([^`']*)'/m, '&lsquo;\1&rsquo;')
290
307