Captain Codeman Captain Codeman

Polymer Web-Components for Markdown Image Upload

Creating a great image upload experience with Markdown



One of the great things about Polymer and Web-Components is they are part of the platform. What I mean by that is that once you define an element, you can add some HTML containing a reference to it however and wherever you like and the browser will render it.

Not all JavaScript frameworks can do that. Amazingly, some front-end frameworks don’t seem to be able to handle HTML unless it’s HTML that they are generating. Set some innerHTML and even though it may contain elements defined in the app, they won’t appear.

To show how useful it is, imagine we want to implement a markdown editor with Ghost-like image uploading …

In case you haven’t seen it, the Ghost editor has a great feature where, when you add a blank image reference, it will render it as a placeholder prompting you to upload the actual image.

It’s a great idea and I wanted to implement the same approach for my own blog engine. Unfortunately, all the implementations I could find were quite complex and didn’t fit with other parts of my app so I set out to build it myself.

It turns out that Web-Components really help to make this easy. Here’s how it works with the prototype I’ve been working on:

As you type, the markdown content is rendered to HTML and shown in the preview. Here we are about to finish adding a reference to an image:

Adding an image reference

Once added, this would normally render as an empty image, but we hook into the markdown rendering and, if there is no src, we set the rendered output to be an <image-placeholder> element.

This is a custom element defined in the app that renders a placeholder complete with file input selection box if you click it or support for drag-and-drop.

Image upload placeholder

Selecting an image loads it into the box (so it now appears inline) and starts the upload process. It shows a progress bar to reflect the upload progress and once completed, the src for the newly added image is inserted into the markdown image reference source.

Once this is done, the markdown preview automatically updates (because Polymer is observing it) and this time the image is rendered as a regular <img> element.

Image reference replaced

The end result is an easy-to-use image upload mechanism for use by content authors.

Also helping to make this possible is Google Cloud Storage and their newly added pubsub push notifications. When the client wants to upload an image it just has to make an API call to send the image metadata to the server and receives a signed URL that can be used to PUT the image directly to the cloud storage bucket.

The client doesn’t need to do anything else once this is successful - the pubsub push notification calls the server to let it know about the new file and the metadata is added to the system. It could at this point pre-generate different sizes for use in responsive layouts but right now I’m doing that dynamically as they are requested.