-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(gatsby-remark-responsive-iframe): iframe ratio is NaN if d… (#18328)
* simplify width/height value check, ratio calculation doesnt return NaN * update test snapshot * modernize the code * update test snapshot (remove extra colon, extra space) * convert: add comments, trim off white space
- Loading branch information
1 parent
08dc747
commit 257f5d6
Showing
4 changed files
with
78 additions
and
98 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
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 |
---|---|---|
@@ -1,85 +1,85 @@ | ||
const visit = require(`unist-util-visit`) | ||
const cheerio = require(`cheerio`) | ||
const Promise = require(`bluebird`) | ||
const { oneLine } = require(`common-tags`) | ||
const _ = require(`lodash`) | ||
|
||
const isPixelNumber = n => /\d+px$/.test(n) | ||
|
||
const isUnitlessNumber = n => { | ||
const nToNum = _.toNumber(n) | ||
return _.isFinite(nToNum) | ||
} | ||
const needsSemicolon = str => !str.endsWith(`;`) | ||
|
||
const isUnitlessOrPixelNumber = n => | ||
n && (isUnitlessNumber(n) || isPixelNumber(n)) | ||
/** | ||
* Convert anything to number, except for % value. | ||
* We don't have to check for other values (em, vw, etc.) | ||
* because the browsers will treat them as px anyway. | ||
* @param {*} n something to be converted to number | ||
* @returns {number} | ||
*/ | ||
const convert = n => | ||
typeof n === `string` && n.trim().endsWith(`%`) ? NaN : parseInt(n, 10) | ||
|
||
const needsSemicolon = str => !str.endsWith(`;`) | ||
/** | ||
* Check whether all passed in arguments are valid number or not | ||
* @param {...number} args dimension to check | ||
* @returns {boolean} | ||
*/ | ||
const isValidDimensions = (...args) => args.every(n => _.isFinite(n)) | ||
|
||
// Aspect ratio can only be determined if both width and height are unitless or | ||
// pixel values. Any other values mean the responsive wrapper is not applied. | ||
const acceptedDimensions = (width, height) => | ||
isUnitlessOrPixelNumber(width) && isUnitlessOrPixelNumber(height) | ||
module.exports = async ({ markdownAST }, pluginOptions = {}) => { | ||
const defaults = { | ||
wrapperStyle: ``, | ||
} | ||
const options = _.defaults(pluginOptions, defaults) | ||
visit(markdownAST, [`html`, `jsx`], node => { | ||
const $ = cheerio.load(node.value) | ||
const iframe = $(`iframe, object`) | ||
if (iframe.length === 0) { | ||
return | ||
} | ||
|
||
module.exports = ({ markdownAST }, pluginOptions = {}) => | ||
new Promise(resolve => { | ||
const defaults = { | ||
wrapperStyle: ``, | ||
const width = convert(iframe.attr(`width`)) | ||
const height = convert(iframe.attr(`height`)) | ||
if (!isValidDimensions(width, height)) { | ||
return | ||
} | ||
const options = _.defaults(pluginOptions, defaults) | ||
visit(markdownAST, [`html`, `jsx`], node => { | ||
const $ = cheerio.load(node.value) | ||
const iframe = $(`iframe, object`) | ||
if (iframe.length) { | ||
const width = iframe.attr(`width`) | ||
const height = iframe.attr(`height`) | ||
|
||
if (acceptedDimensions(width, height)) { | ||
const existingStyle = $(`iframe`).attr(`style`) // Other plugins might set border: 0 | ||
// so we make sure that we maintain those existing styles. If other styles like height or | ||
// width are already defined they will be overridden anyway. | ||
let fullStyle = $(`iframe`).attr(`style`) || `` // Other plugins might set border: 0 | ||
// so we make sure that we maintain those existing styles. If other styles like height or | ||
// width are already defined they will be overridden anyway. | ||
|
||
let fullStyle = `` | ||
if (existingStyle && needsSemicolon(existingStyle)) { | ||
fullStyle = `${existingStyle};` | ||
} else if (existingStyle) { | ||
fullStyle = existingStyle | ||
} | ||
if (fullStyle.length > 0 && needsSemicolon(fullStyle)) { | ||
fullStyle = `${fullStyle};` | ||
} | ||
|
||
$(`iframe, object`).attr( | ||
`style`, | ||
`${fullStyle} | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
` | ||
) | ||
$(`iframe, object`) | ||
.attr(`width`, null) | ||
.attr(`height`, null) | ||
const newIframe = $(`body`).html() // fix for cheerio v1 | ||
$(`iframe, object`) | ||
.attr( | ||
`style`, | ||
`${fullStyle} | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
` | ||
) | ||
.attr(`width`, null) | ||
.attr(`height`, null) | ||
|
||
// TODO add youtube preview image as background-image. | ||
const newIframe = $(`body`).html() // fix for cheerio v1 | ||
|
||
const rawHTML = oneLine` | ||
<div | ||
class="gatsby-resp-iframe-wrapper" | ||
style="padding-bottom: ${(height / width) * | ||
100}%; position: relative; height: 0; overflow: hidden;${ | ||
options.wrapperStyle | ||
}" | ||
> | ||
${newIframe} | ||
</div> | ||
` | ||
// TODO add youtube preview image as background-image. | ||
|
||
node.type = `html` | ||
node.value = rawHTML | ||
} | ||
} | ||
}) | ||
const rawHTML = oneLine` | ||
<div | ||
class="gatsby-resp-iframe-wrapper" | ||
style="padding-bottom: ${(height / width) * | ||
100}%; position: relative; height: 0; overflow: hidden; | ||
${options.wrapperStyle}" | ||
> | ||
${newIframe} | ||
</div> | ||
` | ||
|
||
return resolve(markdownAST) | ||
node.type = `html` | ||
node.value = rawHTML | ||
}) | ||
|
||
return markdownAST | ||
} |
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