Skip to content

Commit

Permalink
Generate social images
Browse files Browse the repository at this point in the history
- Fixes #1723
  • Loading branch information
gastaldi committed Oct 10, 2023
1 parent 4c4aeb6 commit e213e26
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 21 deletions.
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ gem "wdm", "~> 0.1.0" if Gem.win_platform?


gem "webrick", "~> 1.7"

# Used in _plugins/social_images.rb
gem "chunky_png", "~> 1.4.0"
gem 'rsvg2', '~> 4.1.7'
gem "cairo", "~> 1.17.9"
gem "rake", "~> 13.0.1"
72 changes: 52 additions & 20 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,19 +1,38 @@
GEM
remote: https://rubygems.org/
specs:
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
asciidoctor (2.0.15)
addressable (2.8.4)
public_suffix (>= 2.0.2, < 6.0)
asciidoctor (2.0.20)
cairo (1.17.9)
native-package-installer (>= 1.0.3)
pkg-config (>= 1.2.2)
red-colors
cairo-gobject (4.1.7)
cairo (>= 1.16.2)
glib2 (= 4.1.7)
chunky_png (1.4.0)
colorator (1.1.0)
concurrent-ruby (1.1.8)
em-websocket (0.5.2)
concurrent-ruby (1.2.2)
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
http_parser.rb (~> 0)
eventmachine (1.2.7)
ffi (1.15.0)
ffi (1.15.5)
fiddle (1.1.1)
forwardable-extended (2.6.0)
http_parser.rb (0.6.0)
i18n (1.8.10)
gdk_pixbuf2 (4.1.7)
gio2 (= 4.1.7)
gio2 (4.1.7)
fiddle
gobject-introspection (= 4.1.7)
glib2 (4.1.7)
native-package-installer (>= 1.0.3)
pkg-config (>= 1.3.5)
gobject-introspection (4.1.7)
glib2 (= 4.1.7)
http_parser.rb (0.8.0)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jekyll (4.1.1)
addressable (~> 2.4)
Expand All @@ -35,57 +54,70 @@ GEM
jekyll-asciidoc (3.0.0)
asciidoctor (>= 1.5.0)
jekyll (>= 3.0.0)
jekyll-feed (0.15.1)
jekyll-feed (0.17.0)
jekyll (>= 3.7, < 5.0)
jekyll-paginate-v2 (3.0.0)
jekyll (>= 3.0, < 5.0)
jekyll-sass-converter (2.1.0)
jekyll-sass-converter (2.2.0)
sassc (> 2.0.1, < 3.0)
jekyll-seo-tag (2.7.1)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
kramdown (2.3.1)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.5.1)
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
matrix (0.4.2)
mercenary (0.4.0)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
native-package-installer (1.1.5)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (4.0.6)
rb-fsevent (0.11.0)
pkg-config (1.5.1)
public_suffix (5.0.1)
rake (13.0.6)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
red-colors (0.3.0)
matrix
rexml (3.2.5)
rouge (3.26.0)
rouge (3.30.0)
rsvg2 (4.1.7)
cairo-gobject (= 4.1.7)
gdk_pixbuf2 (= 4.1.7)
safe_yaml (1.0.5)
sassc (2.4.0)
ffi (~> 1.9)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
unicode-display_width (1.7.0)
webrick (1.7.0)
unicode-display_width (1.8.0)
webrick (1.8.1)

PLATFORMS
ruby

DEPENDENCIES
cairo (~> 1.17.9)
chunky_png (~> 1.4.0)
jekyll (~> 4.1.1)
jekyll-archives
jekyll-asciidoc
jekyll-feed (~> 0.6)
jekyll-paginate-v2
minima (~> 2.0)
rake (~> 13.0.1)
rsvg2 (~> 4.1.7)
tzinfo-data
webrick (~> 1.7)

BUNDLED WITH
2.2.16
2.4.10
2 changes: 1 addition & 1 deletion _layouts/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
<meta property="og:url" content="{{ page.url | prepend: site.url }}" />
<meta property="og:title" content="{{ page.title }}{{ page_title_version_suffix }}" />
<meta property="og:description" content="{% if page.description %}{{ page.description }}{% else %}{{ site.description }}{% endif %}" />
<meta property="og:image" content="{{ '/assets/images/quarkus_card.png' | prepend: site.url }}" />
<meta property="og:image" content="{{ page.social_image | social_image: page.path | prepend: site.url }}" />
{% if page.layout == 'guides' or page.layout == 'guides-index' %}
{%assign canonical_url = page.url | replace_regex: '^/version/[^/]+', '' %}
{% else %}
Expand Down
Binary file added _plugins/assets/quarkus_card_blank.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
123 changes: 123 additions & 0 deletions _plugins/social_images.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
require 'chunky_png'
require 'cairo'
require 'rsvg2'

module Jekyll
# Generates social images for blog posts and guides
module SocialImages
def social_image(text, page_path)
# If text is not empty, return it
if text.nil? || text.empty?
# If page_path contains "guides/", return the social image path
if page_path.include?('guides/')
return "/assets/images/social/#{File.basename(page_path, '.adoc')}.png"
else
return "/assets/images/quarkus_card.png"
end
else
text
end
end
end

class GenerateSocialImagesGenerator < Generator
def generate(site)
guides = Dir.glob(File.join(site.source, '_guides', '*.adoc'))
output_dir = 'assets/images/social'
FileUtils.mkdir_p(File.join(site.source, output_dir))

guides.each do |guide_file|
basename = File.basename(guide_file, '.adoc')
if basename.start_with?('_')
next
end
title = extract_title(guide_file)
output_file = File.join(site.source, output_dir, "#{basename}.png")
# Skip if the file already exists
if File.exist?(output_file)
next
end

# Generate the SVG image
svg_image_str = generate_svg_string(title)

# Create a Cairo surface and context for the PNG image (must be smaller than 600x330)
surface = Cairo::ImageSurface.new(Cairo::FORMAT_ARGB32, 600, 250)
context = Cairo::Context.new(surface)

# Load and render the SVG onto the Cairo context
svg = RSVG::Handle.new_from_data(svg_image_str)
context.render_rsvg_handle(svg)

# Save the Cairo surface to a PNG file
b = StringIO.new
surface.write_to_png(b)

# Compose the generated image with the template image
png_image = ChunkyPNG::Image.from_file('_plugins/assets/quarkus_card_blank.png')
# Change the last parameters to change the position of the generated image
png_image.compose!(ChunkyPNG::Image.from_blob(b.string), 0, 80)

Jekyll.logger.info("Generating social image to #{output_file}")
# Save the composed image to the output file
png_image.save(output_file)
end
end

def split_text_into_lines(text)
lines = []
words = text.split(' ')
current_line = ''

words.each do |word|
if current_line.length + word.length <= 32
current_line += (current_line == '' ? '' : ' ') + word
else
lines.push(current_line)
current_line = word
end
end

lines.push(current_line) unless current_line.empty?

lines
end

private

def generate_svg_string(title)
idx = 90
font_size = 30
tspan_elements = ''
split_text_into_lines(title).each_with_index do |line, index|
tspan_elements += "<tspan x='50%' y='#{idx}'>#{line}</tspan>"
idx += font_size + 10
end
"
<svg width=\"600\" height=\"330\">
<style>
.title { fill: white; font-size: #{font_size}px; font-weight: bold; font-family:'Open Sans'}
</style>
<text x=\"50%\" y=\"50%\" text-anchor=\"middle\" class=\"title\" >
#{tspan_elements}
</text>
</svg>
"
end

def extract_title(adoc_file)
title = ''
File.open(adoc_file, 'r') do |file|
file.each_line do |line|
if line.start_with? '='
title = line[2..].strip
break
end
end
end
title
end
end
end

Liquid::Template.register_filter(Jekyll::SocialImages)

0 comments on commit e213e26

Please sign in to comment.