middleman-social_image 0.0.2 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b385845fc4206a82deb572478bead5cfe8eed70c74757bf128e611179987c310
4
- data.tar.gz: 84bdf82a6bfe4314c73322d2ae664a802cf3c90788e0af26a2750cb7496cb56b
3
+ metadata.gz: 6903e2e4c9c370bcff55abbc8ffd6a6d2333b67db7d3fe127b6ebb0b4d3b1ec9
4
+ data.tar.gz: a4b1388cdd36533812451638ecb7651c40ef898bdf3d9f6e714c7b82304a29b2
5
5
  SHA512:
6
- metadata.gz: 0cf692ac57d02ba0f7c69009cc365ced16a8f9b75d3809b70e1d8e319c0f4542065fae4aa5dcc1e85c34f3c5960c14e75b292b7465debb82dcc9c33b2af309bc
7
- data.tar.gz: f68d00fa0cf0ff4ead068b2baac8f0a1be7ca00ce7d72c51e2d18f362ed37e733aa01bb2e586e415abd79eb075c70fb9491f750deb70330db154447834c358a7
6
+ metadata.gz: 1da14d580fce03713d103ab310067911ff16030e56334cf287797ed9a859ad798dabd4cfdb1906464d39a552d4787a10c069d67489242c6e3fe51343800989b0
7
+ data.tar.gz: 523f65bd90f08997969ea286454551566657fa3b189856e12e0ce2b4b12d533a55c00ee240e4a129a676b9cc98015db15e2d98b3529028ad473d5445700df432
data/.gitignore CHANGED
@@ -9,3 +9,4 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+ Gemfile.lock
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Middleman::SocialImage
2
2
 
3
- Use HTML and CSS to dynamically generate static images for Open Graph (Facebook, LinkedIn) and Twitter cards in a Middleman application. Image is generated by using Google Chrome in headless mode to screenshot a page served by middleman. Originally created for [tokyodev](https://www.tokyodev.com/), which lists internationally-friendly software developer jobs in Japan.
3
+ Use HTML and CSS to generate images when building your Middleman site. The intended use case is for generating images for use with [the Open Graph protocol](https://ogp.me/), which will be included when someone shares your page on Facebook, Twitter, etc.
4
+
5
+ Example of an image generated with this extension:
6
+
7
+ ![](https://www.tokyodev.com/2020/05/29/generating-social-images-with-static-site-generators/social-image-714b5c6e.png)
8
+
9
+ For more background, see [generating social images with static site generators](https://www.tokyodev.com/2020/05/29/generating-social-images-with-static-site-generators/).
4
10
 
5
11
  ## Installation
6
12
 
@@ -25,17 +31,21 @@ Optionally, you can configure this extension with the following (defaults are sh
25
31
  ```ruby
26
32
  activate :social_image do |social_image|
27
33
  social_image.window_size = '1200,600' # The size of the screenshot
28
- social_image.base_url = 'http://localhost:4567/' # Base URL of running middleman server
29
- social_image.base_asset_dir = 'assets/images/social-images' # Where to save the generated images
30
- social_image.social_image_url_pattern = %r{(/social-image)/$} # Screenshot URLs matching this pattern
31
- social_image.social_image_url_substitution, '\1.png' # When generating screenshots, replace URLs matching social_image_url_pattern with this
34
+ social_image.selector = 'body > *' # Used to test that the social image url has loaded properly. The more specific this is, the better the chance of catching errors.
35
+ social_image.always_generate = true # Always regenerate images. Takes a long time, but ensures any changes are reflected.
36
+ social_image.parallel = true # Generate images in parallel.
37
+ social_image.base_url = "http://localhost:4567/" # When building the site, fetch against this URL.
32
38
  end
33
39
  ```
34
40
 
35
- Create a HTML page in your middleman app that contains the HTML you want to be rendered. The URL for this should match the social_image_url_pattern (so by default, ending with `/social-image/`).
36
-
37
- Start up the middleman server with `bundle exec middleman server`
41
+ Create a HTML page in your middleman app that contains the HTML you want to be rendered. Add `social_image: true` to the page's front matter to indicate it is the source for a social image. You can also add it as an option if you're using a proxy page like the following.
38
42
 
39
- Run the `bundle exec middleman social_image` command to generate images from any URLs matching social_image_url_pattern. The image will be saved to a location matching the URL of the resource used to generate it, with the social_image_url_substitution applied, in the base_asset_dir. So with the default settings, if for instance you had created a page at `/examples/social-image/`, this image would be saved at `assets/images/social-images/examples/social-image.png`.
43
+ ``` ruby
44
+ ["tom", "dick", "harry"].each do |name|
45
+ proxy "/social-image/#{name}.html", "/templates/social-image.html", social_image: true, locals: { name: name }
46
+ end
47
+ ```
40
48
 
41
49
  You can now refer to this image as normal within your middleman application.
50
+
51
+ In preview mode, you don't need any other special setup. However, to generate the images in build, you also need to be running the preview server. While you can use `bundle exec middleman server`, using a concurrent server like puma can speed up the generation incredibly. To do this, you'll need to [create a config.ru file](https://middlemanapp.com/basics/start-new-site/#config-ru).
@@ -3,6 +3,5 @@ require 'middleman-social_image/version'
3
3
 
4
4
  Middleman::Extensions.register :social_image do
5
5
  require "middleman-social_image/extension"
6
- require 'middleman-social_image/commands'
7
6
  Middleman::SocialImage::Extension
8
7
  end
@@ -0,0 +1,12 @@
1
+ require "capybara"
2
+ Capybara.server = :webrick
3
+ Capybara.register_driver :selenium_chrome_headless do |app|
4
+ Capybara::Selenium::Driver.load_selenium
5
+ browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
6
+ opts.args << '--headless'
7
+ opts.args << '--disable-gpu' if Gem.win_platform?
8
+ opts.args << '--disable-site-isolation-trials'
9
+ opts.args << '--hide-scrollbars'
10
+ end
11
+ Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
12
+ end
@@ -0,0 +1,42 @@
1
+ require "middleman-social_image/capybara"
2
+ class Middleman::SocialImage::Converter
3
+ def initialize(app, window_size, selector, always_generate, base_url)
4
+ @app = app
5
+ @window_size = window_size
6
+ @selector = selector
7
+ @always_generate = always_generate
8
+ @base_url = base_url
9
+ end
10
+
11
+ def image_path(resource)
12
+ File.join(@app.root, "tmp/middleman-social_image", resource.path.sub(".html", ".png"))
13
+ end
14
+
15
+ def convert(resource)
16
+ image_path = image_path(resource)
17
+ if File.exist?(image_path) && !@always_generate
18
+ @app.logger.debug "== social_image: skipping #{resource.path} as already in cache"
19
+ else
20
+ @app.logger.debug "== social_image: converting #{resource.path}"
21
+ session.visit(File.join(@base_url, resource.url))
22
+ raise "#{resource.url} did not contain '#{@selector}'." unless session.has_selector?(@selector)
23
+ FileUtils.mkdir_p(File.dirname(image_path))
24
+ session.save_screenshot(image_path)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def session
31
+ @session ||= begin
32
+ if @app.server?
33
+ rack_app = ::Middleman::Rack.new(@app).to_app
34
+ session = Capybara::Session.new(:selenium_chrome_headless, rack_app)
35
+ else
36
+ session = Capybara::Session.new(:selenium_chrome_headless)
37
+ end
38
+ session.current_window.resize_to(*@window_size.split(","))
39
+ session
40
+ end
41
+ end
42
+ end
@@ -1,10 +1,64 @@
1
1
  require 'middleman-core'
2
- require 'middleman-social_image/commands'
3
2
 
4
3
  class Middleman::SocialImage::Extension < ::Middleman::Extension
5
4
  option :window_size, '1200,600'
6
- option :base_url, 'http://localhost:4567/'
7
- option :base_asset_dir, 'assets/images/social-images'
8
- option :social_image_url_pattern, %r{(/social-image)/$}
9
- option :social_image_url_substitution, '\1.png'
5
+ option :selector, "body > *"
6
+ option :always_generate, true
7
+ option :parallel, true
8
+ option :base_url, "http://localhost:4567/"
9
+
10
+ def initialize(app, options_hash={}, &block)
11
+ super
12
+ require "middleman-social_image/converter"
13
+ require "middleman-social_image/resource"
14
+ @converter = Middleman::SocialImage::Converter.new(app, options.window_size, options.selector, options.always_generate, options.base_url)
15
+ end
16
+
17
+ def manipulate_resource_list(resources)
18
+ if app.build?
19
+ manipulate_resource_list_for_build(resources)
20
+ else
21
+ manipulate_resource_list_for_preview(resources)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def social_image_source_resources
28
+ app.sitemap.resources.select {|resource| resource.options[:social_image] || resource.data[:social_image] }
29
+ end
30
+
31
+ def path_for_source_resource(resource)
32
+ resource.path.sub(".html", ".png")
33
+ end
34
+
35
+ def manipulate_resource_list_for_build(resources)
36
+ convert_resource = proc do |resource|
37
+ @converter.convert(resource)
38
+ end
39
+ if options.parallel
40
+ ::Parallel.each(social_image_source_resources, &convert_resource)
41
+ else
42
+ social_image_source_resources.each(&convert_resource)
43
+ end
44
+ social_image_resources = social_image_source_resources.map do |resource|
45
+ Middleman::Sitemap::Resource.new(
46
+ @app.sitemap,
47
+ path_for_source_resource(resource),
48
+ @converter.image_path(resource)
49
+ )
50
+ end
51
+ resources + social_image_resources - social_image_source_resources
52
+ end
53
+
54
+ def manipulate_resource_list_for_preview(resources)
55
+ resources + social_image_source_resources.map do |resource|
56
+ Middleman::SocialImage::Resource.new(
57
+ @app.sitemap,
58
+ path_for_source_resource(resource),
59
+ @converter,
60
+ resource
61
+ )
62
+ end
63
+ end
10
64
  end
@@ -0,0 +1,12 @@
1
+ class Middleman::SocialImage::Resource < ::Middleman::Sitemap::Resource
2
+ def initialize(store, path, converter, base_resource)
3
+ super(store, path)
4
+ @converter = converter
5
+ @base_resource = base_resource
6
+ end
7
+
8
+ def render(*)
9
+ @converter.convert(@base_resource)
10
+ File.read(@converter.image_path(@base_resource))
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  module Middleman
2
2
  module SocialImage
3
- VERSION = '0.0.2'.freeze
3
+ VERSION = '0.0.7'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-social_image
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul McMahon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-12 00:00:00.000000000 Z
11
+ date: 2020-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: middleman-core
@@ -67,8 +67,10 @@ files:
67
67
  - bin/console
68
68
  - bin/setup
69
69
  - lib/middleman-social_image.rb
70
- - lib/middleman-social_image/commands.rb
70
+ - lib/middleman-social_image/capybara.rb
71
+ - lib/middleman-social_image/converter.rb
71
72
  - lib/middleman-social_image/extension.rb
73
+ - lib/middleman-social_image/resource.rb
72
74
  - lib/middleman-social_image/version.rb
73
75
  - middleman-social_image.gemspec
74
76
  homepage: https://github.com/pwim/middleman-social_image
@@ -1,55 +0,0 @@
1
- require 'middleman-cli'
2
-
3
- module Middleman
4
- module Cli
5
- class SocialImage < Thor::Group
6
- include Thor::Actions
7
-
8
- check_unknown_options!
9
-
10
- namespace :social_image
11
-
12
- def self.exit_on_failure?
13
- true
14
- end
15
-
16
- def social_image
17
- require "capybara"
18
- app = ::Middleman::Application.new do
19
- config[:mode] = :config
20
- config[:watcher_disable] = true
21
- end
22
- options = app.extensions[:social_image].options
23
- Capybara.register_driver :selenium_chrome_headless do |app|
24
- Capybara::Selenium::Driver.load_selenium
25
- browser_options = ::Selenium::WebDriver::Chrome::Options.new.tap do |opts|
26
- opts.args << "--window-size=#{options.window_size}"
27
- opts.args << '--headless'
28
- opts.args << '--disable-gpu' if Gem.win_platform?
29
- opts.args << '--disable-site-isolation-trials'
30
- opts.args << '--hide-scrollbars'
31
- end
32
- Capybara::Selenium::Driver.new(app, browser: :chrome, options: browser_options)
33
- end
34
- session = Capybara::Session.new(:selenium_chrome_headless)
35
-
36
- app.sitemap.resources.each do |resource|
37
- if resource.url =~ options.social_image_url_pattern
38
- image_path = File.join(app.source_dir, options.base_asset_dir, resource.url.sub(options.social_image_url_pattern, options.social_image_url_substitution))
39
- if File.exists?(image_path)
40
- say "Skipping #{image_path} as already generated"
41
- else
42
- say "Generating #{image_path}"
43
- FileUtils.mkdir_p(File.dirname(image_path))
44
- url = File.join(options.base_url, resource.url)
45
- session.visit(url)
46
- session.save_screenshot(image_path)
47
- end
48
- end
49
- end
50
- end
51
- end
52
-
53
- Base.register(Middleman::Cli::SocialImage, 'social_image', 'social_image [options]', 'Generates social images.')
54
- end
55
- end