From d863cc27a5bbe9368233fa95f7bc825b743a9881 Mon Sep 17 00:00:00 2001 From: Edward Loveall Date: Mon, 5 Jul 2021 14:54:58 -0400 Subject: [PATCH] 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/// 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. --- spec/classes/paragraph_converter_spec.cr | 8 +++---- spec/components/page_content_spec.cr | 12 ++++++---- spec/models/nodes_spec.cr | 18 +++++++++++++++ src/classes/paragraph_converter.cr | 6 ++++- src/components/page_content.cr | 2 +- src/models/nodes.cr | 29 ++++++++++++++++++++---- 6 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 spec/models/nodes_spec.cr diff --git a/spec/classes/paragraph_converter_spec.cr b/spec/classes/paragraph_converter_spec.cr index fcf37b6..d53fd18 100644 --- a/spec/classes/paragraph_converter_spec.cr +++ b/spec/classes/paragraph_converter_spec.cr @@ -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"), diff --git a/spec/components/page_content_spec.cr b/spec/components/page_content_spec.cr index a3c1f2b..983b263 100644 --- a/spec/components/page_content_spec.cr +++ b/spec/components/page_content_spec.cr @@ -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
- +
A caption
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 %(

) + html.should eq stripped_html <<-HTML +

+ +

+ HTML end it "renders an iframe container" do diff --git a/spec/models/nodes_spec.cr b/spec/models/nodes_spec.cr new file mode 100644 index 0000000..dc46144 --- /dev/null +++ b/spec/models/nodes_spec.cr @@ -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 diff --git a/src/classes/paragraph_converter.cr b/src/classes/paragraph_converter.cr index 071a742..278702c 100644 --- a/src/classes/paragraph_converter.cr +++ b/src/classes/paragraph_converter.cr @@ -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 diff --git a/src/components/page_content.cr b/src/components/page_content.cr index 1a50d29..a4213a1 100644 --- a/src/components/page_content.cr +++ b/src/components/page_content.cr @@ -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) diff --git a/src/models/nodes.cr b/src/models/nodes.cr index cb1b873..da55d66 100644 --- a/src/models/nodes.cr +++ b/src/models/nodes.cr @@ -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