diff --git a/bristlecode.rb b/bristlecode.rb
index 9536c54..48ab082 100644
--- a/bristlecode.rb
+++ b/bristlecode.rb
@@ -18,14 +18,18 @@ module Bristlecode
)
def Bristlecode.to_html(text)
- parser = Bristlecode::Parser.new
- parse_tree = parser.parse(text)
- tree = Bristlecode::Transform.new.apply(parse_tree)
- html = tree.to_html
+ begin
+ parser = Bristlecode::Parser.new
+ parse_tree = parser.parse(text)
+ tree = Bristlecode::Transform.new.apply(parse_tree)
+ html = tree.to_html
+ rescue Parslet::ParseFailed => parse_error
+ html = text
+ end
Sanitize.fragment(html, Bristlecode::Config)
end
- def Bristlecode.clean(text)
+ def Bristlecode.clean!(text)
text.gsub!('&', '&')
text.gsub!('<', '<')
text.gsub!('>', '>')
@@ -50,7 +54,7 @@ module Bristlecode
rule(:simple_href) { (url_close.absent? >> any).repeat }
rule(:simple_url) { url_open >> simple_href.as(:href) >> url_close }
rule(:url_title_open) { str('[url=') }
- rule(:url_title_href) { (match(']').absent? >> any).repeat }
+ rule(:url_title_href) { (match(']').absent? >> any).repeat(1) }
rule(:url_with_title) {
url_title_open >>
url_title_href.as(:href) >>
@@ -100,6 +104,12 @@ module Bristlecode
children.each{|child| s << child.to_html }
s.string
end
+
+ def to_text
+ s = StringIO.new
+ children.each{|child| s << child.to_text }
+ s.string
+ end
end
class Text
@@ -107,12 +117,16 @@ module Bristlecode
def initialize(text)
self.text = text.to_str
- Bristlecode.clean(self.text)
+ Bristlecode.clean!(self.text)
end
def to_html
text
end
+
+ def to_text
+ text
+ end
end
class Bold
@@ -125,6 +139,10 @@ module Bristlecode
def to_html
"#{children.to_html}"
end
+
+ def to_text
+ "[b]#{children.to_text}[/b]"
+ end
end
class Italic
@@ -137,6 +155,10 @@ module Bristlecode
def to_html
"#{children.to_html}"
end
+
+ def to_text
+ "[i]#{children.to_text}[/i]"
+ end
end
class Url
@@ -149,27 +171,29 @@ module Bristlecode
self.title = Doc.new(args[:title])
else
self.title_supplied = false
- self.title = Text.new(self.href)
+ self.title = Text.new(args[:href].to_str.strip)
end
end
def href_ok?
- href =~ /^https?:/
+ href =~ /^(\/|https?:\/\/)/
end
def to_html
if href_ok?
"#{title.to_html}"
else
- reject
+ to_text
end
end
- def reject
+ def to_text
if title_supplied
- "[url=#{href}]#{title.to_html}[/url]"
+ "[url=#{href}]#{title.to_text}[/url]"
else
- Text.new("[url]#{href}[/url]").to_html
+ text = "[url]#{href}[/url]"
+ Bristlecode.clean!(text)
+ text
end
end
end
@@ -178,6 +202,10 @@ module Bristlecode
def to_html
"
"
end
+
+ def to_text
+ "[br]"
+ end
end
class Img
@@ -188,15 +216,21 @@ module Bristlecode
end
def src_ok?
- src =~ /^(\/[^\/]|https?:\/\/)/
+ src =~ /^(\/|https?:\/\/)/
end
def to_html
if src_ok?
""
else
- Text.new("[img]#{src}[/img]").to_html
+ to_text
end
end
+
+ def to_text
+ text = "[img]#{src}[/img]"
+ Bristlecode.clean!(text)
+ text
+ end
end
end
diff --git a/spec/bristlecode/parser_spec.rb b/spec/bristlecode/parser_spec.rb
index 6233490..17c7aa6 100644
--- a/spec/bristlecode/parser_spec.rb
+++ b/spec/bristlecode/parser_spec.rb
@@ -57,7 +57,9 @@ module Bristlecode
input = '[url]http://example.com[/url]'
output = 'http://example.com'
expect(to_html(input)).to eq(output)
+ end
+ it 'trims whitespace around urls' do
input = '[url] http://example.com [/url]'
output = 'http://example.com'
expect(to_html(input)).to eq(output)
@@ -113,6 +115,14 @@ module Bristlecode
input = '[img]ftp://example.com/cat.gif[/img]'
expect(to_html(input)).to eq(input)
end
+
+ it 'returns the original text on parse failure' do
+ input = '[img]http://example.com/dog.gif[img]http://example.com/cat.gif[/img][/img]'
+ expect(to_html(input)).to eq(input)
+
+ input = '[url][url]x[/url][/url]'
+ expect(to_html(input)).to eq(input)
+ end
end
describe Parser do