gatsby-plugin-amp-alternative
Version:
A gatsby plugin for scaffolding AMP pages
194 lines (171 loc) • 6.58 kB
JavaScript
;
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard");
exports.__esModule = true;
exports.replaceRenderer = void 0;
var _react = _interopRequireWildcard(require("react"));
var _server = require("react-dom/server");
var _jsxFileName = "/Users/einomi/projects/opensource/gatsby-plugin-amp-alternative/src/replaceRenderer.js";
const JSDOM = eval('require("jsdom")').JSDOM;
const replaceRenderer = ({
bodyComponent,
replaceBodyHTMLString,
setHeadComponents,
pathname
}, {
pathIdentifier = "/amp/"
}) => {
const defaults = {
image: {
width: 640,
height: 475,
layout: "responsive"
},
twitter: {
width: "390",
height: "330",
layout: "responsive"
},
iframe: {
width: 640,
height: 475,
layout: "responsive"
}
};
const headComponents = [];
const isAmp = pathname && pathname.indexOf(pathIdentifier) > -1;
if (isAmp) {
const bodyHTML = (0, _server.renderToString)(bodyComponent);
const dom = new JSDOM(bodyHTML);
const document = dom.window.document; // convert images to amp-img or amp-anim
const images = [].slice.call(document.getElementsByTagName("img"));
images.forEach(image => {
let ampImage;
if (image.src && image.src.indexOf(".gif") > -1) {
ampImage = document.createElement("amp-anim");
headComponents.push({
name: "amp-anim",
version: "0.1"
});
} else {
ampImage = document.createElement("amp-img");
}
const attributes = Object.keys(image.attributes);
const includedAttributes = attributes.map(key => {
const attribute = image.attributes[key];
ampImage.setAttribute(attribute.name, attribute.value);
return attribute.name;
});
Object.keys(defaults.image).forEach(key => {
if (includedAttributes && includedAttributes.indexOf(key) === -1) {
ampImage.setAttribute(key, defaults.image[key]);
}
});
image.parentNode.replaceChild(ampImage, image);
}); // convert twitter posts to amp-twitter
const twitterPosts = [].slice.call(document.getElementsByClassName("twitter-tweet"));
twitterPosts.forEach(post => {
headComponents.push({
name: "amp-twitter",
version: "0.1"
});
const ampTwitter = document.createElement("amp-twitter");
const attributes = Object.keys(post.attributes);
const includedAttributes = attributes.map(key => {
const attribute = post.attributes[key];
ampTwitter.setAttribute(attribute.name, attribute.value);
return attribute.name;
});
Object.keys(defaults.twitter).forEach(key => {
if (includedAttributes && includedAttributes.indexOf(key) === -1) {
ampTwitter.setAttribute(key, defaults.twitter[key]);
}
}); // grab the last link in the tweet for the twee id
const links = [].slice.call(post.getElementsByTagName("a"));
const link = links[links.length - 1];
const hrefArr = link.href.split("/");
const id = hrefArr[hrefArr.length - 1].split("?")[0];
ampTwitter.setAttribute("data-tweetid", id); // clone the original blockquote for a placeholder
const _post = post.cloneNode(true);
_post.setAttribute("placeholder", "");
ampTwitter.appendChild(_post);
post.parentNode.replaceChild(ampTwitter, post);
}); // convert iframes to amp-iframe or amp-youtube
const iframes = [].slice.call(document.getElementsByTagName("iframe"));
iframes.forEach(iframe => {
let ampIframe;
let attributes;
if (iframe.src && iframe.src.indexOf("youtube.com/embed/") > -1) {
headComponents.push({
name: "amp-youtube",
version: "0.1"
});
ampIframe = document.createElement("amp-youtube");
const src = iframe.src.split("/");
const id = src[src.length - 1].split("?")[0];
ampIframe.setAttribute("data-videoid", id);
const placeholder = document.createElement("amp-img");
placeholder.setAttribute("src", `https://i.ytimg.com/vi/${id}/mqdefault.jpg`);
placeholder.setAttribute("placeholder", "");
placeholder.setAttribute("layout", "fill");
ampIframe.appendChild(placeholder);
const forbidden = ["allow", "allowfullscreen", "frameborder", "src"];
attributes = Object.keys(iframe.attributes).filter(key => {
const attribute = iframe.attributes[key];
return !forbidden.includes(attribute.name);
});
} else {
headComponents.push({
name: "amp-iframe",
version: "0.1"
});
ampIframe = document.createElement("amp-iframe");
attributes = Object.keys(iframe.attributes);
}
const includedAttributes = attributes.map(key => {
const attribute = iframe.attributes[key];
ampIframe.setAttribute(attribute.name, attribute.value);
return attribute.name;
});
Object.keys(defaults.iframe).forEach(key => {
if (includedAttributes && includedAttributes.indexOf(key) === -1) {
ampIframe.setAttribute(key, defaults.iframe[key]);
}
});
iframe.parentNode.replaceChild(ampIframe, iframe);
});
const styleTags = [].slice.call(document.getElementsByTagName("style"));
styleTags.forEach(styleTag => {
if (styleTag.getAttribute('data-emotion-css') != null) {
styleTag.setAttribute('amp-custom', "");
}
});
setHeadComponents(Array.from(new Set(headComponents)).map((component, i) => /*#__PURE__*/_react.default.createElement(_react.Fragment, {
key: `head-components-${i}`,
__self: void 0,
__source: {
fileName: _jsxFileName,
lineNumber: 139,
columnNumber: 9
}
}, /*#__PURE__*/_react.default.createElement("script", {
async: true,
"custom-element": component.name,
src: `https://cdn.ampproject.org/v0/${component.name}-${component.version}.js`,
__self: void 0,
__source: {
fileName: _jsxFileName,
lineNumber: 140,
columnNumber: 11
}
}))));
function getNonDivParentElement(element) {
const childElement = element.children[0];
if (childElement.tagName.toLowerCase() === 'div') {
return getNonDivParentElement(childElement);
}
return childElement;
}
replaceBodyHTMLString(getNonDivParentElement(document.body).outerHTML);
}
};
exports.replaceRenderer = replaceRenderer;