Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Pluggable parsers #354

Closed
wants to merge 5 commits into from

4 participants

@cs
Collaborator
cs commented

As discussed in pull request #353, I tried to add support for pluggable parsers to prawn.

The critical question is, where to put the new parser management code. I decided to use the existing module Prawn::Text::Formatted, because parser management really belongs to the other code related to formatting. All in all, I tried to make as few changed to prawn as possible.

Also, you might want to take a look at: prawn-html5 - I created a new Gem called prawn-html5 which depends on the changes of this pull request and supplies the modified parser I suggested before (in pull request #353).

Finally, I've created a small small Rails application to demonstrate the use of prawn-html5 with HTML5 compatible WYSIWYG editing. See prawn-html5-example.

This isn't finished yet. There are still a things left to do. Please tell me what you think so far!

Christoph Sc... added some commits
Christoph Schiessl add #pt2pt to Prawn::Measurements 4e10098
Christoph Schiessl initial support for pluggable parsers
parser management is done in `Prawn::Text::Formatted`.
i tried to keep everything as simple as possible!
fed495d
@cs
Collaborator
cs commented

One more thing...

For now, all parsers are required to respond to only one method (that's the interface parsers have to implement):

def to_array(string, *args)
   # parse string and produce a prawn compatible array...
   return [] # stub
end

The other methods in Prawn::Text::Formatted::Parser still have to be dealt with accordingly.

Christoph Sc... added some commits
Christoph Schiessl correct interface of to_array method in prawn default parser e1b5125
Christoph Schiessl different approach: choose the parser when the document is created.
=> new option called `:parser` in `Prawn::Document`
   defaults to the parser shipping with Prawn (`Prawn::Text::Formatted::Parser`).
0a56506
@cs
Collaborator
cs commented

Hi! I realize that you won't merge this pull request in its present form (mainly for the lack of documentation). However, some kind of feedback would be nice nonetheless?

Am I on the right track? Would you prefer some kind of different approach? I would really appreciate getting answers to those questions before investing more work.

@yob
Collaborator
yob commented

Hi,

Sorry we never provided feedback on this, our time for prawn has been slim recently. I can't speak for the other prawn maintainers, but my feeling is adding this to the official gem in the near future will slow us down in releasing 1.0. un that's released, our focus is on stablising the API and fixing bugs.

I suggest we leave this issue open as a wishlist though. thanks!

@cs cs Merge branch 'master' into pluggable-parsers
Conflicts:
	lib/prawn/table/cell/text.rb
	lib/prawn/text/formatted/parser.rb
f6e1a91
@cs
Collaborator
cs commented

@yob, thank you for your feedback...

I just wanted to let you know, that I'm still interested in this. Actually, I'm using my pluggable parsers implementation in production at the moment.

There's an example application available here, illustrating the possibility of using WYSIWYG editing for prawn PDF documents (enabled by the pluggable parsers extension).

@practicingruby

@cs: Sorry again that we didn't get to this sooner. The team didn't even have time to address all the pull requests we got for bugs, so features were very much de-prioritized.

I will take a closer look at this as I work through the pull request backlog. Thanks for your patience.

@practicingruby

@cs: Just a heads up, I've done some light review of this patch and I'm definitely sold on the idea. I want to think more about the interface before merging though, and so this may sit around for a little while until I get a chance to merge some of the other patches that have been piling up in the queue.

But I'll be sure to get in touch once I have time to take a closer look at this one!

@packetmonkey

I merged master into this branch and pushed a copy of it up to the pluggable-parsers feature branch on the prawn repo. I'll open a PR for that branch so we can work on finishing bringing this in.

@practicingruby

@cs: We're going to work on this over at #586. Please do share your thoughts over there as @packetmonkey attempts a slightly revised approach to this problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 30, 2012
  1. add #pt2pt to Prawn::Measurements

    Christoph Schiessl authored
Commits on Jun 2, 2012
  1. initial support for pluggable parsers

    Christoph Schiessl authored
    parser management is done in `Prawn::Text::Formatted`.
    i tried to keep everything as simple as possible!
  2. correct interface of to_array method in prawn default parser

    Christoph Schiessl authored
Commits on Jun 16, 2012
  1. different approach: choose the parser when the document is created.

    Christoph Schiessl authored
    => new option called `:parser` in `Prawn::Document`
       defaults to the parser shipping with Prawn (`Prawn::Text::Formatted::Parser`).
Commits on May 1, 2013
  1. @cs

    Merge branch 'master' into pluggable-parsers

    cs authored
    Conflicts:
    	lib/prawn/table/cell/text.rb
    	lib/prawn/text/formatted/parser.rb
This page is out of date. Refresh to see the latest.
View
6 lib/prawn/document.rb
@@ -140,6 +140,7 @@ def self.generate(filename,options={},&block)
# <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
# <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
# <tt>:template</tt>:: The path to an existing PDF file to use as a template [nil]
+ # <tt>:parser</tt>: The parser to use for <tt>:inline_format</tt>ted text [Prawn::Text::Formatted::Parser]
#
# Setting e.g. the :margin to 100 points and the :left_margin to 50 will result in margins
# of 100 points on every side except for the left, where it will be 50.
@@ -176,7 +177,7 @@ def initialize(options={},&block)
Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
:right_margin, :top_margin, :bottom_margin, :skip_page_creation,
:compress, :skip_encoding, :background, :info,
- :optimize_objects, :template], options
+ :optimize_objects, :template, :parser], options
# need to fix, as the refactoring breaks this
# raise NotImplementedError if options[:skip_page_creation]
@@ -195,6 +196,8 @@ def initialize(options={},&block)
@page_number = 0
+ @parser = options.delete(:parser) || Text::Formatted::Parser
+
options[:size] = options.delete(:page_size)
options[:layout] = options.delete(:page_layout)
@@ -220,6 +223,7 @@ def initialize(options={},&block)
attr_reader :margins, :y
attr_writer :font_size
attr_accessor :page_number
+ attr_accessor :parser
def state
@internal_state
View
6 lib/prawn/font.rb
@@ -217,11 +217,13 @@ def font_families
# it and redefine the width calculation behavior.
#++
def width_of(string, options={})
- if options[:inline_format]
+ if p = options[:inline_format]
+ p = [] unless p.is_a?(Array)
+
# Build up an Arranger with the entire string on one line, finalize it,
# and find its width.
arranger = Core::Text::Formatted::Arranger.new(self, options)
- arranger.consumed = Text::Formatted::Parser.to_array(string)
+ arranger.consumed = self.parser.to_array(string, *p)
arranger.finalize_line
arranger.line_width
View
2  lib/prawn/measurement_extensions.rb
@@ -41,6 +41,6 @@ def ft
end
def pt
- return self
+ return pt2pt(self)
end
end
View
4 lib/prawn/measurements.rb
@@ -36,6 +36,10 @@ def yd2in(yd)
# ============================================================================
# PostscriptPoint-converisons
+ def pt2pt(pt)
+ return pt
+ end
+
def in2pt(inch)
return inch * 72
end
View
8 lib/prawn/table/cell/text.rb
@@ -113,14 +113,16 @@ def with_text_color
end
def text_box(extra_options={})
- if @text_options[:inline_format]
+ if p = @text_options[:inline_format]
+ p = [] unless p.is_a?(Array)
options = @text_options.dup
options.delete(:inline_format)
options.merge!(extra_options)
options[:document] = @pdf
- array = ::Prawn::Text::Formatted::Parser.to_array(@content)
- ::Prawn::Text::Formatted::Box.new(array, options)
+ array = @pdf.parser.to_array(@content, *p)
+ ::Prawn::Text::Formatted::Box.new(array,
+ options.merge(extra_options).merge(:document => @pdf))
else
::Prawn::Text::Box.new(@content, @text_options.merge(extra_options).
merge(:document => @pdf))
View
10 lib/prawn/text.rb
@@ -70,7 +70,8 @@ module Text
#
# <tt>:inline_format</tt>::
# <tt>boolean</tt>. If true, then the string parameter is interpreted
- # as a HTML-esque string that recognizes the following tags:
+ # as a HTML-esque string that recognizes the following tags
+ # (assuming the default parser is used):
# <tt>\<b></b></tt>:: bold
# <tt>\<i></i></tt>:: italic
# <tt>\<u></u></tt>:: underline
@@ -156,9 +157,10 @@ def text(string, options={})
# we modify the options. don't change the user's hash
options = options.dup
- if options[:inline_format]
+ if p = options[:inline_format]
+ p = [] unless p.is_a?(Array)
options.delete(:inline_format)
- array = Text::Formatted::Parser.to_array(string)
+ array = self.parser.to_array(string, *p)
else
array = [{ :text => string }]
end
@@ -197,7 +199,7 @@ def formatted_text(array, options={})
end
if @indent_paragraphs
- Text::Formatted::Parser.array_paragraphs(array).each do |paragraph|
+ self.parser.array_paragraphs(array).each do |paragraph|
options[:skip_encoding] = false
remaining_text = draw_indented_formatted_line(paragraph, options)
options[:skip_encoding] = true
View
5 lib/prawn/text/box.rb
@@ -108,8 +108,9 @@ def text_box(string, options={})
options = options.dup
options[:document] = self
- box = if options.delete(:inline_format)
- array = Text::Formatted::Parser.to_array(string)
+ box = if p = options.delete(:inline_format)
+ p = [] unless p.is_a?(Array)
+ array = self.parser.to_array(string, *p)
Text::Formatted::Box.new(array, options)
else
Text::Box.new(string, options)
View
3  lib/prawn/text/formatted/parser.rb
@@ -13,7 +13,6 @@ module Text
module Formatted
class Parser
-
PARSER_REGEX = begin
regex_string = "\n|" +
"<b>|</b>|" +
@@ -32,7 +31,7 @@ class Parser
regex = Regexp.new(regex_string, Regexp::MULTILINE)
end
- def self.to_array(string)
+ def self.to_array(string, *args)
tokens = string.gsub(/<br\s*\/?>/, "\n").scan(PARSER_REGEX)
self.array_from_tokens(tokens)
end
Something went wrong with that request. Please try again.