Automatic read more-link for truncated blog summaries

In a list of blog posts that has been truncated, I prefer if the the ”Read more”-link only appears when there actually is more to read.

Also, after clicking a read more-link, I prefer if the page scrolls up, making it easy to continue reading.

I’ve added some code to config.rb to do this. It’s a workaround, not very elegant. But I suspect that this kind of functionality will be added to the blog extension in the future, so this will do for the time being.


Workaround to automaticly add ‘Read more’-links

The blog extension has functions for extracting a summary from an article, either by looking for a manually added separator, or after a certain number of characters.

It will however not automatically generate a read more-link. For this some working around is required.

Do do this, we will utilize that the summary function will accept a custom summary generator. Unfortunally, it is only applied when generating a summary of a certain size. If the separator is manually added, it will be taken care of before reaching the generator.

But by adding a dummy separator, that never exist in any text, to the blog preferences we can make all articles go to the generator.

As a first step, we define the separator pattern in config.rb

@readmore_separator = /(<p>)?\(Read more\)(<\/p>)?/i

This will look for a ”(Read more)” separator (it will be used both in the blog options and further down in config in the helper section, by the cleanup_readmore function.)

Then we define the generator. (separator is the separator pattern, readmore_text is the text of the link to the full article, and if link_to_separator_position is true, the page will scroll up, making it easy to find where to continue reading)

def setup_summary_generator(
    separator = /(READMORE)/i,
    readmore_text = 'Read more',
    link_to_separator_position = true)

  return Proc.new  do |resource, rendered, length, ellipsis|
    require 'middleman-blog/truncate_html'
    if link_to_separator_position
      readmore_link = "\n<p class = 'readmore'>#{link_to(readmore_text, resource, :fragment => 'readmore')}</p>"
    else
      readmore_link = "\n<p class = 'readmore'>#{link_to(readmore_text, resource)}</p>"
    end

    if rendered =~ separator
      # The separator is found in the text
      summary = rendered.split(separator).first
      summary + readmore_link   # return
    elsif length
      summary = TruncateHTML.truncate_html(rendered, length, ellipsis)
      unless summary.strip == rendered.strip  # If the
            # original text was longer then the summary...
        summary = summary + readmore_link     # ...add
            # a read more-link.
      end
      summary    # return
    else
      rendered   # return
    end
  end
end

Now we add some blog options

activate :blog do |blog|
    ...
    blog.summary_separator = /DUMMY SEPARATOR/
    blog.summary_length = 250
    blog.summary_generator = setup_summary_generator(@readmore_separator)
    ...
end

Normally, the blog extension would remove the separator from the text. But this workaround unfortunately has worked itself around that. So in the helper section of config.rb we need to add a function

def cleanup_readmore(html)
    html.sub(@readmore_separator, "<span id='readmore'></span>")
end

and use it in the layout. Replace

yield

with

cleanup_readmore(yield)

Great write-up, super informative. As this is the only example of a custom article summary generator I’ve found in the forums, I was wondering if you could help me (a Ruby noob) with a summary generation problem.

How could I go about ensuring that all parts of footnotes (link and content) are brought into the summary? Say, for example, that a footnote link is in the summary portion of an article (whether defined by length or separator), but, of course, the footnote content is at the bottom of the HTML and thus not within the bounds of the summary. The default summary generator will simply bring the footnote link and not the footnote content. I want both, so I will need to go and get the footnote content and add it to the bottom of the article summary.

Is this possible? If so, any guidance on how to achieve it?


edit

I have a working solution which I posted on my original question post. It uses a RegEx to grab the footnotes div and appends it to the summary. Couldn’t have figured it out without this post, so thank you kindly.

Thanks for that. This definitely gives me some ideas. As a Ruby and Middleman noob, I found it really helpful.