UNPKG

gatsby-remark-embedder

Version:

Gatsby Remark plugin to embed well known services by their URL.

82 lines (78 loc) 2.81 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _parse = _interopRequireDefault(require("parse5")); var _hastUtilFromParse = _interopRequireDefault(require("hast-util-from-parse5")); var _unistUtilVisit = _interopRequireDefault(require("unist-util-visit")); var _transformers = require("./transformers"); // results in an AST node of type "root" with a single "children" node of type "element" // so we return the first (and only) child "element" node const htmlToHast = string => (0, _hastUtilFromParse.default)(_parse.default.parseFragment(string)).children[0]; const getUrlString = url => { const urlString = url.startsWith('http') ? url : `https://${url}`; try { return new URL(urlString).toString(); } catch (error) { return null; } }; module.exports = async ({ cache, markdownAST }, { customTransformers = [], services = {} } = {}) => { const transformers = [..._transformers.defaultTransformers, ...customTransformers]; const transformations = []; (0, _unistUtilVisit.default)(markdownAST, 'paragraph', paragraphNode => { if (paragraphNode.children.length !== 1) { return; } const [node] = paragraphNode.children; const isText = node.type === 'text'; // it's a valid link if there's no title, and the value is the same as the URL const isValidLink = node.type === 'link' && node.title === null && node.children.length === 1 && node.children[0].value === node.url; if (!isText && !isValidLink) { return; } const { url, value = url } = node; const urlString = getUrlString(value); if (!urlString) { return; } transformers.filter(({ shouldTransform }) => shouldTransform(urlString)).forEach(({ getHTML, name = '' }) => { transformations.push(async () => { try { let html = await cache.get(urlString); if (!html) { html = await getHTML(urlString, services[name] || {}); await cache.set(urlString, html); } // if nothing's returned from getHTML, then no modifications are needed if (!html) return; // convert the HTML string into an AST const htmlElement = htmlToHast(html); // set the paragraphNode.data with the necessary properties paragraphNode.data = { hName: htmlElement.tagName, hProperties: htmlElement.properties, hChildren: htmlElement.children }; } catch (error) { error.message = `The following error appeared while processing '${urlString}':\n\n${error.message}`; throw error; } }); }); }); await Promise.all(transformations.map(t => t())); return markdownAST; };