2013-02-06 03:16:51 +08:00
|
|
|
# Post processing that we can do after a post has already been cooked. For
|
|
|
|
# example, inserting the onebox content, or image sizes.
|
|
|
|
|
|
|
|
require_dependency 'oneboxer'
|
|
|
|
|
|
|
|
class CookedPostProcessor
|
|
|
|
|
|
|
|
def initialize(post, opts={})
|
|
|
|
@dirty = false
|
|
|
|
@opts = opts
|
|
|
|
@post = post
|
2013-02-12 22:46:45 +08:00
|
|
|
@doc = Nokogiri::HTML(post.cooked)
|
2013-02-06 03:16:51 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def dirty?
|
|
|
|
@dirty
|
|
|
|
end
|
|
|
|
|
|
|
|
# Bake onebox content into the post
|
|
|
|
def post_process_oneboxes
|
|
|
|
args = {post_id: @post.id}
|
|
|
|
args[:invalidate_oneboxes] = true if @opts[:invalidate_oneboxes]
|
|
|
|
|
|
|
|
Oneboxer.each_onebox_link(@doc) do |url, element|
|
|
|
|
onebox = Oneboxer.onebox(url, args)
|
|
|
|
if onebox
|
|
|
|
element.swap onebox
|
|
|
|
@dirty = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# First let's consider the images
|
|
|
|
def post_process_images
|
|
|
|
images = @doc.search("img")
|
|
|
|
if images.present?
|
|
|
|
|
|
|
|
# Extract the first image from the first post and use it as the 'topic image'
|
|
|
|
if @post.post_number == 1
|
|
|
|
img = images.first
|
|
|
|
@post.topic.update_column :image_url, img['src'] if img['src'].present?
|
|
|
|
end
|
|
|
|
|
|
|
|
images.each do |img|
|
|
|
|
if img['src'].present?
|
|
|
|
|
|
|
|
# If we provided some image sizes, look those up first
|
|
|
|
if @opts[:image_sizes].present?
|
|
|
|
if dim = @opts[:image_sizes][img['src']]
|
|
|
|
w, h = ImageSizer.resize(dim['width'], dim['height'])
|
|
|
|
img.set_attribute 'width', w.to_s
|
|
|
|
img.set_attribute 'height', h.to_s
|
|
|
|
@dirty = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# If the image has no width or height, figure them out.
|
|
|
|
if img['width'].blank? or img['height'].blank?
|
|
|
|
dim = CookedPostProcessor.image_dimensions(img['src'])
|
|
|
|
if dim.present?
|
|
|
|
img.set_attribute 'width', dim[0].to_s
|
|
|
|
img.set_attribute 'height', dim[1].to_s
|
|
|
|
@dirty = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def post_process
|
|
|
|
return unless @doc.present?
|
|
|
|
post_process_images
|
|
|
|
post_process_oneboxes
|
|
|
|
end
|
|
|
|
|
|
|
|
def html
|
|
|
|
@doc.try(:to_html)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Retrieve the image dimensions for a url
|
|
|
|
def self.image_dimensions(url)
|
|
|
|
return nil unless SiteSetting.crawl_images?
|
|
|
|
uri = URI.parse(url)
|
|
|
|
return nil unless %w(http https).include?(uri.scheme)
|
|
|
|
w, h = FastImage.size(url)
|
|
|
|
|
|
|
|
ImageSizer.resize(w, h)
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|