66 lines
1.8 KiB
JavaScript
66 lines
1.8 KiB
JavaScript
|
import { without } from 'lodash';
|
||
|
import u from 'unist-builder';
|
||
|
import mdastDefinitions from 'mdast-util-definitions';
|
||
|
|
||
|
/**
|
||
|
* Raw markdown may contain image references or link references. Because there
|
||
|
* is no way to maintain these references within the Slate AST, we convert image
|
||
|
* and link references to standard images and links by putting their url's
|
||
|
* inline. The definitions are then removed from the document.
|
||
|
*
|
||
|
* For example, the following markdown:
|
||
|
*
|
||
|
* ```
|
||
|
* ![alpha][bravo]
|
||
|
*
|
||
|
* [bravo]: http://example.com/example.jpg
|
||
|
* ```
|
||
|
*
|
||
|
* Yields:
|
||
|
*
|
||
|
* ```
|
||
|
* ![alpha][http://example.com/example.jpg]
|
||
|
* ```
|
||
|
*
|
||
|
*/
|
||
|
export default function remarkSquashReferences() {
|
||
|
return getTransform;
|
||
|
|
||
|
function getTransform(node) {
|
||
|
const getDefinition = mdastDefinitions(node);
|
||
|
return transform.call(null, getDefinition, node);
|
||
|
}
|
||
|
|
||
|
function transform(getDefinition, node) {
|
||
|
|
||
|
/**
|
||
|
* Bind the `getDefinition` function to `transform` and recursively map all
|
||
|
* nodes.
|
||
|
*/
|
||
|
const boundTransform = transform.bind(null, getDefinition);
|
||
|
const children = node.children ? node.children.map(boundTransform) : node.children;
|
||
|
|
||
|
/**
|
||
|
* Combine reference and definition nodes into standard image and link
|
||
|
* nodes.
|
||
|
*/
|
||
|
if (['imageReference', 'linkReference'].includes(node.type)) {
|
||
|
const type = node.type === 'imageReference' ? 'image' : 'link';
|
||
|
const { title, url } = getDefinition(node.identifier) || {};
|
||
|
return u(type, { title, url, alt: node.alt }, children);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Remove definition nodes and filter the resulting null values from the
|
||
|
* filtered children array.
|
||
|
*/
|
||
|
if(node.type === 'definition') {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
const filteredChildren = without(children, null);
|
||
|
|
||
|
return { ...node, children: filteredChildren };
|
||
|
}
|
||
|
}
|