Class: JekyllGFMAdmonitions::GFMAdmonitionConverter

Inherits:
Jekyll::Generator
  • Object
show all
Defined in:
lib/jekyll-gfm-admonitions.rb

Overview

GFMAdmonitionConverter is a Jekyll generator that converts custom admonition blocks in markdown (e.g., ‘> [!IMPORTANT]`) into styled HTML alert boxes with icons.

This generator processes both posts and pages, replacing admonition syntax with HTML markup that includes appropriate iconography and CSS styling.

Class Attribute Summary collapse

Instance Method Summary collapse

Class Attribute Details

.admonition_pagesObject (readonly)

Returns the value of attribute admonition_pages.



30
31
32
# File 'lib/jekyll-gfm-admonitions.rb', line 30

def admonition_pages
  @admonition_pages
end

Instance Method Details

#admonition_html(type, title, text, icon) ⇒ Object



104
105
106
107
108
109
# File 'lib/jekyll-gfm-admonitions.rb', line 104

def admonition_html(type, title, text, icon)
  "<div class='markdown-alert markdown-alert-#{type}'>
      <p class='markdown-alert-title'>#{icon} #{title}</p>
      <p>#{@markdown.convert(text)}</p>
    </div>\n\n"
end

#convert_admonitions(doc) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/jekyll-gfm-admonitions.rb', line 92

def convert_admonitions(doc)
  doc.content.gsub!(/>\s*\[!(IMPORTANT|NOTE|WARNING|TIP|CAUTION)\]\s*\n((?:>.*\n?)*)/) do
    type = ::Regexp.last_match(1).downcase
    title = type.capitalize
    text = ::Regexp.last_match(2).gsub(/^>\s*/, '').strip
    icon = Octicons::Octicon.new(ADMONITION_ICONS[type]).to_svg
    Jekyll.logger.debug 'GFMA:', "Converting #{type} admonition."

    admonition_html(type, title, text, icon)
  end
end

#generate(site) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/jekyll-gfm-admonitions.rb', line 34

def generate(site)
  init_converter(site)
  process_posts(site)
  process_pages(site)
  Jekyll.logger.info 'GFMA:', 'Converted adminitions in' \
    " #{self.class.admonition_pages.length} file(s)."
end

#init_converter(site) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/jekyll-gfm-admonitions.rb', line 42

def init_converter(site)
  @markdown = site.converters.find { |c| c.is_a?(Jekyll::Converters::Markdown) }
  return if @markdown

  raise 'Markdown converter not found. Please ensure that you have a markdown' \
          ' converter configured in your Jekyll site.'
end

#process_doc(doc) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/jekyll-gfm-admonitions.rb', line 75

def process_doc(doc)
  code_blocks = []
  # Temporarily replace code blocks by a tag, so that we don't process any admonitions
  # inside of code blocks.
  doc.content.gsub!(/(?:^|\n)(?<!>)\s*```.*?```/m) do |match|
    code_blocks << match
    "```{{CODE_BLOCK_#{code_blocks.length - 1}}}```"
  end

  convert_admonitions(doc)

  # Put the code blocks back in place
  doc.content.gsub!(/```\{\{CODE_BLOCK_(\d+)}}```/) do
    code_blocks[::Regexp.last_match(1).to_i]
  end
end

#process_doc_content(doc) ⇒ Object



64
65
66
67
68
69
70
71
72
73
# File 'lib/jekyll-gfm-admonitions.rb', line 64

def process_doc_content(doc)
  original_content = doc.content.dup
  process_doc(doc)

  return unless doc.content != original_content

  # Store a reference to all the pages we modified, to inject the CSS post render
  # (otherwise GitHub Pages sanitizes the CSS into plaintext)
  self.class.admonition_pages << doc
end

#process_pages(site) ⇒ Object



57
58
59
60
61
62
# File 'lib/jekyll-gfm-admonitions.rb', line 57

def process_pages(site)
  site.pages.each do |page|
    Jekyll.logger.debug 'GFMA:', "Processing page '#{page.path}' (#{page.content.length} characters)."
    process_doc_content(page)
  end
end

#process_posts(site) ⇒ Object



50
51
52
53
54
55
# File 'lib/jekyll-gfm-admonitions.rb', line 50

def process_posts(site)
  site.posts.docs.each do |doc|
    Jekyll.logger.debug 'GFMA:', "Processing post '#{doc.path}' (#{doc.content.length} characters)."
    process_doc(doc)
  end
end