asciidoctor 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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