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 Jun 14, 2023
1 parent 9fdad16 commit 393a390
Show file tree
Hide file tree
Showing 5 changed files with 160 additions and 2 deletions.
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ gem "wdm", "~> 0.1.0" if Gem.win_platform?


gem "webrick", "~> 1.7"

# Used in _plugins/social_images.rb
gem "chunky_png"
gem "cairo"
gem "rsvg2"
32 changes: 31 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,33 @@ GEM
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
asciidoctor (2.0.15)
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)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
eventmachine (1.2.7)
ffi (1.15.0)
fiddle (1.1.1)
forwardable-extended (2.6.0)
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.6.0)
i18n (1.8.10)
concurrent-ruby (~> 1.0)
Expand Down Expand Up @@ -53,19 +72,27 @@ GEM
listen (3.5.1)
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)
pkg-config (1.5.1)
public_suffix (4.0.6)
rb-fsevent (0.11.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
red-colors (0.3.0)
matrix
rexml (3.2.5)
rouge (3.26.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)
Expand All @@ -78,14 +105,17 @@ PLATFORMS
ruby

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

BUNDLED WITH
2.2.16
2.3.7
2 changes: 1 addition & 1 deletion _layouts/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,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.dest, 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.dest, 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 393a390

Please sign in to comment.