Fetch the resized image

Instead of getting the full size image, the image can be fetched with a
width and height parameter so that only the resized data is
transferred. The url looks like this:

https://cdn-images-1.medium.com/fit/c/<width>/<height>/<media-id>

I picked a max image width of 800px. If the image width is more than
that, it scales the width down to 800, then applies that ratio to the
height. If it's smaller than that, the image is displayed as the
original.
This commit is contained in:
Edward Loveall 2021-07-05 14:54:58 -04:00
parent f7a72fd2b5
commit d863cc27a5
No known key found for this signature in database
GPG key ID: 789A4AE983AC8901
6 changed files with 61 additions and 14 deletions

View file

@ -180,14 +180,14 @@ describe ParagraphConverter do
"layout": "INSET_CENTER",
"metadata": {
"id": "image.png",
"originalWidth": 618,
"originalHeight": 682
"originalWidth": 1000,
"originalHeight": 600
}
}
JSON
expected = [
Figure.new(children: [
Image.new(src: "image.png"),
Image.new(src: "image.png", originalWidth: 1000, originalHeight: 600),
FigureCaption.new(children: [
Text.new("Image by "),
Anchor.new(href: "https://unsplash.com/@someuser", text: "someuser"),
@ -303,7 +303,7 @@ describe ParagraphConverter do
UnorderedList.new([ListItem.new([Text.new("text")] of Child)] of Child),
OrderedList.new([ListItem.new([Text.new("text")] of Child)] of Child),
Figure.new(children: [
Image.new(src: "1*miroimage.png"),
Image.new(src: "1*miroimage.png", originalWidth: 618, originalHeight: 682),
FigureCaption.new(children: [Text.new("text")] of Child),
] of Child),
IFrame.new(href: "https://example.com"),

View file

@ -90,7 +90,7 @@ describe PageContent do
it "renders a figure and figure caption" do
page = Page.new(nodes: [
Figure.new(children: [
Image.new(src: "image.png"),
Image.new(src: "image.png", originalWidth: 100, originalHeight: 100),
FigureCaption.new(children: [
Text.new("A caption")
] of Child),
@ -101,7 +101,7 @@ describe PageContent do
html.should eq stripped_html <<-HTML
<figure>
<img src="https://cdn-images-1.medium.com/image.png">
<img src="https://cdn-images-1.medium.com/fit/c/100/100/image.png" width="100" height="100">
<figcaption>A caption</figcaption>
</figure>
HTML
@ -134,13 +134,17 @@ describe PageContent do
it "renders an image" do
page = Page.new(nodes: [
Paragraph.new(children: [
Image.new(src: "image.png"),
Image.new(src: "image.png", originalWidth: 100, originalHeight: 100),
] of Child)
] of Child)
html = PageContent.new(page: page).render_to_string
html.should eq %(<p><img src="https://cdn-images-1.medium.com/image.png"></p>)
html.should eq stripped_html <<-HTML
<p>
<img src="https://cdn-images-1.medium.com/fit/c/100/100/image.png" width="100" height="100">
</p>
HTML
end
it "renders an iframe container" do

18
spec/models/nodes_spec.cr Normal file
View file

@ -0,0 +1,18 @@
require "../spec_helper"
module Nodes
describe Image do
it "adjusts the width and height proportionally" do
image = Image.new(src: "image.png", originalWidth: 1000, originalHeight: 603)
image.width.should eq("800")
image.height.should eq("482")
end
it "includes the adjusted width and height in the src" do
image = Image.new(src: "image.png", originalWidth: 1000, originalHeight: 603)
image.src.should eq("https://cdn-images-1.medium.com/fit/c/800/482/image.png")
end
end
end

View file

@ -77,7 +77,11 @@ class ParagraphConverter
if metadata = paragraph.metadata
caption_markup = MarkupConverter.convert(paragraph.text, paragraph.markups)
Figure.new(children: [
Image.new(src: metadata.id),
Image.new(
src: metadata.id,
originalWidth: metadata.originalWidth,
originalHeight: metadata.originalHeight
),
FigureCaption.new(children: caption_markup)
] of Child)
else

View file

@ -63,7 +63,7 @@ class PageContent < BaseComponent
end
def render_child(child : Image)
img src: child.src
img src: child.src, width: child.width, height: child.height
end
def render_child(node : ListItem)

View file

@ -79,18 +79,39 @@ module Nodes
end
class Image
IMAGE_HOST = "https://cdn-images-1.medium.com"
IMAGE_HOST = "https://cdn-images-1.medium.com/fit/c"
MAX_WIDTH = 800
getter src : String
getter originalHeight : Int32
getter originalWidth : Int32
def initialize(src : String)
@src = "#{IMAGE_HOST}/#{src}"
def initialize(@src : String, @originalWidth : Int32, @originalHeight : Int32)
end
def ==(other : Image)
other.src == src
end
def src
[IMAGE_HOST, width, height, @src].join("/")
end
def width
[originalWidth, MAX_WIDTH].min.to_s
end
def height
if originalWidth > MAX_WIDTH
(originalHeight * ratio).round.to_i.to_s
else
originalHeight.to_s
end
end
private def ratio
MAX_WIDTH / originalWidth
end
def empty?
false
end