Class: Seo::FaInlineSvgRestorer

Inherits:
BaseService show all
Defined in:
app/services/seo/fa_inline_svg_restorer.rb

Overview

Restores Font Awesome web-font <i> tags in HTML content that has been
rewritten by FA's SVG+JS engine, and patches missing icons in
callout-facts headings.

Why this exists

The CRM editor (Redactor) uses FA's SVG+JS engine, which transforms
<i class="fa-sharp fa-solid fa-icon"> into
<svg class="svg-inline--fa fa-icon" data-prefix="fas" data-icon="icon">.
The public www frontend uses CSS Web Fonts, which expect <i> tags. This
service runs on stored content before it leaves CRM authoring and restores
the natural <i> form so icons render on both sides.

Also patches section.callout-facts > h4|h5 headings whose icon <i> was
accidentally stripped, re-inserting the canonical fa-list-check glyph.

All emitted classes consolidate onto the project's sharp-only family per
.font-awesome.md — see PREFIX_MAP.

Examples:

result = Seo::FaInlineSvgRestorer.new.process(html_string)
result.html_out    # => cleaned HTML (html_safe) or nil if untouched
result.changed?    # => Boolean — any replacements made?
result.svg_count   # => Integer — SVGs replaced
result.icon_count  # => Integer — missing callout icons restored

See Also:

Defined Under Namespace

Classes: Result

Constant Summary collapse

PREFIX_MAP =

Mapping of FA prefix → emitted CSS classes. Consolidates onto the
project's sharp-only family per .font-awesome.md: light/thin collapse
to regular, duotone collapses to solid. Brands has no sharp variant.

{
  "fas" => "fa-sharp fa-solid",
  "far" => "fa-sharp fa-regular",
  "fal" => "fa-sharp fa-regular",
  "fat" => "fa-sharp fa-regular",
  "fad" => "fa-sharp fa-solid",
  "fab" => "fa-brands",
  "fass" => "fa-sharp fa-solid",
  "fasr" => "fa-sharp fa-regular",
  "fasl" => "fa-sharp fa-regular",
  # Sharp Duotone (FA ≥6.6.0). Listed explicitly so the duotone-collapse
  # policy is self-documenting; otherwise these would hit the
  # `|| "fa-sharp fa-solid"` fallback below.
  "fasds" => "fa-sharp fa-solid",
  "fasdr" => "fa-sharp fa-regular",
  "fasdl" => "fa-sharp fa-regular",
  "fasdt" => "fa-sharp fa-regular"
}.freeze
CALLOUT_FACTS_ICON =

Canonical icon name for section.callout-facts headings.

"fa-list-check"

Instance Attribute Summary

Attributes inherited from BaseService

#options

Instance Method Summary collapse

Methods inherited from BaseService

#initialize, #log_debug, #log_error, #log_info, #log_warning, #logger, #tagged_logger

Constructor Details

This class inherits a constructor from BaseService

Instance Method Details

#process(html_fragment) ⇒ Seo::FaInlineSvgRestorer::Result

Restores inline-SVG icons and missing callout-facts heading icons.

Returns a no-op Result (with the original input echoed back) when the
fragment is blank or contains neither an FA SVG marker nor a callout-facts
section — this keeps the parser cost off the happy path.

Parameters:

  • html_fragment (String, nil)

    HTML fragment to normalize

Returns:



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'app/services/seo/fa_inline_svg_restorer.rb', line 80

def process(html_fragment)
  return Result.new(html_out: html_fragment) if html_fragment.blank?
  return Result.new(html_out: html_fragment) unless html_fragment.include?("svg-inline--fa") || html_fragment.include?("callout-facts")

  doc = Nokogiri::HTML(html_fragment)
  svg_count = replace_inline_svgs(doc)
  icon_count = restore_callout_facts_icons(doc)

  if svg_count > 0 || icon_count > 0
    html_out = doc.at("body")&.inner_html.presence&.html_safe
    Result.new(html_out: html_out, changed: true, svg_count: svg_count, icon_count: icon_count)
  else
    Result.new(html_out: html_fragment)
  end
end