Choose the image a srcset loads

Write codeMedium20 min

Your task

A responsive image hands the browser a srcset and lets it pick one file. Write the picker: given the srcset string, the width in CSS pixels of the slot the image fills (slot_width, at least 1) and the device pixel ratio (dpr, greater than 0), return the URL the browser should load.

Parsing. Split srcset on commas. Each piece is one candidate: after trimming whitespace (spaces, tabs, newlines) it is a URL, optionally followed by whitespace and descriptors. URLs never contain commas or whitespace. A candidate is skipped when it is empty or invalid. It is invalid when it has more than one descriptor, or its one descriptor is neither of these:

  • a width descriptor: one or more digits followed by a lowercase w, with a value greater than 0, such as 480w
  • a density descriptor: one or more digits, optionally a . and one or more digits, followed by a lowercase x, with a value greater than 0, such as 2x or 1.5x

Density. Every valid candidate gets an effective pixel density: a width descriptor gives width / slot_width, a density descriptor gives its number, and a candidate with no descriptor counts as 1x. Mixing width and density descriptors in one srcset is allowed. When two valid candidates have exactly the same density, only the one that appears first is kept.

Choice. Return the URL of the candidate with the smallest density that is at least dpr. When no candidate reaches dpr, return the URL of the candidate with the largest density. When there is no valid candidate at all, return an empty string.

Examples:

  • pick_srcset("hero-480.jpg 480w, hero-800.jpg 800w, hero-1200.jpg 1200w", 400, 2) returns "hero-800.jpg": the densities are 1.2, 2 and 3, and 2 is the smallest that reaches 2.
  • pick_srcset("logo.png, logo@2x.png 2x, logo@3x.png 3x", 120, 1.5) returns "logo@2x.png": the first candidate has no descriptor, so it is 1x.
  • pick_srcset("a.jpg 300w, b.jpg 600w", 400, 3) returns "b.jpg": nothing reaches 3, so the densest file wins.

Examples

pick_srcset(srcset: str, slot_width: int, dpr: float) -> str
Example 1
Inputpick_srcset("hero-480.jpg 480w, hero-800.jpg 800w, hero-1200.jpg 1200w", 400, 2)
Output"hero-800.jpg"
Example 2
Inputpick_srcset("logo.png, logo@2x.png 2x, logo@3x.png 3x", 120, 1.5)
Output"logo@2x.png"
Example 3
Inputpick_srcset("a.jpg 300w, b.jpg 600w", 400, 3)
Output"b.jpg"