11# frozen_string_literal: true
22
33require "jekyll"
4- require "grover"
54require "fileutils"
65require "uri"
76
7+ # Conditionally require grover - only needed when PDF generation is enabled
8+ begin
9+ require "grover"
10+ GROVER_AVAILABLE = true
11+ rescue LoadError
12+ GROVER_AVAILABLE = false
13+ # Don't log here as Jekyll logger may not be available yet
14+ end
15+
816##
917# Jekyll Generator Plugin for PDF Generation
1018# Generates PDF versions of documentation collections during Jekyll build
@@ -18,6 +26,7 @@ class PdfGenerator < Generator
1826
1927 def generate ( site )
2028 return unless site . config [ "pdf_generator" ] && site . config [ "pdf_generator" ] [ "enabled" ]
29+ return unless GROVER_AVAILABLE
2130
2231 @site = site
2332 @pdf_config = site . config [ "pdf_generator" ]
@@ -226,8 +235,8 @@ def build_document_section(doc, section_number, total_sections)
226235 end
227236
228237 # Clean up content - remove script tags and interactive elements
229- content = content . gsub ( /<script\b [^<]*(?:(?!<\/ script>)<[^<]*)*<\/ script>/mi , "" )
230- content = content . gsub ( /<style\b [^<]*(?:(?!<\/ style>)<[^<]*)*<\/ style>/mi , "" )
238+ content = content . gsub ( /<script\b [^<]*(?:(?!<\/ script>)<[^<]*)*<\/ script>/mis , "" )
239+ content = content . gsub ( /<style\b [^<]*(?:(?!<\/ style>)<[^<]*)*<\/ style>/mis , "" )
231240
232241 # Extract main content from HTML - try to find the main content area
233242 # Remove common HTML structure elements
@@ -253,42 +262,42 @@ def extract_main_content(html)
253262 return "" if html . nil? || html . empty?
254263
255264 # Remove entire head section
256- html = html . gsub ( /<head[^>]*>.*?<\/ head>/mi , "" )
265+ html = html . gsub ( /<head[^>]*>.*?<\/ head>/mis , "" )
257266
258267 # Remove header/nav elements (entire elements)
259- html = html . gsub ( /<header[^>]*>.*?<\/ header>/mi , "" )
260- html = html . gsub ( /<nav[^>]*>.*?<\/ nav>/mi , "" )
261- html = html . gsub ( /<aside[^>]*>.*?<\/ aside>/mi , "" )
262- html = html . gsub ( /<footer[^>]*>.*?<\/ footer>/mi , "" )
268+ html = html . gsub ( /<header[^>]*>.*?<\/ header>/mis , "" )
269+ html = html . gsub ( /<nav[^>]*>.*?<\/ nav>/mis , "" )
270+ html = html . gsub ( /<aside[^>]*>.*?<\/ aside>/mis , "" )
271+ html = html . gsub ( /<footer[^>]*>.*?<\/ footer>/mis , "" )
263272
264273 # Remove side-bar and navigation divs (multiline match)
265- html = html . gsub ( /<div[^>]*class=["'][^"']*side-bar[^"']*["'][^>]*>.*?<\/ div>/mi , "" )
266- html = html . gsub ( /<div[^>]*class=["'][^"']*site-nav[^"']*["'][^>]*>.*?<\/ div>/mi , "" )
267- html = html . gsub ( /<div[^>]*class=["'][^"']*site-header[^"']*["'][^>]*>.*?<\/ div>/mi , "" )
268- html = html . gsub ( /<div[^>]*class=["'][^"']*toc-wrap[^"']*["'][^>]*>.*?<\/ div>/mi , "" )
274+ html = html . gsub ( /<div[^>]*class=["'][^"']*side-bar[^"']*["'][^>]*>.*?<\/ div>/mis , "" )
275+ html = html . gsub ( /<div[^>]*class=["'][^"']*site-nav[^"']*["'][^>]*>.*?<\/ div>/mis , "" )
276+ html = html . gsub ( /<div[^>]*class=["'][^"']*site-header[^"']*["'][^>]*>.*?<\/ div>/mis , "" )
277+ html = html . gsub ( /<div[^>]*class=["'][^"']*toc-wrap[^"']*["'][^>]*>.*?<\/ div>/mis , "" )
269278
270279 # Try to extract main content area - look for main-content or main-content-wrap
271280 # Using multiline and dotall matching
272- if html =~ /<div[^>]*class=["'][^"']*main-content[^"']*["'][^>]*>(.*?)<\/ div>/mi
281+ if html =~ /<div[^>]*class=["'][^"']*main-content[^"']*["'][^>]*>(.*?)<\/ div>/mis
273282 html = $1
274- elsif html =~ /<div[^>]*id=["'][^"']*main-content[^"']*["'][^>]*>(.*?)<\/ div>/mi
283+ elsif html =~ /<div[^>]*id=["'][^"']*main-content[^"']*["'][^>]*>(.*?)<\/ div>/mis
275284 html = $1
276- elsif html =~ /<main[^>]*>(.*?)<\/ main>/mi
285+ elsif html =~ /<main[^>]*>(.*?)<\/ main>/mis
277286 html = $1
278- elsif html =~ /<div[^>]*id=["'][^"']*main[^"']*["'][^>]*>(.*?)<\/ div>/mi
287+ elsif html =~ /<div[^>]*id=["'][^"']*main[^"']*["'][^>]*>(.*?)<\/ div>/mis
279288 html = $1
280289 end
281290
282291 # Remove breadcrumb navigation
283- html = html . gsub ( /<nav[^>]*aria-label=["']Breadcrumb["'][^>]*>.*?<\/ nav>/mi , "" )
284- html = html . gsub ( /<div[^>]*class=["'][^"']*breadcrumb[^"']*["'][^>]*>.*?<\/ div>/mi , "" )
292+ html = html . gsub ( /<nav[^>]*aria-label=["']Breadcrumb["'][^>]*>.*?<\/ nav>/mis , "" )
293+ html = html . gsub ( /<div[^>]*class=["'][^"']*breadcrumb[^"']*["'][^>]*>.*?<\/ div>/mis , "" )
285294
286295 # Remove any remaining script/style tags
287- html = html . gsub ( /<script[^>]*>.*?<\/ script>/mi , "" )
288- html = html . gsub ( /<style[^>]*>.*?<\/ style>/mi , "" )
296+ html = html . gsub ( /<script[^>]*>.*?<\/ script>/mis , "" )
297+ html = html . gsub ( /<style[^>]*>.*?<\/ style>/mis , "" )
289298
290299 # Remove SVG elements (icons, etc.)
291- html = html . gsub ( /<svg[^>]*>.*?<\/ svg>/mi , "" )
300+ html = html . gsub ( /<svg[^>]*>.*?<\/ svg>/mis , "" )
292301
293302 # Clean up extra whitespace
294303 html = html . gsub ( /\s +/ , " " )
@@ -560,6 +569,7 @@ def escape_html(text)
560569# Hook to generate PDFs after all files are written
561570Jekyll ::Hooks . register :site , :post_write do |site |
562571 next unless site . config [ "pdf_generator" ] && site . config [ "pdf_generator" ] [ "enabled" ]
572+ next unless GROVER_AVAILABLE
563573
564574 # Process all queued PDF generations
565575 Jekyll ::PdfGenerator . pdf_jobs . each do |pdf_job |
0 commit comments