Class: DocsKit::OgGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/docs_kit/og_generator.rb

Overview

Screenshots a URL into the site's OG/Twitter images. Loaded ONLY by the host-installed docs_kit:og rake task (via an explicit require) — never at gem runtime — so the headless-browser tooling it drives is never a docs-kit dependency. zeitwerk ignores this file (see lib/docs_kit.rb) for the same reason: it must not be eager-loaded into a host that never runs the task.

Usage (from the rake task):

DocsKit::OgGenerator.new(url:, out_dir:, sizes:, shooter:).call

When #url is nil the generator boots the Rails app on an ephemeral port and shoots "/"; when set it shoots that URL directly (e.g. a deployed site). The shooter is a headless-browser CLI resolved at runtime: an explicit override, else the first of shot-scraper / chromium / chrome found on PATH.

Defined Under Namespace

Classes: NoShooterError

Constant Summary collapse

SHOOTERS =

The shooters we know how to drive, in preference order. shot-scraper first (purpose-built, handles sizing cleanly); then a raw chromium/chrome.

%w[shot-scraper chromium chromium-browser google-chrome chrome].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url:, out_dir:, sizes:, shooter: nil) ⇒ OgGenerator

Returns a new instance of OgGenerator.



31
32
33
34
35
36
# File 'lib/docs_kit/og_generator.rb', line 31

def initialize(url:, out_dir:, sizes:, shooter: nil)
  @url = url
  @out_dir = out_dir.to_s
  @sizes = sizes
  @shooter = shooter
end

Instance Attribute Details

#out_dirObject (readonly)

Returns the value of attribute out_dir.



29
30
31
# File 'lib/docs_kit/og_generator.rb', line 29

def out_dir
  @out_dir
end

#sizesObject (readonly)

Returns the value of attribute sizes.



29
30
31
# File 'lib/docs_kit/og_generator.rb', line 29

def sizes
  @sizes
end

#urlObject (readonly)

Returns the value of attribute url.



29
30
31
# File 'lib/docs_kit/og_generator.rb', line 29

def url
  @url
end

Instance Method Details

#callObject

The full run: resolve a shooter, ensure the output dir, boot a local server if needed, and shoot every size. Returns the list of written paths.



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/docs_kit/og_generator.rb', line 43

def call
  tool = resolve_shooter!
  require "fileutils"
  FileUtils.mkdir_p(out_dir)

  with_target_url do |target|
    sizes.map do |filename, dimensions|
      path = File.join(out_dir, filename)
      run(command_for(tool, target, dimensions, path))
      path
    end
  end
end

#command_for(tool, target, dimensions, path) ⇒ Object

Build the argv for tool to screenshot target at [w, h] into path. Kept pure (no side effects) so it's unit-testable without a browser.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/docs_kit/og_generator.rb', line 74

def command_for(tool, target, dimensions, path)
  width, height = dimensions
  case tool
  when "shot-scraper"
    ["shot-scraper", target, "--width", width.to_s, "--height", height.to_s, "-o", path]
  else # a chromium/chrome family binary
    [
      tool, "--headless=new", "--disable-gpu", "--hide-scrollbars",
      "--force-device-scale-factor=1",
      "--window-size=#{width},#{height}",
      "--screenshot=#{path}", target
    ]
  end
end

#resolve_shooter!Object

Resolve the shooter CLI: an explicit override (returned as-is so a user can force a specific tool), else the first supported binary on PATH. Raises NoShooterError naming the options when none is found.

Raises:



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/docs_kit/og_generator.rb', line 60

def resolve_shooter!
  return @shooter if @shooter && !@shooter.to_s.empty?

  found = SHOOTERS.find { |cmd| which(cmd) }
  return found if found

  raise NoShooterError,
        "No headless-browser CLI found. Install one of: shot-scraper " \
        "(`pipx install shot-scraper && shot-scraper install`), chromium, or " \
        "chrome — or set DOCS_KIT_SHOT to the command to use."
end

#shooter_nameObject

The chosen shooter name (explicit override or nil until #resolve_shooter!).



39
# File 'lib/docs_kit/og_generator.rb', line 39

def shooter_name = @shooter