diff --git a/Gemfile b/Gemfile
index af8e1eeab01..1cd59d50896 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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"
diff --git a/Gemfile.lock b/Gemfile.lock
index 20443298663..c5fceee0c73 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,6 +4,14 @@ 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)
@@ -11,7 +19,18 @@ GEM
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)
@@ -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)
@@ -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
diff --git a/_layouts/base.html b/_layouts/base.html
index 62d83ff8d99..409be9f8183 100755
--- a/_layouts/base.html
+++ b/_layouts/base.html
@@ -34,7 +34,7 @@
-
+
{% if page.layout == 'guides' or page.layout == 'guides-index' %}
{%assign canonical_url = page.url | replace_regex: '^/version/[^/]+', '' %}
{% else %}
diff --git a/_plugins/assets/quarkus_card_blank.png b/_plugins/assets/quarkus_card_blank.png
new file mode 100644
index 00000000000..4b74b1102e0
Binary files /dev/null and b/_plugins/assets/quarkus_card_blank.png differ
diff --git a/_plugins/social_images.rb b/_plugins/social_images.rb
new file mode 100644
index 00000000000..4aef5dbf5ae
--- /dev/null
+++ b/_plugins/social_images.rb
@@ -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 += "#{line}"
+ idx += font_size + 10
+ end
+ "
+
+ "
+ 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)