middleman-social_image 0.0.1 → 0.0.6

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: fb0b030a5107566244948ab289a30177c59bd5d5754022fc32d816507b7540fe
4
- data.tar.gz: 63da5dd031a4a50a2df41f05ad10816e5c0b7853a823d4a10850df693ae24ccd
3
+ metadata.gz: 4b33a5a00bdde76bcf00c4c872bcc525e691874adf5bd95a12d92e52f38974e4
4
+ data.tar.gz: 992ac18e68e3f25e9f9bd8c1ef0b3af7a253e75aef05a442b63ed6278a769323
5
5
  SHA512:
6
- metadata.gz: 4eb79e1af1523f4fd77a616d108a8b53440c3122690a98c338cb8a164ea4262a9726b8686314b5ffa15d8b18604cd9ffb1b11f3db516f7f597146fb2823db4f9
7
- data.tar.gz: 99c2d6ebaad6d2a4dbaa1e03c6ed2d903411183137b612e710ccc134bc5367c1f63a6418ddf020811679d57194302e9d807995093fcf76b89698fddf5ca7dfcd
6
+ metadata.gz: 86ea9bb9a3bb9759e770e1633058c2390594096d182fd68b221c3e67abf0b8fa95800cce97ac0b3eb23a2dc1623cc3c89e451be6b11a12a80c0faa50bb2cff44
7
+ data.tar.gz: ab6aaf979d769b23ec82ee5d056fd7d6f604b7f298d088472b4ef32a824602ba58555e2f867ff53d466f93f44b978b5ca9e3b42f325c6f7fa4f2e66dbf98e668
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
 
@@ -24,19 +30,21 @@ Optionally, you can configure this extension with the following (defaults are sh
24
30
 
25
31
  ```ruby
26
32
  activate :social_image do |social_image|
27
- social_image.path_to_chrome = '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome' # Command to execute chrome
28
33
  social_image.window_size = '1200,600' # The size of the screenshot
29
- social_image.base_url = 'http://localhost:4567/' # Base URL of running middleman server
30
- social_image.base_asset_dir = 'assets/images/social-images' # Where to save the generated images
31
- social_image.social_image_url_pattern = %r{(/social-image)/$} # Screenshot URLs matching this pattern
32
- 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.parallel = true # Generate images in parallel.
36
+ social_image.base_url = "http://localhost:4567/" # When building the site, fetch against this URL.
33
37
  end
34
38
  ```
35
39
 
36
- 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/`).
37
-
38
- Start up the middleman server with `bundle exec middleman server`
40
+ 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.
39
41
 
40
- 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`.
42
+ ``` ruby
43
+ ["tom", "dick", "harry"].each do |name|
44
+ proxy "/social-image/#{name}.html", "/templates/social-image.html", social_image: true, locals: { name: name }
45
+ end
46
+ ```
41
47
 
42
48
  You can now refer to this image as normal within your middleman application.
49
+
50
+ 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,37 @@
1
+ require "middleman-social_image/capybara"
2
+ class Middleman::SocialImage::Converter
3
+ def initialize(app, window_size, selector, base_url)
4
+ @app = app
5
+ @window_size = window_size
6
+ @selector = selector
7
+ @base_url = base_url
8
+ end
9
+
10
+ def image_path(resource)
11
+ File.join(@app.root, "tmp/middleman-social_image", resource.path.sub(".html", ".png"))
12
+ end
13
+
14
+ def convert(resource)
15
+ image_path = image_path(resource)
16
+ @app.logger.debug "== social_image: converting #{resource.path}"
17
+ session.visit(File.join(@base_url, resource.url))
18
+ raise "#{resource.url} did not contain '#{@selector}'." unless session.has_selector?(@selector)
19
+ FileUtils.mkdir_p(File.dirname(image_path))
20
+ session.save_screenshot(image_path)
21
+ end
22
+
23
+ private
24
+
25
+ def session
26
+ @session ||= begin
27
+ if @app.server?
28
+ rack_app = ::Middleman::Rack.new(@app).to_app
29
+ session = Capybara::Session.new(:selenium_chrome_headless, rack_app)
30
+ else
31
+ session = Capybara::Session.new(:selenium_chrome_headless)
32
+ end
33
+ session.current_window.resize_to(*@window_size.split(","))
34
+ session
35
+ end
36
+ end
37
+ end
@@ -1,11 +1,63 @@
1
1
  require 'middleman-core'
2
- require 'middleman-social_image/commands'
3
2
 
4
3
  class Middleman::SocialImage::Extension < ::Middleman::Extension
5
- option :path_to_chrome, '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome'
6
4
  option :window_size, '1200,600'
7
- option :base_url, 'http://localhost:4567/'
8
- option :base_asset_dir, 'assets/images/social-images'
9
- option :social_image_url_pattern, %r{(/social-image)/$}
10
- option :social_image_url_substitution, '\1.png'
5
+ option :selector, "body > *"
6
+ option :parallel, true
7
+ option :base_url, "http://localhost:4567/"
8
+
9
+ def initialize(app, options_hash={}, &block)
10
+ super
11
+ require "middleman-social_image/converter"
12
+ require "middleman-social_image/resource"
13
+ @converter = Middleman::SocialImage::Converter.new(app, options.window_size, options.selector, options.base_url)
14
+ end
15
+
16
+ def manipulate_resource_list(resources)
17
+ if app.build?
18
+ manipulate_resource_list_for_build(resources)
19
+ else
20
+ manipulate_resource_list_for_preview(resources)
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ def social_image_source_resources
27
+ app.sitemap.resources.select {|resource| resource.options[:social_image] || resource.data[:social_image] }
28
+ end
29
+
30
+ def path_for_source_resource(resource)
31
+ resource.path.sub(".html", ".png")
32
+ end
33
+
34
+ def manipulate_resource_list_for_build(resources)
35
+ convert_resource = proc do |resource|
36
+ @converter.convert(resource)
37
+ end
38
+ if options.parallel
39
+ ::Parallel.each(social_image_source_resources, &convert_resource)
40
+ else
41
+ social_image_source_resources.each(&convert_resource)
42
+ end
43
+ social_image_resources = social_image_source_resources.map do |resource|
44
+ Middleman::Sitemap::Resource.new(
45
+ @app.sitemap,
46
+ path_for_source_resource(resource),
47
+ @converter.image_path(resource)
48
+ )
49
+ end
50
+ resources + social_image_resources - social_image_source_resources
51
+ end
52
+
53
+ def manipulate_resource_list_for_preview(resources)
54
+ resources + social_image_source_resources.map do |resource|
55
+ Middleman::SocialImage::Resource.new(
56
+ @app.sitemap,
57
+ path_for_source_resource(resource),
58
+ @converter,
59
+ resource
60
+ )
61
+ end
62
+ end
11
63
  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.1'.freeze
3
+ VERSION = '0.0.6'.freeze
4
4
  end
5
5
  end
@@ -22,4 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.bindir = "exe"
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency( "middleman-core", [ ">= 4.0.0" ] )
27
+ spec.add_dependency( "capybara" )
28
+ spec.add_dependency( "selenium-webdriver" )
25
29
  end
metadata CHANGED
@@ -1,15 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: middleman-social_image
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.6
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-08 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2020-06-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: middleman-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: capybara
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: selenium-webdriver
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
13
55
  description:
14
56
  email:
15
57
  - paul@tokyodev.com
@@ -25,8 +67,10 @@ files:
25
67
  - bin/console
26
68
  - bin/setup
27
69
  - lib/middleman-social_image.rb
28
- - lib/middleman-social_image/commands.rb
70
+ - lib/middleman-social_image/capybara.rb
71
+ - lib/middleman-social_image/converter.rb
29
72
  - lib/middleman-social_image/extension.rb
73
+ - lib/middleman-social_image/resource.rb
30
74
  - lib/middleman-social_image/version.rb
31
75
  - middleman-social_image.gemspec
32
76
  homepage: https://github.com/pwim/middleman-social_image
@@ -1,39 +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
- app = ::Middleman::Application.new do
18
- config[:mode] = :config
19
- config[:watcher_disable] = true
20
- end
21
- options = app.extensions[:social_image].options
22
- app.sitemap.resources.each do |resource|
23
- if resource.url =~ options.social_image_url_pattern
24
- image_path = File.join(app.source_dir, options.base_asset_dir, resource.url.sub(options.social_image_url_pattern, options.social_image_url_substitution))
25
- if File.exists?(image_path)
26
- say "Image for #{resource.url} already generated, skipping."
27
- else
28
- FileUtils.mkdir_p(File.dirname(image_path))
29
- url = File.join(options.base_url, resource.url)
30
- run "#{options.path_to_chrome} --headless --disable-gpu --screenshot=#{image_path} --window-size=#{options.window_size} #{url}"
31
- end
32
- end
33
- end
34
- end
35
- end
36
-
37
- Base.register(Middleman::Cli::SocialImage, 'social_image', 'social_image [options]', 'Generates social images.')
38
- end
39
- end