├── .gitignore
├── Gemfile
├── LICENSE
├── LICENSE.txt
├── README.md
├── Rakefile
├── jekyll-auto-image.gemspec
├── lib
├── jekyll-auto-image.rb
└── jekyll-auto-image
│ └── version.rb
└── test
├── fixtures
├── _posts
│ └── 2015-01-01-post-with-contents-image.md
├── contents-html.html
├── contents-image.md
├── front-matter-image.md
└── no-image.md
├── helper.rb
└── test_jekyll_auto_image.rb
/.gitignore:
--------------------------------------------------------------------------------
1 | *.gem
2 | *.rbc
3 | .bundle
4 | .config
5 | .yardoc
6 | Gemfile.lock
7 | InstalledFiles
8 | _yardoc
9 | coverage
10 | doc/
11 | lib/bundler/man
12 | pkg
13 | rdoc
14 | spec/reports
15 | test/tmp
16 | test/version_tmp
17 | tmp
18 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 |
3 | # Specify your gem's dependencies in jekyll-auto-image.gemspec
4 | gemspec
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Merlos
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Juan M. Merlos (@merlos) jekyll-auto-image
2 |
3 | MIT License
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining
6 | a copy of this software and associated documentation files (the
7 | "Software"), to deal in the Software without restriction, including
8 | without limitation the rights to use, copy, modify, merge, publish,
9 | distribute, sublicense, and/or sell copies of the Software, and to
10 | permit persons to whom the Software is furnished to do so, subject to
11 | the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be
14 | included in all copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # jekyll-auto-image plugin
2 |
3 | jekyll plugin that makes available the first image of a post in the template as a variable.
4 |
5 | By installing the plugin you will be able to access the first image of a page through `{{ @page.image }}`.
6 |
7 | This plugin is useful if you want to:
8 |
9 | * Include an image on your list of posts
10 | * Set a twitter card image for a post (see example below)
11 |
12 |
13 | # Install
14 |
15 | Add to your Gemfile:
16 |
17 | ```
18 | gem 'jekyll-auto-image'
19 | ```
20 | or run
21 |
22 | ```
23 | $ gem install jekyll-auto-image
24 | ```
25 |
26 |
27 | Then, add to your `_config.yml`:
28 |
29 | ```yaml
30 | gems:
31 | - jekyll-auto-image
32 | ```
33 |
34 | The plugin allows you to set a default image for all pages/posts. To do that, add to your `_config.yml`:
35 |
36 | ```yaml
37 | # _config.yml
38 |
39 | image: /path/to/your/default/image.png
40 | ```
41 |
42 | ### Jekyll 3.0
43 | Versions of jekyll-auto-image >= 1.1.0 are compatible with jekyll 3.0. If you require compatibility with jekyll 2.0 use jekyll-auto-image 1.0.2.
44 |
45 | ```
46 | # Run this command check installed versions
47 | $ gem list | grep jekyll
48 | jekyll (3.0.1)
49 | jekyll-auto-image (1.0.2)
50 | ```
51 |
52 | # Usage
53 |
54 | In each post/page, the plugin will set `{{ page.image }}` following this fallback rules:
55 |
56 | 1. Front matter `image` value
57 | 2. First image in the post/page contents
58 | 3. Default site image (defined in `_config.yml`)
59 | 4. nil
60 |
61 | Basically, the plugin will return the front matter image value if set. If it is not set, then it will look for the first image asset that is defined in your post content. If the post does not have any image, then it will set the site.image defined in _config.yml.
62 |
63 |
64 | ### Example of usage
65 |
66 | Example post 1:
67 |
68 | ```markdown
69 | ---
70 | layout: post
71 | title: Post 1
72 | ---
73 |
74 | This is my example post. It includes an image in the contents.
75 |
76 | 
77 |
78 | ```
79 | Example post 2:
80 |
81 | ```markdown
82 | ---
83 | layout: post
84 | title: Post 2
85 | image: /assets/front_matter_image.png
86 | ---
87 |
88 | This is my second example post, because the
89 | post includes the front matter image, the plugin
90 | will return it instead of the first image in the
91 | contents.
92 |
93 | 
94 |
95 | ```
96 |
97 | #### Template example
98 |
99 | ```liquid
100 | {% for post in site.posts %}
101 | title: {{ post.title }}
102 |
103 | image: {{ post.image }}
104 |
105 | ```
106 |
107 | #### Output HTML Rendered:
108 |
109 | ```html
110 | title: Post 1
111 |
112 | image: /assets/first_image.png
113 |
114 |
115 | title: Post 2
116 |
117 | image: /assets/front_matter_image.png
118 | ```
119 | ### Example using twitter cards
120 |
121 | Another use of this plugin is to create a [twitter card](https://dev.twitter.com/cards/getting-started).
122 |
123 | You can define a set of `` elements in your `head.html` template, so when sharing a post in twitter, the tweet displays it in cool way. You have more info in [twitter's developers page](https://dev.twitter.com/cards/types)
124 |
125 | Here you have a sample:
126 |
127 | ```html
128 |
129 |
130 |
131 |
132 |
133 |
134 | {% if page.image %}
135 |
136 | {% endif %}
137 |
138 | ```
139 |
140 | You can validate how it will look using the [cards validator](https://cards-dev.twitter.com/validator)
141 |
142 |
143 | # Contributing
144 |
145 | 1. Fork it (https://github.com/merlos/jekyll-auto-image/fork)
146 | 2. Create your feature branch (`git checkout -b my-new-feature)
147 | 3. Commit your changes (`git commit -am 'Add some feature'`)
148 | 4. Push to the branch (git push origin my-new-feature)
149 | 4. Create a new Pull Request
150 |
151 | # Run tests
152 |
153 | ```
154 | $ rake test
155 | ```
156 |
157 | The tests are based on the code of [https://github.com/ivantsepp/jekyll-autolink_email](https://github.com/ivantsepp/jekyll-autolink_email)
158 |
159 |
160 | # License
161 |
162 | Copyright (c) 2015 Juan M. Merlos (@merlos) [www.merlos.org](http://www.merlos.org) Distributed under MIT License
163 |
164 |
165 |
166 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | require "bundler/gem_tasks"
2 | require 'rake/testtask'
3 |
4 | Rake::TestTask.new(:test) do |t|
5 | t.libs << 'test'
6 | t.test_files = FileList['test/test_*.rb']
7 | t.verbose = true
8 | end
--------------------------------------------------------------------------------
/jekyll-auto-image.gemspec:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | lib = File.expand_path('../lib', __FILE__)
3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 | require 'jekyll-auto-image/version'
5 |
6 | Gem::Specification.new do |spec|
7 | spec.name = "jekyll-auto-image"
8 | spec.version = Jekyll::AutoImage::VERSION
9 | spec.authors = ["merlos"]
10 | spec.email = ["jmmerlos@merlos.org"]
11 | spec.summary = %q{jekyll plugin that makes available the first image of a post in the template}
12 | spec.description = %q{jekyll plugin that makes available the first image of a post in the template}
13 | spec.homepage = "https://github.com/merlos/jekyll-auto-image"
14 | spec.license = "MIT"
15 |
16 | spec.files = `git ls-files`.split($/)
17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19 | spec.require_paths = ["lib"]
20 |
21 | spec.add_dependency "jekyll"
22 |
23 | spec.add_development_dependency "bundler", "~> 1.5"
24 | spec.add_development_dependency "rake"
25 | spec.add_development_dependency "shoulda"
26 | spec.add_development_dependency "mocha"
27 |
28 | end
29 |
--------------------------------------------------------------------------------
/lib/jekyll-auto-image.rb:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2015 Juan M. Merlos (@merlos) jekyll-auto-image
3 | #
4 | # MIT License
5 | #
6 | # Permission is hereby granted, free of charge, to any person obtaining
7 | # a copy of this software and associated documentation files (the
8 | # "Software"), to deal in the Software without restriction, including
9 | # without limitation the rights to use, copy, modify, merge, publish,
10 | # distribute, sublicense, and/or sell copies of the Software, and to
11 | # permit persons to whom the Software is furnished to do so, subject to
12 | # the following conditions:
13 | #
14 | # The above copyright notice and this permission notice shall be
15 | # included in all copies or substantial portions of the Software.
16 | #
17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 | # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 | # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 |
25 |
26 | require "jekyll-auto-image/version"
27 | require "jekyll"
28 |
29 | module Jekyll
30 |
31 | #
32 | # Auto Image Generator
33 | #
34 | # Sets {{page.image}} variable in liquid with the following fallback:
35 | #
36 | # 1) image value in front matter
37 | # 2) first image in the post/pàge
38 | # 3) _config.yaml image default
39 | # 4) nothing (not set)
40 | #
41 | #
42 | class AutoImageGenerator < Generator
43 |
44 | def generate(site)
45 | @site = site
46 |
47 | site.pages.each do |page|
48 | img = get_image(page)
49 | page.data['image'] = img if img
50 | end
51 | # Now do the same with posts
52 | site.posts.docs.each do |post|
53 | #puts "hola"
54 | #puts Jekyll::VERSION
55 | #puts post.class
56 | #puts post.inspect
57 | #puts post.data.inspect
58 | #puts "-----"
59 | #puts post.output
60 | #puts "----"
61 | img = get_image(post)
62 | post.data['image'] = img if img
63 | end
64 | end # generate
65 |
66 | #
67 | # page: is either a Jekyll::Page or a Jekyll::Post in 2.x. In Jekyll 3.0 is Jekyll::Document and
68 | # in Jekyll 3.3 is either Jekyll::Page or Jekyll::Document (fascinating!)
69 | #
70 | # returns the path of the first image found in the contents
71 | # of the page/post
72 | #
73 | def get_image(page)
74 |
75 | # debug lines
76 | #puts page.title
77 | #puts page.name
78 | #puts page.ext
79 | #puts @site.converters.select { |c| c.matches(page.ext) }.sort
80 | if page.data['image']
81 | return page.data['image']
82 | end
83 |
84 | # fix for jekyll 3.3.0,
85 | @site.config['kramdown'] = @site.config['kramdown'].dup
86 |
87 | # convert the contents to html, and extract the first
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus, ante ut tincidunt placerat, sapien nulla lobortis tellus, vel consequat quam est eget ligula.
6 |
7 |
8 |
9 |
10 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus, ante ut tincidunt placerat, sapien nulla lobortis tellus, vel consequat quam est eget ligula.
11 |
12 |
13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus, ante ut tincidunt placerat, sapien nulla lobortis tellus, vel consequat quam est eget ligula.
14 |
--------------------------------------------------------------------------------
/test/fixtures/contents-image.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Page with an image in the contents
3 | ---
4 |
5 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus, ante ut tincidunt placerat, sapien nulla lobortis tellus, vel consequat quam est eget ligula.
6 |
7 | 
8 |
9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus, ante ut tincidunt placerat, sapien nulla lobortis tellus, vel consequat quam est eget ligula.
10 |
11 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin finibus, ante ut tincidunt placerat, sapien nulla lobortis tellus, vel consequat quam est eget ligula.
--------------------------------------------------------------------------------
/test/fixtures/front-matter-image.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Page that defines the front matter image
3 | image: /assets/front-matter-image.png
4 | ---
5 |
6 | Although this post has the following image in the contents, the plugin should set the one in the frontmatter
7 |
8 | 
--------------------------------------------------------------------------------
/test/fixtures/no-image.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: this page does not have an image
3 | ---
4 |
5 | This post does not have an image, in the fallback rules it should display the site.image or nothing if site.image is not defined in _config.yml
--------------------------------------------------------------------------------
/test/helper.rb:
--------------------------------------------------------------------------------
1 | require 'minitest/autorun'
2 | require 'minitest/unit'
3 | require 'shoulda'
4 | require 'mocha/mini_test'
5 | require 'jekyll'
6 | require 'jekyll-auto-image'
7 |
--------------------------------------------------------------------------------
/test/test_jekyll_auto_image.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 |
3 | class Jekyll::AutoImageTest < Minitest::Test
4 | def set_page_image (page, image_path)
5 | page.instance_variable_set(:@content, '
')
6 | end
7 |
8 | context 'AutoImage' do
9 |
10 | setup do
11 |
12 | @default_image_path = '/assets/default_image.png'
13 |
14 | Jekyll.logger.log_level = :error
15 |
16 | #
17 | # Sites
18 | #
19 | @config = Jekyll::Configuration::DEFAULTS.dup
20 | @config['destination'] = File.expand_path('../tmp/', __FILE__)
21 | @site = Jekyll::Site.new(@config)
22 |
23 | # config with default image
24 | @config_with_image = @config.dup
25 | @config_with_image['image'] = @default_image_path
26 | @site_with_default_image = Jekyll::Site.new(@config_with_image)
27 |
28 | # posts are in test/fixtures/_posts/
29 | @config_with_posts = @config.dup
30 | @config_with_posts['source'] = File.expand_path('../fixtures/', __FILE__)
31 | @site_with_posts = Jekyll::Site.new(@config_with_posts)
32 | # now add the collection
33 | @posts_collection = Jekyll::Collection.new(@site_with_posts, 'posts')
34 |
35 | # Pages
36 | @no_image_page = Jekyll::Page.new(@site, File.expand_path('../fixtures/', __FILE__), '', 'no-image.md')
37 | @front_matter_image_page = Jekyll::Page.new(@site, File.expand_path('../fixtures/', __FILE__), '', 'front-matter-image.md')
38 | @contents_image_page = Jekyll::Page.new(@site, File.expand_path('../fixtures/', __FILE__), '', 'contents-image.md')
39 | @contents_html_page = Jekyll::Page.new(@site, File.expand_path('../fixtures/', __FILE__), '', 'contents-html.html')
40 |
41 | # Posts as collections
42 | #@contents_html_page = Jekyll::Document.new(File.expand_path('../fixtures/_posts/contents-image.md', __FILE__), {:site =>@site,:collection =>'post'})
43 |
44 |
45 | @auto_image = Jekyll::AutoImageGenerator.new
46 | @auto_image.generate(@site)
47 | @auto_image_with_default_image = Jekyll::AutoImageGenerator.new
48 | @auto_image_with_default_image.generate(@site_with_default_image)
49 |
50 |
51 | #@page.instance_variable_set(:@content, 'ivan.tse1@gmail.com
')
52 | #@site.pages << @page
53 | #@email_link = ''
54 | end
55 |
56 |
57 | #
58 | # FALLBACK LOGIC TESTS
59 | #
60 |
61 | # Tests without {{site.image}}
62 |
63 | should 'not be defined site image by default' do
64 | assert_nil @site.config['image']
65 | end
66 |
67 | should 'not return image when not set in config and not included in page' do
68 | assert_nil @auto_image.get_image(@no_image_page)
69 | end
70 |
71 | should 'use front matter image whenever defined' do
72 | assert_equal @front_matter_image_page.data['image'], @auto_image.get_image(@front_matter_image_page)
73 | end
74 |
75 | should 'detect contents image on markdown' do
76 | assert_equal '/assets/contents-image.png', @auto_image.get_image(@contents_image_page)
77 | end
78 |
79 | should 'detect contents image in html' do
80 | assert_equal '/assets/contents-html.png', @auto_image.get_image(@contents_html_page)
81 | end
82 |
83 | # Tests with {{site.image}} defined
84 |
85 | should 'be defined site_image in config' do
86 | assert_equal @default_image_path, @site_with_default_image.config['image']
87 | end
88 |
89 | should 'return default image when page does not have image' do
90 | assert_equal @site_with_default_image.config['image'], @auto_image_with_default_image.get_image(@no_image_page)
91 | end
92 |
93 | should 'return front matter image even if default image is defined' do
94 | assert_equal @front_matter_image_page.data['image'], @auto_image_with_default_image.get_image(@front_matter_image_page)
95 | end
96 |
97 |
98 | #
99 | # Tests to check if the regexp works in some use cases
100 | #
101 | should 'find contents image that includes http' do
102 | image ="http://github.com/merlos/jekyll-auto-image/yes.png"
103 | set_page_image(@no_image_page,image)
104 | assert image, @auto_image.get_image(@no_image_page)
105 | end
106 |
107 | #
108 | # Tests to check if the regexp works in some use cases
109 | #
110 | should 'find image with weird characters in name' do
111 | image ="http://github.com/merlos/%$·$%&/(),.-,.-./yes.png"
112 | set_page_image(@no_image_page,image)
113 | assert image, @auto_image.get_image(@no_image_page)
114 | end
115 |
116 | #
117 | # Tests to check if the regexp works in some use cases
118 | #
119 | should 'not find image with space in name' do
120 | image ="http://github.com/merlos/jekyll auto image/yes.png"
121 | set_page_image(@no_image_page,image)
122 | assert_nil @auto_image.get_image(@no_image_page)
123 | end
124 |
125 | #
126 | # Generate site with data
127 | #
128 | should 'generate a site with a page' do
129 | #add page to site
130 | @site.pages << @contents_image_page
131 | @site.generate()
132 | @auto_image.generate(@site)
133 | @auto_image.get_image(@contents_html_page)
134 | assert_equal '/assets/contents-html.png', @auto_image.get_image(@contents_html_page)
135 | end
136 |
137 | should 'generate a site with post as part of collection' do
138 | #puts @posts_collection.directory
139 | assert_equal 1, @posts_collection.entries.length
140 | assert_equal 1, @posts_collection.filtered_entries.length
141 | @site_with_posts.process
142 | @auto_image.generate(@site_with_posts)
143 | assert_equal 1, @site_with_posts.posts.docs.length
144 | #puts @site_with_posts.collections.inspect
145 | assert_equal '/assets/contents-image.png', @auto_image.get_image(@site_with_posts.posts.docs[0])
146 | end
147 |
148 |
149 | end
150 | end
151 |
--------------------------------------------------------------------------------