Module: Presenters::ImageTag
- Extended by:
- ActiveSupport::Concern
- Included in:
- Crm::ImagePresenter, Www::ImagePresenter
- Defined in:
- app/concerns/presenters/image_tag.rb
Constant Summary collapse
- BLANK_PNG_PIXEL_IMG_SRC =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII='- VIEWPORT_WIDTHS =
[3840, 2048, 1920, 1600, 1200, 1080, 915, 750, 500, 320, 160].freeze
Instance Attribute Summary collapse
-
#href ⇒ Object
readonly
Returns the value of attribute href.
-
#imagesizes ⇒ Object
readonly
Returns the value of attribute imagesizes.
-
#imagesrcset ⇒ Object
readonly
Returns the value of attribute imagesrcset.
Instance Method Summary collapse
- #image_tag(options = {}) ⇒ Object
- #image_tag_html(options) ⇒ Object
-
#to_schema_dot_org ⇒ Object
Lazy loading: Uses browser's native loading="lazy" by default - true (default) - Native browser lazy loading (loads when near viewport) - false - No lazy loading, loads immediately (use for LCP/above-fold images).
Instance Attribute Details
#href ⇒ Object (readonly)
Returns the value of attribute href.
6 7 8 |
# File 'app/concerns/presenters/image_tag.rb', line 6 def href @href end |
#imagesizes ⇒ Object (readonly)
Returns the value of attribute imagesizes.
6 7 8 |
# File 'app/concerns/presenters/image_tag.rb', line 6 def imagesizes @imagesizes end |
#imagesrcset ⇒ Object (readonly)
Returns the value of attribute imagesrcset.
6 7 8 |
# File 'app/concerns/presenters/image_tag.rb', line 6 def imagesrcset @imagesrcset end |
Instance Method Details
#image_tag(options = {}) ⇒ Object
33 34 35 36 37 |
# File 'app/concerns/presenters/image_tag.rb', line 33 def image_tag( = {}) .delete(:request_format) .delete(:amp) image_tag_html() end |
#image_tag_html(options) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'app/concerns/presenters/image_tag.rb', line 39 def image_tag_html() = .dup # Extract tag specific param here # img_options[:relative] = false if img_options[:relative].nil? css_class = .delete(:class) style = .delete(:style) itemprop = .delete(:itemprop) fetchpriority = .delete(:fetchpriority) custom_data = .delete(:data) lazyload = .delete(:lazyload) lazyload = true if lazyload.nil? alt = .delete(:alt) || image.try(:seo_title) || image.title title = .delete(:title) || image.title.presence || alt include_srcset = .delete(:include_srcset) # crop_aspect_ratio: height/width float (e.g. 600.0/1920 for a hero banner). # Applies a proportional height to every srcset entry without specifying a fixed # width, so the srcset covers all viewport sizes including Retina (3840w etc.). crop_aspect_ratio = .delete(:crop_aspect_ratio) @imagesizes = sizes = .delete(:sizes) ratio = nil include_srcset = if sizes.present? true elsif include_srcset.nil? true else include_srcset.to_b end = .delete(:viewport_widths) || VIEWPORT_WIDTHS.dup [:encode_format] ||= @options&.dig(:img_options, :encode_format) = .slice(*Image::VALID_IMAGE_URL_OPTIONS) # extracted requested width if any to reduce our srcset requested_width = [:width] requested_width ||= [:size]&.scan(/\A(\d+)x?/)&.flatten&.first requested_width = requested_width.to_i if requested_width requested_height = [:height] requested_height ||= [:size]&.scan(/\A(\d+)x(\d+)?/)&.flatten&.last requested_height = requested_height.to_i if requested_height ratio = requested_height.to_f / requested_width.to_f if requested_width && requested_height && requested_width > 0 if requested_width # Include the requested width into the srcset if requested_width < 150 # don't bother with a srcset on an image this small include_srcset = false else << requested_width = .map(&:presence).compact.map(&:to_i).uniq.sort.reverse end end = .compact url = image.image_url(**) srcsets = [] if include_srcset # Based on https://medium.com/hceverything/applying-srcset-choosing-the-right-sizes-for-responsive-images-at-different-breakpoints-a0433450a4a3 = .reject { |w| requested_width && w > requested_width } # The width returned are for a full width viewport. Remember to pair with a sizes attribute to give the # browser some guidance on the final rendering of the image or use the lazy option. srcsets = .map do |width| # Create a new transform set with the viewport width and passing key transformations to preserve = .slice(:relative, :encode_format, :crop_x, :crop_y, :crop_w, :crop_last, :crop_mode, :crop_h, :borderx, :bordery, :rotate, :relative, :hostname, :cache, :webp, :optimize, :thumbnail, :background, :focus) = { width: width, ** } # Apply explicit ratio (from width+height args) or crop_aspect_ratio for a # proportional height crop at every srcset breakpoint (e.g. hero banners). effective_ratio = ratio || crop_aspect_ratio [:height] = (width * effective_ratio).round if effective_ratio = .compact "#{image.image_url(**)} #{width}w" end end @imagesrcset = strset_str = srcsets.join(',').presence params = { alt: alt, title: title, class: css_class, itemprop: itemprop, style: style } css_class_ary = css_class&.split(' ') || [] # Set image source and srcset params[:src] = url if strset_str.present? params[:srcset] = strset_str params[:sizes] = sizes if sizes.present? end # Native browser lazy loading (default: true) # Use lazyload: false for above-fold/LCP images params[:loading] = 'lazy' if lazyload css_class_ary = css_class_ary.uniq.compact if css_class_ary.present? params[:class] = css_class_ary.join(' ') else params.delete(:class) end params[:width] ||= [:tag_width] if [:tag_width] params[:height] ||= [:tag_height] if [:tag_height] if params[:width].nil? && params[:height].nil? if requested_width && requested_height # Both dimensions explicitly requested (e.g., size: '150x150') params[:width] = requested_width params[:height] = requested_height elsif requested_width && image.aspect_ratio # Only width requested - calculate height from aspect ratio params[:width] = requested_width params[:height] = (requested_width.to_f / image.aspect_ratio).round elsif ![:no_native_size_in_tag].to_b && && image.aspect_ratio params[:width] = [, 1920].min params[:height] = (params[:width].to_f / image.aspect_ratio).round end end params[:data] = (custom_data || {}).merge(iid: image.id) @href = params[:src] # Add fetchpriority for LCP images (only makes sense without lazy loading) params[:fetchpriority] = fetchpriority if fetchpriority.present? && !lazyload h.tag(:img, **params) end |
#to_schema_dot_org ⇒ Object
Lazy loading: Uses browser's native loading="lazy" by default
- true (default) - Native browser lazy loading (loads when near viewport)
- false - No lazy loading, loads immediately (use for LCP/above-fold images)
Native lazy loading has 95%+ browser support and requires no JavaScript.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'app/concerns/presenters/image_tag.rb', line 18 def to_schema_dot_org url = image.image_url width = image. height = image. content_type = image.determine_mime_type SchemaDotOrg::ImageObject.new( url: url, width: width, height: height, encodingFormat: content_type ) end |