diff --git a/src/components/Widgets/Markdown/MarkdownControl/VisualEditor/components.js b/src/components/Widgets/Markdown/MarkdownControl/VisualEditor/components.js
index 0c213884..21c6421e 100644
--- a/src/components/Widgets/Markdown/MarkdownControl/VisualEditor/components.js
+++ b/src/components/Widgets/Markdown/MarkdownControl/VisualEditor/components.js
@@ -35,7 +35,6 @@ export const NODE_COMPONENTS = {
'numbered-list': props =>
{props.children}
,
'link': props => {
- // Need to wrap this in mark components for any marks found in data.
const data = props.node.get('data');
const marks = data.get('marks');
const url = data.get('url');
@@ -47,6 +46,19 @@ export const NODE_COMPONENTS = {
}, link);
return result;
},
+ 'image': props => {
+ const data = props.node.get('data');
+ const marks = data.get('marks');
+ const url = data.get('url');
+ const title = data.get('title');
+ const alt = data.get('alt');
+ const image =
;
+ const result = !marks ? image : marks.reduce((acc, mark) => {
+ const MarkComponent = MARK_COMPONENTS[mark.type];
+ return {acc};
+ }, image);
+ return result;
+ },
'shortcode': props => {
const { attributes, node, state: editorState } = props;
const isSelected = editorState.selection.hasFocusIn(node);
diff --git a/src/components/Widgets/Markdown/serializers/__tests__/slate.spec.js b/src/components/Widgets/Markdown/serializers/__tests__/slate.spec.js
index ae8383e7..768220e8 100644
--- a/src/components/Widgets/Markdown/serializers/__tests__/slate.spec.js
+++ b/src/components/Widgets/Markdown/serializers/__tests__/slate.spec.js
@@ -28,4 +28,8 @@ describe('slate', () => {
expect(process('**a**b**c**')).toEqual('**a**b**c**\n');
expect(process('**a _b_ c**')).toEqual('**a _b_ c**\n');
});
+
+ it('should parse inline images as images', () => {
+ expect(process('a ')).toEqual('a \n');
+ });
});
diff --git a/src/components/Widgets/Markdown/serializers/remarkImagesToText.js b/src/components/Widgets/Markdown/serializers/remarkImagesToText.js
index f63d3820..568e8a06 100644
--- a/src/components/Widgets/Markdown/serializers/remarkImagesToText.js
+++ b/src/components/Widgets/Markdown/serializers/remarkImagesToText.js
@@ -1,18 +1,26 @@
/**
* Images must be parsed as shortcodes for asset proxying. This plugin converts
- * MDAST image nodes back to text to allow shortcode pattern matching.
+ * MDAST image nodes back to text to allow shortcode pattern matching. Note that
+ * this transformation only occurs for images that are the sole child of a top
+ * level paragraph - any other image is left alone and treated as an inline
+ * image.
*/
export default function remarkImagesToText() {
return transform;
function transform(node) {
- const children = node.children ? node.children.map(transform) : node.children;
- if (node.type === 'image') {
- const alt = node.alt || '';
- const url = node.url || '';
- const title = node.title ? ` "${node.title}"` : '';
- return { type: 'text', value: `` };
- }
+ const children = node.children.map(child => {
+ if (
+ child.type === 'paragraph'
+ && child.children.length === 1
+ && child.children[0].type === 'image'
+ ) {
+ const { alt = '', url = '', title = '' } = child.children[0];
+ const value = ``;
+ child.children = [{ type: 'text', value }];
+ }
+ return child;
+ });
return { ...node, children };
}
}
diff --git a/src/components/Widgets/Markdown/serializers/remarkSlate.js b/src/components/Widgets/Markdown/serializers/remarkSlate.js
index 00c6942e..ef28f570 100644
--- a/src/components/Widgets/Markdown/serializers/remarkSlate.js
+++ b/src/components/Widgets/Markdown/serializers/remarkSlate.js
@@ -74,7 +74,7 @@ function createBlock(type, nodes, props = {}) {
/**
* Create a Slate Block node.
*/
-function createInline(type, nodes, props = {}) {
+function createInline(type, props = {}, nodes) {
return { kind: 'inline', type, nodes, ...props };
}
@@ -312,9 +312,23 @@ function convertNode(node, nodes) {
case 'link': {
const { title, url, data } = node;
const newData = { ...data, title, url };
- return createInline(typeMap[type], nodes, { data: newData });
+ return createInline(typeMap[type], { data: newData }, nodes);
}
+ /**
+ * Images
+ *
+ * Identical to link nodes except for the lack of child nodes and addition
+ * of alt attribute data MDAST stores the link attributes directly on the
+ * node, while our Slate schema references them in the data object.
+ */
+ case 'image': {
+ const { title, url, alt, data } = node;
+ const newData = { ...data, title, alt, url };
+ return createInline(typeMap[type], { isVoid: true, data: newData });
+ }
+
+
/**
* Tables
*
diff --git a/src/components/Widgets/Markdown/serializers/slateRemark.js b/src/components/Widgets/Markdown/serializers/slateRemark.js
index aca2d42c..522a9b7a 100644
--- a/src/components/Widgets/Markdown/serializers/slateRemark.js
+++ b/src/components/Widgets/Markdown/serializers/slateRemark.js
@@ -474,6 +474,21 @@ function convertNode(node, children, shortcodePlugins) {
return u(typeMap[node.type], { url, title, data }, children);
}
+ /**
+ * Images
+ *
+ * This transformation is almost identical to that of links, except for the
+ * lack of child nodes and addition of `alt` attribute data. Currently the
+ * CMS handles block images by shortcode, so this case will only apply to
+ * inline images, which currently can only occur through raw markdown
+ * insertion.
+ */
+ case 'image': {
+ const { url, title, alt, ...data } = get(node, 'data', {});
+ return u(typeMap[node.type], { url, title, alt, data });
+ }
+
+
/**
* No default case is supplied because an unhandled case should never
* occur. In the event that it does, let the error throw (for now).