Permalink
Browse files

Merge pull request #4 from gjp/master

mendicant-s9: Integrate Redcarpet parser
  • Loading branch information...
2 parents ab54f35 + 9233dff commit 45e0c4d0a575026deff79732b3c4c737f1c6f15c @practicingruby committed Sep 28, 2011
Showing with 76 additions and 77 deletions.
  1. +3 −2 bookie.gemspec
  2. +2 −0 lib/bookie.rb
  3. +2 −3 lib/bookie/book.rb
  4. +45 −66 lib/bookie/parser.rb
  5. +24 −6 test/units/parser_test.rb
View
5 bookie.gemspec
@@ -12,8 +12,9 @@ Gem::Specification.new do |s|
"processor. For now it's just something I'm playing "+
"around with, so use at your own risk"
- s.add_dependency('prawn', '~> 0.11.0')
- s.add_dependency('eeepub', '~> 0.6.0')
+ s.add_dependency('prawn', '~> 0.12.0')
+ s.add_dependency('eeepub', '~> 0.7.1')
+ s.add_dependency('redcarpet', '~> 2.0.0b5')
s.files = Dir.glob("{lib,test,examples,doc,data}/**/*") + %w(GPLv3 README.md CHANGELOG.md)
s.require_path = 'lib'
View
2 lib/bookie.rb
@@ -7,6 +7,8 @@
require "prawn"
require "eeepub"
+require "redcarpet"
+
require_relative "bookie/version"
require_relative "bookie/parser"
require_relative "bookie/emitters"
View
5 lib/bookie/book.rb
@@ -11,14 +11,13 @@ def chapter(name, file)
chapters << [name, file]
end
- # FIXME: This is inefficient, it should be possible to fire up the parser
- # just once with many emitters.
def render(basename, emitters)
emitters.each do |emitter|
+ markdown = Redcarpet::Markdown.new(Bookie::Parser.new(emitter))
chapters.each_with_index do |(name, file), i|
emitter.start_new_chapter(header: "Chapter #{i+1}",
title: name)
- Bookie::Parser.parse(File.read(file), emitter)
+ markdown.render(File.read(file))
end
output_file = "#{basename}#{emitter.class.extension}"
View
111 lib/bookie/parser.rb
@@ -6,19 +6,55 @@ module Bookie
NormalText = Struct.new(:contents)
CodeText = Struct.new(:contents)
- class Parser
- def self.parse(raw_data, emitter=Bookie::Emitters::Null.new)
- parser = new(raw_data, emitter)
- parser.parsed_content
- end
+ class Parser < Redcarpet::Render::Base
attr_reader :parsed_content
- def initialize(raw_data, emitter)
+ def initialize(emitter=Bookie::Emitters::Null.new)
@emitter = emitter
@parsed_content = []
- parse_contents(raw_data)
+ super()
+ end
+
+ def header(text, header_level)
+ flush_paragraph
+ extract_section_heading(text)
+ text
+ end
+
+ def paragraph(text)
+ flush_paragraph
+ @paragraph = text
+ end
+
+ def block_code(code, language)
+ flush_paragraph
+ extract_raw_text(code)
+ code
+ end
+
+ def list(contents, list_type)
+ flush_paragraph
+ extract_list(contents.split("\n"))
+ contents
+ end
+
+ def list_item(text, list_type)
+ @paragraph = nil
+ text + "\n"
+ end
+
+ def doc_footer
+ flush_paragraph
+ end
+
+ private
+ def flush_paragraph
+ if @paragraph
+ extract_paragraph(@paragraph)
+ @paragraph = nil
+ end
end
def extract_inlines(paragraph_text)
@@ -47,7 +83,7 @@ def extract_paragraph(paragraph_text)
def extract_raw_text(contents)
raw_text = RawText.new(contents)
@emitter.build_raw_text(raw_text)
- parsed_content << raw_text
+ parsed_content << raw_text
end
def extract_section_heading(contents)
@@ -57,66 +93,9 @@ def extract_section_heading(contents)
end
def extract_list(contents)
- list = List.new(contents.map { |e| e.chomp })
+ list = List.new(contents)
@emitter.build_list(list)
parsed_content << list
end
-
- private
-
- def parse_contents(raw_data)
- lines = raw_data.lines.to_a
- mode = nil
-
- until lines.empty?
- line = lines.shift
- case
- when mode == nil
- case line
- when /^## /
- extract_section_heading(line[3..-1])
- when /^ {4,}/
- mode = :raw
- chunk = line[4..-1]
- when /^\* /
- mode = :list
- chunk = [line[2..-1]]
- else
- mode = :paragraph
- chunk = line
- end
- when mode == :raw
- chunk << (line.strip.empty? ? "\n" : line[4..-1].to_s)
-
- if lines.first =~ /^ {0,3}\S/
- mode = nil
- extract_raw_text(chunk)
- end
- when mode == :list
- chunk << line[2..-1].to_s unless line.strip.empty?
-
- if lines.first.to_s.strip.length > 0 && lines.first !~ /^\*/
- mode = nil
- extract_list(chunk)
- end
- when mode == :paragraph
- if line.chomp.empty?
- mode = nil
- extract_paragraph(chunk)
- else
- chunk << line
- end
- end
- end
-
- case mode
- when :paragraph
- extract_paragraph(chunk)
- when :raw
- extract_raw_text(chunk)
- when :list
- extract_list(chunk)
- end
- end
end
end
View
30 test/units/parser_test.rb
@@ -1,14 +1,26 @@
require_relative "../test_helper"
+require 'redcarpet'
context "A Parser" do
+
+ def setup
+ @parser = Bookie::Parser.new
+ @markdown = Redcarpet::Markdown.new(@parser)
+ end
+
test "should know about paragraphs" do
+
+
sample_text = File.read(fixture("multi_paragraph_document.md"))
# NOTE: Is this the behavior we'd expect?
+ # NOTE: gjp added strip - paragraph should not include trailing space
sample_paragraph_text = File.read(fixture("single_paragraph.md"))
- .gsub(/\s+/," ")
- parsed_content = Bookie::Parser.parse(sample_text)
-
+ .gsub(/\s+/," ").strip
+
+ @markdown.render(sample_text)
+ parsed_content = @parser.parsed_content
+
assert_equal 8, parsed_content.length
actual_paragraph = parsed_content[4]
@@ -19,14 +31,18 @@
test "should know about preformatted text" do
sample_text = File.read(fixture("preformatted_blocks.md"))
- parsed_content = Bookie::Parser.parse(sample_text)
+
+ @markdown.render(sample_text)
+ parsed_content = @parser.parsed_content
assert_equal 6, parsed_content.length
end
test "should know about section headers" do
sample_text = File.read(fixture("document_with_headings.md"))
- parsed_content = Bookie::Parser.parse(sample_text)
+
+ @markdown.render(sample_text)
+ parsed_content = @parser.parsed_content
assert_equal 17, parsed_content.length
@@ -38,7 +54,9 @@
test "should know about list elements" do
sample_text = File.read(fixture("lists.md"))
- parsed_content = Bookie::Parser.parse(sample_text)
+
+ @markdown.render(sample_text)
+ parsed_content = @parser.parsed_content
assert_equal 3, parsed_content.length

0 comments on commit 45e0c4d

Please sign in to comment.