Skip to content

Instantly share code, notes, and snippets.

@cwgw cwgw/cwgw-mdx-images.js
Last active Jul 22, 2019

Embed
What would you like to do?
/**
* proof of concept replacement for gatsby-remark-images
* to be used with gatsby-plugin-mdx
*
* this is mostly a copy/paste/edit from gatsby-remark-images
*/
const visitWithParents = require(`unist-util-visit-parents`);
const getDefinitions = require(`mdast-util-definitions`);
const path = require(`path`);
const queryString = require(`query-string`);
const isRelativeUrl = require(`is-relative-url`);
const _ = require(`lodash`);
const { fluid } = require(`gatsby-plugin-sharp`);
const Promise = require(`bluebird`);
const slash = require(`slash`);
const DEFAULT_OPTIONS = {
base64: false,
maxWidth: 650,
tracedSVG: false,
withWebp: false,
wrapperStyle: ``,
};
const getImagePathInfo = uri => {
const { url, query } = queryString.parseUrl(uri);
return {
ext: path
.extname(url)
.split(`.`)
.pop(),
url,
query,
};
};
// If the image is relative (not hosted elsewhere)
// 1. Find the image file
// 2. Create the responsive images.
// 3. Replace image with JSX
module.exports = (
{ cache, files, getNode, markdownAST, markdownNode, pathPrefix, reporter },
pluginOptions
) => {
// Merge default options
const options = _.defaults(pluginOptions, { pathPrefix }, DEFAULT_OPTIONS);
// Get all the available definitions in the markdown tree
const definitions = getDefinitions(markdownAST);
// This will only work for markdown syntax image tags
let markdownImageNodes = [];
visitWithParents(
markdownAST,
[`image`, `imageReference`],
(node, ancestors) => {
markdownImageNodes.push({ node });
}
);
const getImageJSX = async function(src, resolve) {
// Check if this markdownNode has a File parent. This plugin
// won't work if the image isn't hosted locally.
const parentNode = getNode(markdownNode.parent);
let imagePath;
if (parentNode && parentNode.dir) {
imagePath = slash(path.join(parentNode.dir, getImagePathInfo(src).url));
} else {
return null;
}
const imageNode = _.find(files, file => {
if (file && file.absolutePath) {
return file.absolutePath === imagePath;
}
return null;
});
if (!imageNode || !imageNode.absolutePath) {
return resolve();
}
let fluidResult = await fluid({
file: imageNode,
args: options,
reporter,
cache,
});
if (!fluidResult) {
return null;
}
return `<GatsbyImage fluid={${JSON.stringify(fluidResult)}} />`;
};
return Promise.all(
// Simple because there is no nesting in markdown
markdownImageNodes.map(({ node }) => {
return new Promise(async (resolve) => {
let refNode;
if (!node.hasOwnProperty(`url`) && node.hasOwnProperty(`identifier`)) {
//consider as imageReference node
refNode = node;
node = definitions(refNode.identifier);
if (!node) {
// no definition found for image reference,
// so there's nothing for us to do.
return resolve();
}
}
const fileType = getImagePathInfo(node.url).ext;
// Ignore gifs as we can't process them,
// svgs as they are already responsive by definition
if (
isRelativeUrl(node.url) &&
fileType !== `gif` &&
fileType !== `svg`
) {
const imageValue = await getImageJSX(node.url, resolve);
if (imageValue) {
if (refNode) {
node = refNode;
}
node.type = `jsx`;
node.value = imageValue;
}
return resolve(node);
} else {
return resolve();
}
});
})
);
};
module.exports = {
plugins: [
`gatsby-plugin-sharp`,
{
resolve: 'gatsby-plugin-mdx',
options: {
gatsbyRemarkPlugins: [
{
resolve: require.resolve('./plugins/cwgw-mdx-images'),
}
],
}
},
...
import React from 'react';
import MDXRenderer from 'gatsby-plugin-mdx/mdx-renderer';
import { MDXProvider } from '@mdx-js/react';
import GatsbyImage from 'gatsby-image'
const Template = ({ data: { mdx } }) => {
return (
<MDXProvider components={{ GatsbyImage }} >
<MDXRenderer>{mdx.body}</MDXRenderer>
</MDXProvider>
);
}
export default Template;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.