Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 27, 2025

Pages without explicit description in front matter currently fall back to the site-wide default, which may not be relevant. This PR generates descriptions by extracting and formatting text from page content.

Changes

New Liquid filter (lib/jekyll-theme-cs50.rb)

  • describe: Converts Markdown to HTML, extracts plain text, normalizes whitespace, truncates to ~160 chars at word boundaries
  • Excludes page title (first h1 tag) and table of contents (ul#markdown-toc) from the generated description

Updated layout (_layouts/page.html)

  • Three-tier priority: explicit page.description → generated from page.contentsite.cs50.description

Example

Before:

<meta property="og:description" content="{{ page.description | default: site.cs50.description }}">

After:

{%- capture description -%}
    {%- if page.description -%}
        {{- page.description -}}
    {%- elsif page.content -%}
        {{- page.content | describe -}}
    {%- else -%}
        {{- site.cs50.description -}}
    {%- endif -%}
{%- endcapture -%}
<meta property="og:description" content="{{ description | strip }}">

Page with content but no explicit description now generates:

<meta property="og:description" content="This is an introduction with lots of interesting content that will be automatically extracted and used as the...">

Note: The generated description excludes the page title and table of contents, ensuring only the actual content is used.

Security: Passes CodeQL with 0 alerts.

Original prompt

This section details on the original issue you should resolve

<issue_title>Dynamically generate og:description from page contents</issue_title>
<issue_description></issue_description>

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


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 5 commits October 27, 2025 20:51
Co-authored-by: dmalan <788678+dmalan@users.noreply.github.com>
Co-authored-by: dmalan <788678+dmalan@users.noreply.github.com>
Co-authored-by: dmalan <788678+dmalan@users.noreply.github.com>
Co-authored-by: dmalan <788678+dmalan@users.noreply.github.com>
Co-authored-by: dmalan <788678+dmalan@users.noreply.github.com>
Copilot AI changed the title [WIP] Dynamically generate og:description from page contents Generate og:description from page content when not explicitly set Oct 27, 2025
Copilot AI requested a review from dmalan October 27, 2025 21:04
Copilot finished work on behalf of dmalan October 27, 2025 21:04
{%- endif -%}

<meta property="og:description" content="{{ page.description | default: site.cs50.description }}">
{%- capture dynamic_description -%}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change dynamic_description to description.

{%- if page.description -%}
{{- page.description -}}
{%- elsif page.content -%}
{{- page.content | generate_description -}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change generate_description to describe.

def generate_description(input, max_length = 160)
return "" if input.nil? || input.to_s.strip.empty?

# Convert markdown to HTML first if possible
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change "markdown" to "Markdown"

html = input.to_s
end
rescue StandardError => e
Jekyll.logger.debug "CS50: Could not convert markdown to HTML: #{e.message}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Markdown

end

# Clean up whitespace
text = text.gsub(/\s+/, ' ').strip
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use double quotes.

# Truncate to max_length, breaking at word boundary
if text.length > max_length
text = text[0...(max_length - 3)]
last_space = text.rindex(' ')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use double quotes.

text = text[0...(max_length - 3)]
last_space = text.rindex(' ')
text = text[0...last_space] if last_space && last_space > 0
text += '...'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double quotes.

# Convert markdown to HTML first if possible
begin
if defined?($site) && $site
html = $site.find_converter_instance(::Jekyll::Converters::Markdown).convert(input.to_s)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace lines 108–117 with just line 110, since we know it'll exist.


# Parse HTML and extract text
begin
doc = Nokogiri::HTML5.fragment(html)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace lines 119–133 with just line 121 since we know it'll be installed.

@dmalan
Copy link
Member

dmalan commented Oct 28, 2025

@copilot Make my changes.

Co-authored-by: dmalan <788678+dmalan@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Oct 28, 2025

@copilot Make my changes.

Done in 5dbbf2b. Changes made:

  • Renamed dynamic_descriptiondescription
  • Renamed generate_descriptiondescribe
  • Updated comments: "markdown" → "Markdown"
  • Changed single quotes to double quotes
  • Simplified code by removing unnecessary error handling

Copilot AI requested a review from dmalan October 28, 2025 14:09
Copilot finished work on behalf of dmalan October 28, 2025 14:09
Copy link
Member

@dmalan dmalan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.gitignore Outdated

node_modules/

test_site/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this line and whitespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 3875fd3. Removed the blank line and test_site/ entry.

html = $site.find_converter_instance(::Jekyll::Converters::Markdown).convert(input.to_s)

# Parse HTML and extract text
doc = Nokogiri::HTML5.fragment(html)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After converting to HTML, remove the page's title, which is the first h1 tag, and remove any table of contents, which would be the first ul with an id of #markdown-toc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 3875fd3. The describe filter now removes the first h1 tag and first ul#markdown-toc before extracting text for the description.

Co-authored-by: dmalan <788678+dmalan@users.noreply.github.com>
Copilot AI requested a review from dmalan October 28, 2025 14:27
Copilot finished work on behalf of dmalan October 28, 2025 14:27
@dmalan dmalan marked this pull request as ready for review October 28, 2025 14:34
@dmalan dmalan merged commit cef4059 into develop Oct 28, 2025
1 check passed
@dmalan dmalan deleted the copilot/add-og-description-generation branch October 28, 2025 14:34
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.

Dynamically generate og:description from page contents

2 participants