asciidoctor 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.4'
17
- s.date = '2012-08-14'
16
+ s.version = '0.0.5'
17
+ s.date = '2012-12-11'
18
18
  s.rubyforge_project = 'asciidoctor'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -85,6 +85,7 @@ Gem::Specification.new do |s|
85
85
  test/fixtures/list_elements.asciidoc
86
86
  test/headers_test.rb
87
87
  test/lexer_test.rb
88
+ test/links_test.rb
88
89
  test/list_elements_test.rb
89
90
  test/paragraphs_test.rb
90
91
  test/reader_test.rb
@@ -29,10 +29,23 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'vendor'))
29
29
  #
30
30
  # Examples:
31
31
  #
32
- # lines = File.readlines(filename)
32
+ # Use built-in templates:
33
33
  #
34
- # doc = Asciidoctor::Document.new(lines)
35
- # html = doc.render(template_path)
34
+ # lines = File.readlines("your_file.asc")
35
+ # doc = Asciidoctor::Document.new(lines)
36
+ # html = doc.render
37
+ # File.open("your_file.html", "w+") do |file|
38
+ # file.puts html
39
+ # end
40
+ #
41
+ # Use custom (Tilt-supported) templates:
42
+ #
43
+ # lines = File.readlines("your_file.asc")
44
+ # doc = Asciidoctor::Document.new(lines, :template_dir => 'templates')
45
+ # html = doc.render
46
+ # File.open("your_file.html", "w+") do |file|
47
+ # file.puts html
48
+ # end
36
49
  module Asciidoctor
37
50
  REGEXP = {
38
51
  # [[Foo]] (also allows, say, [[[]] or [[[Foo[f]], but I don't think it is supposed to (TODO))
@@ -57,8 +70,13 @@ module Asciidoctor
57
70
  # <1> Foo
58
71
  :colist => /^(\<\d+\>)\s*(.*)/,
59
72
 
73
+ # ////
74
+ # comment block
75
+ # ////
76
+ :comment_blk => /^\/{4,}\s*$/,
77
+
60
78
  # // (and then whatever)
61
- :comment => /^\/\/\s/,
79
+ :comment => /^\/\/[^\/]/,
62
80
 
63
81
  # foo:: || foo;;
64
82
  # Should be followed by a definition line, e.g.,
@@ -126,7 +144,7 @@ module Asciidoctor
126
144
  # ____
127
145
  :quote => /^_{4,}\s*$/,
128
146
 
129
- # ''''
147
+ # '''
130
148
  :ruler => /^'{3,}\s*$/,
131
149
 
132
150
  # ****
@@ -149,16 +167,38 @@ module Asciidoctor
149
167
  INTRINSICS = Hash.new{|h,k| STDERR.puts "Missing intrinsic: #{k.inspect}"; "{#{k}}"}.merge(
150
168
  'startsb' => '[',
151
169
  'endsb' => ']',
170
+ 'brvbar' => '|',
152
171
  'caret' => '^',
153
172
  'asterisk' => '*',
154
173
  'tilde' => '~',
155
174
  'litdd' => '--',
156
175
  'plus' => '+',
157
- 'apostrophe' => "'",
158
- 'backslash' => "\\",
159
- 'backtick' => '`'
176
+ 'apostrophe' => '\'',
177
+ 'backslash' => '\\',
178
+ 'backtick' => '`',
179
+ 'empty' => '',
180
+ 'sp' => ' ',
181
+ 'two-colons' => '::',
182
+ 'two-semicolons' => ';;',
183
+ 'nbsp' => '&#160;',
184
+ 'deg' => '&#176;',
185
+ 'zwsp' => '&#8203;',
186
+ 'lsquo' => '&#8216;',
187
+ 'rsquo' => '&#8217;',
188
+ 'ldquo' => '&#8220;',
189
+ 'rdquo' => '&#8221;',
190
+ 'wj' => '&#8288;',
191
+ 'amp' => '&',
192
+ 'lt' => '<',
193
+ 'gt' => '>',
160
194
  )
161
195
 
196
+ SPECIAL_CHARS = {
197
+ '<' => '&lt;',
198
+ '>' => '&gt;',
199
+ '&' => '&amp;'
200
+ }
201
+
162
202
  HTML_ELEMENTS = {
163
203
  'br-asciidoctor' => '<br/>'
164
204
  }
@@ -192,8 +192,9 @@ class Asciidoctor::Block
192
192
 
193
193
  result = lines.map do |line|
194
194
  Asciidoctor.debug "#{__method__} -> Processing line: #{line}"
195
+ f = sub_special_chars(line)
195
196
  # gsub! doesn't have lookbehind, so we have to capture and re-insert
196
- f = line.gsub(/ (^|[^\\]) \{ (\w[\w\-_]+\w) \} /x) do
197
+ f = f.gsub(/ (^|[^\\]) \{ (\w([\w\-_]+)?\w) \} /x) do
197
198
  if self.document.defines.has_key?($2)
198
199
  # Substitute from user defines first
199
200
  $1 + self.document.defines[$2]
@@ -273,7 +274,7 @@ class Asciidoctor::Block
273
274
  html.gsub!( /(^|[^<])<<([^<>,]+)(,([^>]*))?>>/ ) { "#{$1}link:##{$2}[" + ($4.nil? ? document.references[$2] : $4).to_s + "]" }
274
275
 
275
276
  # Do the same with URLs
276
- html.gsub!( /(^|[^`])(https?:\/\/[^\[ ]+)(\[+[^\]]*\]+)?/ ) do
277
+ html.gsub!( /(^|[^(`|link:)])(https?:\/\/[^\[ ]+)(\[+[^\]]*\]+)?/ ) do
277
278
  pre = $1
278
279
  url = $2
279
280
  link = ( $3 || $2 ).gsub( /(^\[|\]$)/,'' )
@@ -282,7 +283,6 @@ class Asciidoctor::Block
282
283
  "#{pre}link:#{url}[#{link}]"
283
284
  end
284
285
 
285
- html = CGI.escapeHTML(html)
286
286
  html.gsub!(Asciidoctor::REGEXP[:biblio], '<a name="\1">[\1]</a>')
287
287
  html.gsub!(Asciidoctor::REGEXP[:ruler], '<hr>\n')
288
288
  html.gsub!(/``([^`']*)''/m, '&ldquo;\1&rdquo;')
@@ -307,12 +307,14 @@ class Asciidoctor::Block
307
307
 
308
308
  # "Constrained" quotes, which must be bounded by white space or
309
309
  # common punctuation characters
310
- html.gsub!(/([\s\W])\*([^\*]+)\*([\s\W])/m, '\1<strong>\2</strong>\3')
311
- html.gsub!(/([\s\W])'(.+?)'([\s\W])/m, '\1<em>\2</em>\3')
312
- html.gsub!(/([\s\W])_([^_]+)_([\s\W])/m, '\1<em>\2</em>\3')
313
- html.gsub!(/([\s\W])\+([^\+]+)\+([\s\W])/m, '\1<tt>\2</tt>\3')
314
- html.gsub!(/([\s\W])\^([^\^]+)\^([\s\W])/m, '\1<sup>\2</sup>\3')
315
- html.gsub!(/([\s\W])\~([^\~]+)\~([\s\W])/m, '\1<sub>\2</sub>\3')
310
+ html.gsub!(/(^|\s|\W)\*([^\*]+)\*(\s|\W|$)/m, '\1<strong>\2</strong>\3')
311
+ html.gsub!(/(^|\s|\W)'(.+?)'(\s|\W|$)/m, '\1<em>\2</em>\3')
312
+ # restore escaped single quotes after processing emphasis
313
+ html.gsub!(/(\w)\\'(\w)/, '\1\'\2')
314
+ html.gsub!(/(^|\s|\W)_([^_]+)_(\s|\W|$)/m, '\1<em>\2</em>\3')
315
+ html.gsub!(/(^|\s|\W)\+([^\+]+)\+(\s|\W|$)/m, '\1<tt>\2</tt>\3')
316
+ html.gsub!(/(^|\s|\W)\^([^\^]+)\^(\s|\W|$)/m, '\1<sup>\2</sup>\3')
317
+ html.gsub!(/(^|\s|\W)\~([^\~]+)\~(\s|\W|$)/m, '\1<sub>\2</sub>\3')
316
318
 
317
319
  html.gsub!(/\\([\{\}\-])/, '\1')
318
320
  html.gsub!(/linkgit:([^\]]+)\[(\d+)\]/, '<a href="\1.html">\1(\2)</a>')
@@ -321,5 +323,9 @@ class Asciidoctor::Block
321
323
  html
322
324
  end
323
325
  end
326
+
327
+ def sub_special_chars(str)
328
+ str.gsub(/[#{Asciidoctor::SPECIAL_CHARS.keys.join}]/) {|match| Asciidoctor::SPECIAL_CHARS[match] }
329
+ end
324
330
  # end private
325
331
  end
@@ -3,8 +3,12 @@ module Asciidoctor
3
3
  puts *args if self.show_debug_output?
4
4
  end
5
5
 
6
+ def self.set_debug(value)
7
+ @show_debug = value
8
+ end
9
+
6
10
  def self.show_debug_output?
7
- ENV['DEBUG'] == 'true' && ENV['SUPPRESS_DEBUG'] != 'true'
11
+ @show_debug || (ENV['DEBUG'] == 'true' && ENV['SUPPRESS_DEBUG'] != 'true')
8
12
  end
9
13
 
10
14
  def self.puts_indented(level, *args)
@@ -63,7 +63,11 @@ class Asciidoctor::Lexer
63
63
  this_line = reader.get_line
64
64
  next_line = reader.peek_line || ''
65
65
 
66
- if this_line.match(REGEXP[:comment])
66
+ if this_line.match(REGEXP[:comment_blk])
67
+ Reader.new(reader.grab_lines_until {|line| line.match( REGEXP[:comment_blk] ) })
68
+ next
69
+
70
+ elsif this_line.match(REGEXP[:comment])
67
71
  next
68
72
 
69
73
  elsif match = this_line.match(REGEXP[:title])
@@ -659,8 +663,10 @@ class Asciidoctor::Lexer
659
663
  while section_reader.has_lines?
660
664
  section_reader.skip_blank
661
665
 
662
- new_block = next_block(section_reader, section) if section_reader.has_lines?
663
- section << new_block unless new_block.nil?
666
+ if section_reader.has_lines?
667
+ new_block = next_block(section_reader, section)
668
+ section << new_block unless new_block.nil?
669
+ end
664
670
  end
665
671
 
666
672
  section
@@ -68,7 +68,7 @@ class Asciidoctor::Section
68
68
  # section.section_id
69
69
  # => "_foo"
70
70
  def section_id
71
- "_#{name && name.downcase.gsub(' ','_')}"
71
+ "_#{name && name.downcase.gsub(/\W+/,'_').gsub(/_+$/, '')}".tr_s('_', '_')
72
72
  end
73
73
 
74
74
  # Public: Get the Asciidoctor::Document instance to which this Block belongs
@@ -1,3 +1,3 @@
1
1
  module Asciidoctor
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/noof.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rubygems'
2
2
  require 'ap'
3
- require 'lib/asciidoctor'
3
+ require_relative 'lib/asciidoctor'
4
4
 
5
5
  lines = File.readlines("test/fixtures/asciidoc_index.txt")
6
6
  #lines = File.read("test/fixtures/asciidoc_index.txt")
@@ -77,12 +77,26 @@ context "Attributes" do
77
77
  pending "whut?"
78
78
  end
79
79
 
80
- test "Intrinsics" do
81
- Asciidoctor::INTRINSICS.each_pair do |key, value|
82
- html = render_string("Look, a {#{key}} is here")
83
- result = Nokogiri::HTML(html)
84
- assert_equal("Look, a #{value} is here", result.css("p").first.content.strip)
80
+ context "intrinsics" do
81
+
82
+ test "substitute intrinsics" do
83
+ Asciidoctor::INTRINSICS.each_pair do |key, value|
84
+ html = render_string("Look, a {#{key}} is here")
85
+ # can't use Nokogiri because it interprets the HTML entities and we can't match them
86
+ assert_match /Look, a #{Regexp.escape(value)} is here/, html
87
+ end
88
+ end
89
+
90
+ test "don't escape intrinsic substitutions" do
91
+ html = render_string('happy{nbsp}together')
92
+ assert_match /happy&#160;together/, html
93
+ end
94
+
95
+ test "escape special characters" do
96
+ html = render_string('<node>&</node>')
97
+ assert_match /&lt;node&gt;&amp;&lt;\/node&gt;/, html
85
98
  end
99
+
86
100
  end
87
101
 
88
102
  end
@@ -7,13 +7,21 @@ context "Headers" do
7
7
 
8
8
  context "level 1" do
9
9
  test "with multiline syntax" do
10
- assert_xpath "//h2", render_string("My Section\n-----------")
10
+ assert_xpath "//h2[@id='_my_section']", render_string("My Section\n-----------")
11
11
  end
12
12
 
13
13
  test "with single line syntax" do
14
- assert_xpath "//h2", render_string("== My Title")
14
+ assert_xpath "//h2[@id='_my_title']", render_string("== My Title")
15
15
  end
16
- end
16
+
17
+ test "with non-word character" do
18
+ assert_xpath "//h2[@id='_where_s_the_love']", render_string("== Where's the love?")
19
+ end
20
+
21
+ test "with sequential non-word characters" do
22
+ assert_xpath "//h2[@id='_what_the_is_that']", render_string('== What the #@$ is that')
23
+ end
24
+ end
17
25
 
18
26
  context "level 2" do
19
27
  test "with multiline syntax" do
@@ -44,4 +52,4 @@ context "Headers" do
44
52
  assert_xpath "//h5", render_string("===== My Title")
45
53
  end
46
54
  end
47
- end
55
+ end
@@ -0,0 +1,9 @@
1
+ require 'test_helper'
2
+
3
+ context "Links" do
4
+
5
+ test "absolute url with link prefix" do
6
+ assert_xpath "//a[@href='http://asciidoc.org']", render_string("We're parsing link:http://asciidoc.org[AsciiDoc] markup")
7
+ end
8
+
9
+ end
@@ -12,6 +12,11 @@ context "Paragraphs" do
12
12
  assert_xpath "//p", rendered, 2
13
13
  end
14
14
 
15
+ test "no duplicate block before next section" do
16
+ rendered = render_string("Title\n=====\n\nPreamble.\n\n== First Section\n\nParagraph 1\n\nParagraph 2\n\n\n== Second Section\n\nLast words")
17
+ assert_xpath '//p[text()="Paragraph 2"]', rendered, 1
18
+ end
19
+
15
20
  context "code" do
16
21
  test "literal paragraph" do
17
22
  assert_xpath "//pre/tt", render_string(" LITERALS\n\n ARE LITERALLY\n\n AWESOMMMME.")
@@ -35,4 +40,14 @@ context "Paragraphs" do
35
40
  assert_xpath "//div[@class='admonitionblock']", render_string("NOTE: This is important, fool!")
36
41
  end
37
42
  end
38
- end
43
+
44
+ context "comments" do
45
+ test "line comment" do
46
+ assert_no_match /comment/, render_string("first paragraph\n\n//comment\n\nsecond paragraph")
47
+ end
48
+
49
+ test "comment block" do
50
+ assert_no_match /comment/, render_string("first paragraph\n\n////\ncomment\n////\n\nsecond paragraph")
51
+ end
52
+ end
53
+ end
@@ -3,7 +3,7 @@ require 'test/unit'
3
3
 
4
4
  require "#{File.expand_path(File.dirname(__FILE__))}/../lib/asciidoctor.rb"
5
5
 
6
- require 'mocha'
6
+ require 'mocha/setup'
7
7
  require 'htmlentities'
8
8
  require 'nokogiri'
9
9
  require 'pending'
@@ -145,4 +145,4 @@ end
145
145
 
146
146
  def context(*name, &block)
147
147
  Test::Unit::TestCase.context(name, &block)
148
- end
148
+ end
@@ -16,13 +16,33 @@ context "Text" do
16
16
  end
17
17
 
18
18
  test "separator" do
19
- assert_xpath "//hr", render_string("This is separated.\n\n''''\n\n...from this!"), 1
19
+ assert_xpath "//hr", render_string("This is separated.\n\n'''\n\n...from this!"), 1
20
20
  end
21
21
 
22
22
  test "emphasized text" do
23
23
  assert_xpath "//em", render_string("An 'emphatic' no")
24
24
  end
25
25
 
26
+ test "emphasized text with escaped single quote" do
27
+ assert_xpath "//em[text()=\"Johnny's\"]", render_string("It's 'Johnny\\'s' phone")
28
+ end
29
+
30
+ test "escaped single quote is restore as single quote" do
31
+ assert_xpath "//p[contains(text(), \"Let's do it!\")]", render_string("Let\\'s do it!")
32
+ end
33
+
34
+ test "emphasized text at end of line" do
35
+ assert_xpath "//em", render_string("This library is 'awesome'")
36
+ end
37
+
38
+ test "emphasized text at beginning of line" do
39
+ assert_xpath "//em", render_string("'drop' it")
40
+ end
41
+
42
+ test "emphasized text across line" do
43
+ assert_xpath "//em", render_string("'check it'")
44
+ end
45
+
26
46
  test "unquoted text" do
27
47
  assert_no_match /#/, render_string("An #unquoted# word")
28
48
  end
@@ -74,4 +94,4 @@ context "Text" do
74
94
  assert_xpath "//tt", rendered_chars
75
95
  end
76
96
  end
77
- end
97
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-08-14 00:00:00.000000000 Z
13
+ date: 2012-12-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -144,6 +144,7 @@ files:
144
144
  - test/fixtures/list_elements.asciidoc
145
145
  - test/headers_test.rb
146
146
  - test/lexer_test.rb
147
+ - test/links_test.rb
147
148
  - test/list_elements_test.rb
148
149
  - test/paragraphs_test.rb
149
150
  - test/reader_test.rb
@@ -179,6 +180,7 @@ test_files:
179
180
  - test/document_test.rb
180
181
  - test/headers_test.rb
181
182
  - test/lexer_test.rb
183
+ - test/links_test.rb
182
184
  - test/list_elements_test.rb
183
185
  - test/paragraphs_test.rb
184
186
  - test/reader_test.rb