-
Notifications
You must be signed in to change notification settings - Fork 451
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Transform relative URLs in srcset attributes to absolute URLs (#190
- Loading branch information
Showing
2 changed files
with
194 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,4 +56,169 @@ describe('makeLinksAbsolute($)', () => { | |
|
||
assert.equal(result, '<div><img src="http://example.com/#foo"></div>'); | ||
}); | ||
|
||
describe('makes relative srcsets absolute', () => { | ||
/** | ||
* The spec for srcset requires a space character following the comma separating character | ||
* when a candidate that doesn't contain a descriptor needs to be followed by another candidate, | ||
* otherwise, that candidate would be treated as part of the succeeding candidate filename. | ||
* This requirement allows for URLs that contain comma character but no un-encoded spaces. | ||
* | ||
* srcset candidates that all contain descriptors, can safely be separated by commas | ||
* without the need for a space character. | ||
*/ | ||
it('handles invalid srcsets as per their invalid implementation', () => { | ||
/** | ||
* The following srcset values would be interpreted (by browsers, and pasrsed similarly) | ||
* as follows: | ||
* (1) the first source tag - one candidate: | ||
* assets/images/rhythm/076.jpg,assets/images/rhythm/[email protected] 2x | ||
* (2) the second source tag - two candidates: | ||
* assets/images/rhythm/[email protected] 2x | ||
* assets/images/rhythm/120.jpg,assets/images/rhythm/[email protected] 3x | ||
* (3) the third source tag - two candidates: | ||
* assets/images/rhythm/240.jpg,assets/images/rhythm/[email protected] 2x, | ||
* assets/images/rhythm/[email protected] 3x | ||
*/ | ||
const html = `<div> | ||
<picture> | ||
<source srcset="assets/images/rhythm/076.jpg,assets/images/rhythm/[email protected] 2x" media="(max-width: 450px)"> | ||
<source srcset="assets/images/rhythm/[email protected] 2x, assets/images/rhythm/120.jpg,assets/images/rhythm/[email protected] 3x" media="(max-width: 900px)"> | ||
<source srcset="assets/images/rhythm/240.jpg,assets/images/rhythm/[email protected] 2x,assets/images/rhythm/[email protected] 3x" media="(min-width: 901px)"> | ||
<img src="assets/images/rhythm/120.jpg" alt="Vertical and horizontal rhythm"> | ||
</picture> | ||
</div>`; | ||
const $ = cheerio.load(html); | ||
const $content = $('*').first(); | ||
|
||
const result = $.html( | ||
makeLinksAbsolute($content, $, 'http://example.com') | ||
); | ||
|
||
assert.equal( | ||
result, | ||
`<div> | ||
<picture> | ||
<source srcset="http://example.com/assets/images/rhythm/076.jpg,assets/images/rhythm/[email protected] 2x" media="(max-width: 450px)"> | ||
<source srcset="http://example.com/assets/images/rhythm/[email protected] 2x, http://example.com/assets/images/rhythm/120.jpg,assets/images/rhythm/[email protected] 3x" media="(max-width: 900px)"> | ||
<source srcset="http://example.com/assets/images/rhythm/240.jpg,assets/images/rhythm/[email protected] 2x, http://example.com/assets/images/rhythm/[email protected] 3x" media="(min-width: 901px)"> | ||
<img src="http://example.com/assets/images/rhythm/120.jpg" alt="Vertical and horizontal rhythm"> | ||
</picture> | ||
</div>` | ||
); | ||
}); | ||
|
||
it('handles comma separated (with whitespace) srcset files with device-pixel-ratio descriptors', () => { | ||
const html = `<div> | ||
<picture> | ||
<source srcset="assets/images/rhythm/076.jpg 2x, assets/images/rhythm/076.jpg" media="(max-width: 450px)"> | ||
<source srcset="assets/images/rhythm/[email protected] 2x, assets/images/rhythm/076.jpg"> | ||
<img src="http://example.com/assets/images/rhythm/076.jpg" alt="Vertical and horizontal rhythm"> | ||
</picture> | ||
</div>`; | ||
const $ = cheerio.load(html); | ||
const $content = $('*').first(); | ||
|
||
const result = $.html( | ||
makeLinksAbsolute($content, $, 'http://example.com') | ||
); | ||
|
||
assert.equal( | ||
result, | ||
`<div> | ||
<picture> | ||
<source srcset="http://example.com/assets/images/rhythm/076.jpg 2x, http://example.com/assets/images/rhythm/076.jpg" media="(max-width: 450px)"> | ||
<source srcset="http://example.com/assets/images/rhythm/[email protected] 2x, http://example.com/assets/images/rhythm/076.jpg"> | ||
<img src="http://example.com/assets/images/rhythm/076.jpg" alt="Vertical and horizontal rhythm"> | ||
</picture> | ||
</div>` | ||
); | ||
}); | ||
|
||
it('handles comma separated (without whitespace) srcset files with device-pixel-ratio descriptors', () => { | ||
const html = `<div> | ||
<picture> | ||
<source srcset="assets/images/rhythm/076.jpg 2x,assets/images/rhythm/076.jpg" media="(max-width: 450px)"> | ||
<source srcset="assets/images/rhythm/[email protected] 2x,assets/images/rhythm/076.jpg"> | ||
<img src="http://example.com/assets/images/rhythm/076.jpg" alt="Vertical and horizontal rhythm"> | ||
</picture> | ||
</div>`; | ||
const $ = cheerio.load(html); | ||
const $content = $('*').first(); | ||
|
||
const result = $.html( | ||
makeLinksAbsolute($content, $, 'http://example.com') | ||
); | ||
|
||
assert.equal( | ||
result, | ||
`<div> | ||
<picture> | ||
<source srcset="http://example.com/assets/images/rhythm/076.jpg 2x, http://example.com/assets/images/rhythm/076.jpg" media="(max-width: 450px)"> | ||
<source srcset="http://example.com/assets/images/rhythm/[email protected] 2x, http://example.com/assets/images/rhythm/076.jpg"> | ||
<img src="http://example.com/assets/images/rhythm/076.jpg" alt="Vertical and horizontal rhythm"> | ||
</picture> | ||
</div>` | ||
); | ||
}); | ||
|
||
it('handles comma separated (with whitespace) srcset files with width descriptors', () => { | ||
const html = `<div> | ||
<img srcset="elva-fairy-320w.jpg 320w, elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w" sizes="(max-width: 320px) 280px, (max-width: 480px) 440px, 800px" src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy"> | ||
</div>`; | ||
const $ = cheerio.load(html); | ||
const $content = $('*').first(); | ||
|
||
const result = $.html( | ||
makeLinksAbsolute($content, $, 'http://example.com') | ||
); | ||
|
||
assert.equal( | ||
result, | ||
`<div> | ||
<img srcset="http://example.com/elva-fairy-320w.jpg 320w, http://example.com/elva-fairy-480w.jpg 480w, http://example.com/elva-fairy-800w.jpg 800w" sizes="(max-width: 320px) 280px, (max-width: 480px) 440px, 800px" src="http://example.com/elva-fairy-800w.jpg" alt="Elva dressed as a fairy"> | ||
</div>` | ||
); | ||
}); | ||
|
||
it('handles multiline comma separated srcset files with width descriptors', () => { | ||
const html = `<div> | ||
<img srcset="elva-fairy-320w.jpg 320w, | ||
elva-fairy-480w.jpg 480w, | ||
elva-fairy-800w.jpg 800w" sizes="(max-width: 320px) 280px, (max-width: 480px) 440px, 800px" src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy"> | ||
</div>`; | ||
const $ = cheerio.load(html); | ||
const $content = $('*').first(); | ||
|
||
const result = $.html( | ||
makeLinksAbsolute($content, $, 'http://example.com') | ||
); | ||
|
||
assert.equal( | ||
result, | ||
`<div> | ||
<img srcset="http://example.com/elva-fairy-320w.jpg 320w, http://example.com/elva-fairy-480w.jpg 480w, http://example.com/elva-fairy-800w.jpg 800w" sizes="(max-width: 320px) 280px, (max-width: 480px) 440px, 800px" src="http://example.com/elva-fairy-800w.jpg" alt="Elva dressed as a fairy"> | ||
</div>` | ||
); | ||
}); | ||
|
||
it('handles URLs that contain a comma', () => { | ||
const html = `<div> | ||
<picture><source media="(min-width: 768px)" srcset="cartoons/5bbfca021e40b62d6cc418ea/master/w_280,c_limit/181022_a22232.jpg, cartoons/5bbfca021e40b62d6cc418ea/master/w_560,c_limit/181022_a22232.jpg 2x"/><source srcset="cartoons/5bbfca021e40b62d6cc418ea/master/w_727,c_limit/181022_a22232.jpg, cartoons/5bbfca021e40b62d6cc418ea/master/w_1454,c_limit/181022_a22232.jpg 2x"/><img src="cartoons/5bbfca021e40b62d6cc418ea/master/w_727,c_limit/181022_a22232.jpg" /></picture> | ||
</div>`; | ||
const $ = cheerio.load(html); | ||
const $content = $('*').first(); | ||
|
||
const result = $.html( | ||
makeLinksAbsolute($content, $, 'https://media.newyorker.com/') | ||
); | ||
|
||
assert.equal( | ||
result, | ||
`<div> | ||
<picture><source media="(min-width: 768px)" srcset="https://media.newyorker.com/cartoons/5bbfca021e40b62d6cc418ea/master/w_280,c_limit/181022_a22232.jpg, https://media.newyorker.com/cartoons/5bbfca021e40b62d6cc418ea/master/w_560,c_limit/181022_a22232.jpg 2x"><source srcset="https://media.newyorker.com/cartoons/5bbfca021e40b62d6cc418ea/master/w_727,c_limit/181022_a22232.jpg, https://media.newyorker.com/cartoons/5bbfca021e40b62d6cc418ea/master/w_1454,c_limit/181022_a22232.jpg 2x"><img src="https://media.newyorker.com/cartoons/5bbfca021e40b62d6cc418ea/master/w_727,c_limit/181022_a22232.jpg"></picture> | ||
</div>` | ||
); | ||
}); | ||
}); | ||
}); |