diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ef7f0ce --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bin +.bundle diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..fc0c90e --- /dev/null +++ b/.rspec @@ -0,0 +1,4 @@ +--tty +--color +--format documentation +--require spec_helper diff --git a/Gemfile b/Gemfile index 298ba7d..594c90b 100644 --- a/Gemfile +++ b/Gemfile @@ -5,3 +5,4 @@ gem "thin" gem "slim" gem "bb-ruby" gem "ruby-bbcode" +gem "rspec", "~> 3.0" diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..9244ec2 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,63 @@ +GEM + remote: http://rubygems.org/ + specs: + activesupport (4.2.4) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + bb-ruby (1.1.0) + daemons (1.2.3) + diff-lcs (1.2.5) + eventmachine (1.0.8) + i18n (0.7.0) + json (1.8.3) + minitest (5.8.2) + rack (1.6.4) + rack-protection (1.5.3) + rack + rspec (3.1.0) + rspec-core (~> 3.1.0) + rspec-expectations (~> 3.1.0) + rspec-mocks (~> 3.1.0) + rspec-core (3.1.2) + rspec-support (~> 3.1.0) + rspec-expectations (3.1.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.1.0) + rspec-mocks (3.1.0) + rspec-support (~> 3.1.0) + rspec-support (3.1.0) + ruby-bbcode (2.0.0) + activesupport (>= 3.2.3) + sinatra (1.4.6) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (>= 1.3, < 3) + slim (3.0.6) + temple (~> 0.7.3) + tilt (>= 1.3.3, < 2.1) + temple (0.7.6) + thin (1.6.4) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0, >= 1.0.4) + rack (~> 1.0) + thread_safe (0.3.5) + tilt (2.0.1) + tzinfo (1.2.2) + thread_safe (~> 0.1) + +PLATFORMS + ruby + +DEPENDENCIES + bb-ruby + rspec (~> 3.0) + ruby-bbcode + sinatra + slim + thin + +BUNDLED WITH + 1.10.6 diff --git a/bristlecode.rb b/bristlecode.rb index 4dc540f..3491b57 100644 --- a/bristlecode.rb +++ b/bristlecode.rb @@ -14,11 +14,11 @@ module Bristlecode rule(:space?) { space.maybe } rule(:bold_open) { str('[b]') | str('[B]') } - rule(:bold_close) { str('[/b]') | str('[/B]') } + rule(:bold_close) { str('[/b]') | str('[/B]') | eof } rule(:bold) { bold_open >> children.as(:bold) >> bold_close } rule(:italic_open) { str('[i]') | str('[I]') } - rule(:italic_close) { str('[/i]') | str('[/I]') } + rule(:italic_close) { str('[/i]') | str('[/I]') | eof } rule(:italic) { italic_open >> children.as(:italic) >> italic_close } rule(:eof) { any.absent? } @@ -30,7 +30,7 @@ module Bristlecode rule(:text) { (tag_delim.absent? >> any).repeat(1).as(:text) } rule(:children) { space? >> elem.repeat(1) } - rule(:doc) { space? >> elem.repeat(1).as(:doc) } + rule(:doc) { space? >> elem.repeat.as(:doc) } root(:doc) end diff --git a/spec/bristlecode/parser_spec.rb b/spec/bristlecode/parser_spec.rb new file mode 100644 index 0000000..997f5b4 --- /dev/null +++ b/spec/bristlecode/parser_spec.rb @@ -0,0 +1,70 @@ +require 'parslet/rig/rspec' +require_relative '../../bristlecode.rb' + +module Bristlecode + describe Parser do + let(:parser) { Parser.new } + + describe '#parse' do + it 'can parse an empty string' do + expect(parser).to parse('') + end + + it 'can parse plain text' do + expect(parser).to parse('this is some plain text') + end + end + + describe '#bold' do + it 'can parse correct bold text syntax' do + expect(parser.bold).to parse('[b]bolded contents here[/b]') + expect(parser.bold).to parse('[b]bolded contents here[/B]') + expect(parser.bold).to parse('[B]bolded contents here[/b]') + expect(parser.bold).to parse('[B]bolded contents here[/B]') + end + + it 'can parse an unclosed tag' do + expect(parser.bold).to parse('[b]bolded contents here') + expect(parser.bold).to parse('[B]bolded contents here') + end + + it 'fails non-bold text' do + expect(parser.bold).not_to parse('this is not bold') + end + + it 'fails dangling close tags' do + expect(parser.bold).not_to parse('before [/b] after') + end + + it 'fails nonsense tag' do + expect(parser.bold).not_to parse('[bold]fake content[/bold]') + end + end + + describe '#italic' do + it 'can parse correct italic text syntax' do + expect(parser.italic).to parse('[i]italiced contents here[/i]') + expect(parser.italic).to parse('[i]italiced contents here[/I]') + expect(parser.italic).to parse('[I]italiced contents here[/i]') + expect(parser.italic).to parse('[I]italiced contents here[/I]') + end + + it 'can parse an unclosed tag' do + expect(parser.italic).to parse('[i]italiced contents here') + expect(parser.italic).to parse('[I]italiced contents here') + end + + it 'fails non-italic text' do + expect(parser.italic).not_to parse('this is not italic') + end + + it 'fails dangling close tags' do + expect(parser.italic).not_to parse('before [/i] after') + end + + it 'fails nonsense tag' do + expect(parser.italic).not_to parse('[italic]fake content[/italic]') + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..b054591 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,9 @@ +RSpec.configure do |config| + config.expect_with :rspec do |expect| + expect.include_chain_clauses_in_custom_matcher_descriptions = true + end + + config.mock_with :rspec do |mocks| + mocks.verify_partial_doubles = true + end +end