Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 7, 2025

In v4.2.0, articles with summary_separator lost their HTML document structure when rendered with layout. The buggy implementation from PR #395 applied separator logic to all renders, stripping <!DOCTYPE html>, <html>, <head>, <body> along with summary content.

Changes

lib/middleman-blog/blog_article.rb

  • Conditionally apply separator logic based on opts[:layout]
  • When layout == false: strip to content after separator (for article.body)
  • When rendering with layout: remove separator marker only, preserve all content
if opts[:layout] == false
  content = TruncateHTML.content_after_separator(content, blog_options.summary_separator)
else
  content = content.gsub(blog_options.summary_separator, '')
end

features/summary.feature

  • Update 3 scenarios to verify full pages contain complete HTML structure and both summary + body
  • Add explicit test case for HTML structure preservation

Impact

  • article.body → content after separator (no change)
  • article.summary → content before separator (no change)
  • Full page render → complete HTML structure + both summary and body content (fixed)
Original prompt

This section details on the original issue you should resolve

<issue_title>v4.2.0: Articles with summary_separator lose HTML document structure when rendered with layout</issue_title>
<issue_description>## Problem

In v4.2.0, when an article contains a summary_separator (e.g., READMORE), the rendered page loses its HTML document structure (<!DOCTYPE html>, <html>, <head>, etc.) and starts directly from the content after the separator.

Steps to Reproduce

  1. Configure a blog with summary_separator:
activate :blog do |blog|
  blog.summary_separator = /(READMORE)/
end
  1. Create an article with the separator:
---
title: Test Article
---

This is summary content.

READMORE

### Main Content
This is the main article body.
  1. Build the site and view the generated HTML file

Expected Behavior

The generated HTML should have complete document structure:

<!DOCTYPE html>
<html>
<head>
  <title>Test Article</title>
  ...
</head>
<body>
  ...
  <h3>Main Content</h3>
  <p>This is the main article body.</p>
  ...
</body>
</html>

Actual Behavior

The generated HTML starts directly from the content after separator:

<h3>Main Content</h3>
<p>This is the main article body.</p>
...

All content before READMORE (including the entire HTML document structure from layout) is stripped.

Root Cause

PR #395 (commit a1171c5) modified the BlogArticle#render method to support the intended behavior where article.body should return only content after the separator.

However, the implementation in lib/middleman-blog/blog_article.rb lines 60-67 applies this logic to all render calls, including when rendering the full page with layout:

def render(opts = {}, locs = {}, &block)
  # ... layout handling ...
  
  content = super(opts, locs, &block)
  
  # This runs for BOTH layout: false (article.body) AND layout: 'blog' (full page)
  if blog_options.summary_separator && !opts[:keep_separator]
    if content.match?(blog_options.summary_separator)
      require 'middleman-blog/truncate_html'
      content = TruncateHTML.content_after_separator(content, blog_options.summary_separator)
    end
  end
  
  content
end

The problem is:

  • article.body calls render(layout: false) → Works correctly, returns content after separator
  • ❌ Full page rendering calls render(layout: 'blog')Incorrectly strips everything before separator, including HTML structure from layout

Suggested Fix

The separator processing should only apply when rendering without layout:

def render(opts = {}, locs = {}, &block)
  unless opts.key?(:layout)
    opts[:layout] = metadata[:options][:layout]
    opts[:layout] = blog_options.layout if opts[:layout].nil? || opts[:layout] == :_auto_layout
    opts[:layout] = opts[:layout].to_s if opts[:layout].is_a? Symbol
  end

  content = super(opts, locs, &block)

  # Only apply separator logic when rendering without layout
  if opts[:layout] == false && blog_options.summary_separator && !opts[:keep_separator]
    if content.match?(blog_options.summary_separator)
      require 'middleman-blog/truncate_html'
      content = TruncateHTML.content_after_separator(content, blog_options.summary_separator)
    end
  end

  content
end

Environment

  • middleman-blog: 4.2.0
  • middleman-core: 4.6.1

Workaround

Until fixed, users can:

  1. Downgrade to v4.1.0
  2. Comment out blog.summary_separator in config.rb
  3. Remove READMORE from all articles</issue_description>

Comments on the Issue (you are @copilot in this section)

@markets Hello @unhappychoice and thanks for such detailed report. Could you please send a patch with tests? I'd be very happy to review it.

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@markets markets marked this pull request as ready for review November 7, 2025 10:10
Copilot AI and others added 4 commits November 7, 2025 10:19
- Only apply "content after separator" logic when rendering without layout (article.body)
- When rendering with layout (full page), remove separator marker but keep all content
- Update tests to expect full pages to have complete HTML structure and both summary + body content

Co-authored-by: markets <576701+markets@users.noreply.github.com>
Co-authored-by: markets <576701+markets@users.noreply.github.com>
This ensures we only match exactly false, not other falsy values like nil

Co-authored-by: markets <576701+markets@users.noreply.github.com>
Co-authored-by: markets <576701+markets@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix HTML document structure loss with summary_separator Fix summary_separator stripping HTML document structure from full page renders Nov 7, 2025
Copilot AI requested a review from markets November 7, 2025 10:27
@markets
Copy link
Member

markets commented Nov 7, 2025

@unhappychoice Could you please try this branch?

@unhappychoice
Copy link

I tested this PR with my blog project that uses summary_separator = /(READMORE)/ and can confirm it works perfectly!

Verification Results

✅ HTML document structure (<!DOCTYPE html>, <html>, <head>, <body>) is fully preserved
✅ Both summary content (before READMORE) and main content (after READMORE) are included in the rendered page
✅ READMORE marker is properly removed from the output

The fix correctly addresses the issue reported in #400. Thank you for the quick fix!

@markets markets merged commit e3c48f7 into master Nov 7, 2025
12 checks passed
@markets markets deleted the copilot/fix-html-structure-issue branch November 7, 2025 17:09
@markets
Copy link
Member

markets commented Nov 7, 2025

Thanks @unhappychoice! 🙌🏼 I'll release a new patch version asap.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v4.2.0: Articles with summary_separator lose HTML document structure when rendered with layout

3 participants