prawn icon indicating copy to clipboard operation
prawn copied to clipboard

:overflow => :ellipses not working

Open jcarlos opened this issue 4 years ago • 9 comments

Hi,

Creating a PDF doc and passing the overflow option as ellipses is not adding ... at the end of text, it is just truncating the text.

I've tried to quickly debugging prawn to find the issue and search on the source code for ellilpses and couldn't find anything

Example of code not working:

Prawn::Document.generate("prawn.pdf") do
    string = "This is the beginning of the text. It will be cut somewhere and " +
    "the rest of the text will procede to be rendered this time by " +
    "calling another method." 
    y_position = cursor - 20
    
    excess_text = text_box string,
                           :width => 300,
                           :height => 50,
                           :overflow => :ellipses,
                           :at => [100, y_position],
                           :size => 18,
end

Thank you

jcarlos avatar Mar 18 '20 22:03 jcarlos

Hi,

I don't think Prawn supports :ellipses overflow mode.

Did you see it in the documentation or code somewhere?

pointlessone avatar Mar 19 '20 08:03 pointlessone

@pointlessone yes, I saw it here https://www.rubydoc.info/gems/prawn-core/0.7.2/Prawn%2FText:text_box

Perhaps documentation is wrong or it was supported in an older version and it isn't anymore?

Thanks

jcarlos avatar Mar 20 '20 06:03 jcarlos

Also came here to report the same issue

sherisoli avatar May 22 '20 20:05 sherisoli

@sherisoli as a workaround I ended up doing something like this:

def truncate string, coord_x, coord_y
      params = { size: 12, leading: 10, width: 500, height: 90, at: [coord_x, coord_y - 30] }
      excess_text = pdf.text_box(string, params.merge(dry_run: true, mode: :invisible))
      if excess_text.empty?
        pdf.text_box(string, params.merge(dry_run: false))
      else
        # omission set to "" so spaces can be removed from the end
        # before adding ...more
        new_text = string.truncate(string.length - excess_text.length - ELLIPSIS_LENGTH, omission: "")
        other_content = "http://somelink"
        pdf.formatted_text_box([
                                 { text: new_text.strip.chomp + "..." },
                                 { text: "more", color: "006FFF", link: other_content }
                               ], params.merge(dry_run: false))
      end
    end

You may need to adapt according to your use case, the key is to use dry_run and invisible to get the excess_text and use it to truncate the original string with the ellipsis length then call the method again without dry_run and invisible using the truncated string.

jcarlos avatar May 25 '20 00:05 jcarlos

@jcarlos There is no Ruby String#truncate method... See https://ruby-doc.org/core-2.7.1/String.html

gettalong avatar May 25 '20 11:05 gettalong

@gettalong sorry, I’m using that code as part of a Rails application: https://apidock.com/rails/ActionView/Helpers/TextHelper/truncate

You may want to use that ActionView helper as a gem, or check its source code to see how it does it. Alternatively replace truncate with slice https://ruby-doc.org/core-2.5.1/String.html#method-i-slice

jcarlos avatar May 25 '20 13:05 jcarlos

Looks like it was intentionally removed in 526cbfcc back in 2011. Here's the google groups conversation about the removal (also linked in the commit).

I'm DRYing up text per my previous post and have come up against the ellipses overflow option again in Text::Box. I had made it unsupported in formatted text because it is more complicated there than for regular text, and it wasn't clear to me how it should be handled. Now that I'm making all text resolve to formatted text, I'm facing failing specs. I don't particularly like the way I implemented the ellipses overflow option last time (and I'm not sure how related that was to the original implementation I was replacing). It also added extra complexity. But beyond that, is adding ellipses really a necessary low-level feature of Prawn? I'd say not.

What would you think about removing the :ellipses overflow option from Text::Box?

Thank You, Daniel


I'm all for it. If there ends up being a nice way to expose an API so that end-user code can reimplement this, all the better. But I don't think we need this in core.

-be [Brad Ediger]

chrismo avatar Jul 14 '21 01:07 chrismo

I ended up with this for myself:

    def truncate(string, max_width)
      # if you're worried about performance here, prawn basically does the same
      # thing with font sizes when you use shrink_to_fit with text_box.
      if width_of(string) > max_width
        string.size.downto(1) do |length|
          if width_of(truncated = string.truncate(length)) < max_width
            return truncated
          end
        end
      end
      string
    end

chrismo avatar Jul 14 '21 03:07 chrismo

This version doesn't iterate, but yields more ragged results:

    def truncate(string, max_width)
      if width_of(string) > max_width
        rendered_width = width_of("#{string}...")
        rendered_pct = max_width / (rendered_width * 1.0)
        pct_margin = 0.02
        characters = (string.size * (rendered_pct - pct_margin)).to_i
        string.truncate(characters)
      else
        string
      end
    end

chrismo avatar Jul 14 '21 03:07 chrismo

I don't know what that gem is. This repo never had this options. I'm glad you guys are having fun implementing the feature though.

I don't even know what resolution to assign to this issue. Is it "out of scope"? Is it "has workaround"? Anyway, I don't have anything to here so I'm closing it.

pointlessone avatar Jan 16 '24 14:01 pointlessone