lib/jekyll-linkpreview.rb in jekyll-linkpreview-0.3.2 vs lib/jekyll-linkpreview.rb in jekyll-linkpreview-0.4.0
- old
+ new
@@ -1,96 +1,165 @@
require "digest"
require "json"
+require 'uri'
require "metainspector"
require "jekyll-linkpreview/version"
module Jekyll
module Linkpreview
class OpenGraphProperties
- def get(url)
- og_properties = fetch(url)
- og_url = get_og_property(og_properties, 'og:url')
- domain = extract_domain(og_url)
- image_url = get_og_property(og_properties, 'og:image')
+ @@template_file = 'linkpreview.html'
+
+ def initialize(title, url, image, description, domain)
+ @title = title
+ @url = url
+ @image = image
+ @description = description
+ @domain = domain
+ end
+
+ def to_hash()
{
- 'title' => get_og_property(og_properties, 'og:title'),
- 'url' => og_url,
- 'image' => convert_to_absolute_url(image_url, domain),
- 'description' => get_og_property(og_properties, 'og:description'),
- 'domain' => domain
+ 'title' => @title,
+ 'url' => @url,
+ 'image' => @image,
+ 'description' => @description,
+ 'domain' => @domain,
}
end
+ def to_hash_for_custom_template()
+ {
+ 'link_title' => @title,
+ 'link_url' => @url,
+ 'link_image' => @image,
+ 'link_description' => @description,
+ 'link_domain' => @domain
+ }
+ end
+
+ def template_file()
+ @@template_file
+ end
+ end
+
+ class OpenGraphPropertiesFactory
+ def from_page(page)
+ og_properties = page.meta_tags['property']
+ image_url = get_og_property(og_properties, 'og:image')
+ title = get_og_property(og_properties, 'og:title')
+ url = get_og_property(og_properties, 'og:url')
+ image = convert_to_absolute_url(image_url, page.root_url)
+ description = get_og_property(og_properties, 'og:description')
+ domain = page.host
+ OpenGraphProperties.new(title, url, image, description, domain)
+ end
+
+ def from_hash(hash)
+ OpenGraphProperties.new(
+ hash['title'], hash['url'], hash['image'], hash['description'], hash['domain'])
+ end
+
private
def get_og_property(properties, key)
if !properties.key? key then
return nil
end
- properties[key][0]
+ properties[key].first
end
private
- def fetch(url)
- MetaInspector.new(url).meta_tags['property']
- end
-
- private
def convert_to_absolute_url(url, domain)
if url.nil? then
return nil
end
# root relative url
if url[0] == '/' then
- return "//#{domain}#{url}"
+ return URI.join(domain, url).to_s
end
url
end
+ end
+ class NonOpenGraphProperties
+ @@template_file = 'linkpreview_nog.html'
+
+ def initialize(title, url, description, domain)
+ @title = title
+ @url = url
+ @description = description
+ @domain = domain
+ end
+
+ def to_hash()
+ {
+ 'title' => @title,
+ 'url' => @url,
+ 'description' => @description,
+ 'domain' => @domain,
+ }
+ end
+
+ def to_hash_for_custom_template()
+ {
+ 'link_title' => @title,
+ 'link_url' => @url,
+ 'link_description' => @description,
+ 'link_domain' => @domain
+ }
+ end
+
+ def template_file()
+ @@template_file
+ end
+ end
+
+ class NonOpenGraphPropertiesFactory
+ def from_page(page)
+ NonOpenGraphProperties.new(
+ page.title, page.url, get_description(page), page.host)
+ end
+
+ def from_hash(hash)
+ NonOpenGraphProperties.new(
+ hash['title'], hash['url'], hash['description'], hash['domain'])
+ end
+
private
- def extract_domain(url)
- if url.nil? then
- return nil
+ def get_description(page)
+ if !page.parsed.xpath('//p[normalize-space()]').empty? then
+ return page.parsed.xpath('//p[normalize-space()]').map(&:text).first[0..180] + "..."
+ else
+ return "..."
end
- m = url.match(%r{(http|https)://([^/]+).*})
- if m.nil? then
- return nil
- end
- m[-1]
end
end
class LinkpreviewTag < Liquid::Tag
@@cache_dir = '_cache'
+ @@template_dir = '_includes'
def initialize(tag_name, markup, parse_context)
super
@markup = markup.strip()
- @og_properties = OpenGraphProperties.new
end
def render(context)
url = get_url_from(context)
properties = get_properties(url)
- title = properties['title']
- image = properties['image']
- description = properties['description']
- domain = properties['domain']
-
- if title.nil? || image.nil? || domain.nil? then
- render_linkpreview_nog(context, url)
- else
- render_linkpreview_og(context, url, title, image, description, domain)
- end
+ render_linkpreview properties
end
def get_properties(url)
cache_filepath = "#{@@cache_dir}/%s.json" % Digest::MD5.hexdigest(url)
if File.exist?(cache_filepath) then
- return load_cache_file(cache_filepath)
+ hash = load_cache_file(cache_filepath)
+ return create_properties_from_hash(hash)
end
- properties = @og_properties.get(url)
+ page = fetch(url)
+ properties = create_properties_from_page(page)
if Dir.exists?(@@cache_dir) then
save_cache_file(cache_filepath, properties)
else
# TODO: This message will be shown at all linkprevew tag
warn "'#{@@cache_dir}' directory does not exist. Create it for caching."
@@ -102,78 +171,102 @@
def get_url_from(context)
context[@markup]
end
private
+ def fetch(url)
+ MetaInspector.new(url)
+ end
+
+ private
def load_cache_file(filepath)
JSON.parse(File.open(filepath).read)
end
protected
def save_cache_file(filepath, properties)
- File.open(filepath, 'w') { |f| f.write JSON.generate(properties) }
+ File.open(filepath, 'w') { |f| f.write JSON.generate(properties.to_hash) }
end
private
- def render_linkpreview_og(context, url, title, image, description, domain)
- template_path = get_linkpreview_og_template()
+ def create_properties_from_page(page)
+ if page.meta_tags['property'].empty? then
+ factory = NonOpenGraphPropertiesFactory.new
+ else
+ factory = OpenGraphPropertiesFactory.new
+ end
+ factory.from_page(page)
+ end
+
+ private
+ def create_properties_from_hash(hash)
+ if hash['image'] then
+ factory = OpenGraphPropertiesFactory.new
+ else
+ factory = NonOpenGraphPropertiesFactory.new
+ end
+ factory.from_hash(hash)
+ end
+
+ private
+ def render_linkpreview(properties)
+ template_path = get_custom_template_path properties
if File.exist?(template_path)
- template_file = File.read template_path
- site = context.registers[:site]
- template_file = (Liquid::Template.parse template_file).render site.site_payload.merge!({"link_url" => url, "link_title" => title, "link_image" => image, "link_description" => description, "link_domain" => domain})
+ hash = properties.to_hash_for_custom_template
+ gen_custom_template template_path, hash
else
- html = <<-EOS
+ gen_default_template properties.to_hash
+ end
+ end
+
+ private
+ def get_custom_template_path(properties)
+ File.join Dir.pwd, @@template_dir, properties.template_file
+ end
+
+ private
+ def gen_default_template(hash)
+ title = hash['title']
+ url = hash['url']
+ description = hash['description']
+ domain = hash['domain']
+ image = hash['image']
+ image_html = ""
+ if image then
+ image_html = <<-EOS
+<div class="jekyll-linkpreview-image">
+ <a href="#{url}" target="_blank">
+ <img src="#{image}" />
+ </a>
+</div>
+EOS
+ end
+ html = <<-EOS
<div class="jekyll-linkpreview-wrapper">
<p><a href="#{url}" target="_blank">#{url}</a></p>
<div class="jekyll-linkpreview-wrapper-inner">
<div class="jekyll-linkpreview-content">
- <div class="jekyll-linkpreview-image">
- <a href="#{url}" target="_blank">
- <img src="#{image}" />
- </a>
- </div>
+#{image_html}
<div class="jekyll-linkpreview-body">
<h2 class="jekyll-linkpreview-title">
<a href="#{url}" target="_blank">#{title}</a>
</h2>
<div class="jekyll-linkpreview-description">#{description}</div>
</div>
</div>
<div class="jekyll-linkpreview-footer">
- <a href="//#{domain}" target="_blank">#{domain}</a>
+ <a href="#{domain}" target="_blank">#{domain}</a>
</div>
</div>
</div>
EOS
- html
- end
+ html
end
private
- def render_linkpreview_nog(context, url)
- template_path = get_linkpreview_nog_template()
- if File.exist?(template_path)
- template_file = File.read template_path
- site = context.registers[:site]
- template_file = (Liquid::Template.parse template_file).render site.site_payload.merge!({"link_url" => url})
- else
- html = <<-EOS
-<div class="jekyll-linkpreview-wrapper">
- <p><a href="#{url}" target="_blank">#{url}</a></p>
-</div>
- EOS
- html
- end
- end
-
- private
- def get_linkpreview_og_template()
- File.join Dir.pwd, "_includes", "linkpreview.html"
- end
-
- private
- def get_linkpreview_nog_template()
- File.join Dir.pwd, "_includes", "linkpreview_nog.html"
+ def gen_custom_template(template_path, hash)
+ template = File.read template_path
+ Liquid::Template.parse(template).render!(hash)
end
end
end
end