Building a Plugin to Embed Tweets in Crafter Studio's Rich Text Editor

Crafter Studio supports Rich Text Editing via TinyMCE by default. TinyMCE is one of the most powerful WYSIWYG editors. This Rich Text Editor (RTE) enables users to input different types of content such as text, images, videos, and so on to Crafter Studio. We can also extend TinyMCE with plugins.

In this article, we will build an RTE plugin for TinyMCE that enables authors to easily embed Tweets to site pages. This plugin uses Tweet ID as the only input required to render Embed Tweets either by inserting static HTML or dynamically at runtime.

Prerequisites

No special requirements for this plugin. You only need a running instance of Crafter Studio. For this article, we are using CrafterCMS 3.1 version and TinyMCE 5.

Create a Built-In Site

For convenience, we have already created a site blueprint to include this RTE plugin. You can use this repository to do a quick scan of how the plugin is added. This blueprint is based on the Editorial Blueprint.

To create a new site with the above blueprint, from Crafter Studio, click create a new site from Git Remote Repository.

  • Site ID: tw
  • Git Repo URL: https://github.com/phuongnq/craftercms-embed-tweet-sample-site
  • Everything else can be as default.

If you successfully create the site, go to the dashboard, articles pages, check a page which we have included a Tweet as the following screenshot.

Click Edit to confirm that our plugin has been included.

We have two buttons to embed Tweets: Add Tweet Embed Dynamic or Add Tweet Embed Static. In the next section, we will discuss more details about this. Click on Add Tweet Embed Static to open a popup. Input any Tweet ID to insert raw html to the page.

Install Plugin

In this section, we discuss more how to implement this kind of RTE plugin. Full source code can be found in this repository.

Embed Tweets bring the ability to include Twitter content to your site. We can even customize how the Tweet should look with some supported options such as color themes, show cards, conversations, threads or not, and so on. For more information, check out the Twitter official documentation.

We will introduce two ways to embed a Tweet to a Crafter site: static with raw HTML or dynamically rendering with JavaScript. While static raw HTML is more suitable for sites with static page content in HTML, dynamically rendering is more suitable for dynamic SPA sites such as React or Angular applications.

Note: Check out this document for how to add an RTE plugin to TinyMCE in Crafter Studio.

Add Tweet Embed Static

For this type of plugin, we use the oEmbed API to convert a Tweet ID into embedded Tweet markup. A sample request looks like this:

GET https://publish.twitter.com/oembed?url=https://twitter.com/Interior/status/507185938620219395

Sample of response:

{
"url": "https://twitter.com/Interior/status/507185938620219395",
"author_name": "US Dept of Interior",
"author_url": "https://twitter.com/Interior",
"html": "<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Happy 50th anniversary to the Wilderness Act! Here&#39;s a great wilderness photo from <a href="https://twitter.com/YosemiteNPS">@YosemiteNPS</a>. <a href="https://twitter.com/hashtag/Wilderness50?src=hash">#Wilderness50</a> <a href="http://t.co/HMhbyTg18X">pic.twitter.com/HMhbyTg18X</a></p>&mdash; US Dept of Interior (@Interior) <a href="https://twitter.com/Interior/status/507185938620219395">September 3, 2014</a></blockquote>n<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>",
"width": 550,
"height": null,
"type": "rich",
"cache_age": "3153600000",
"provider_url": "https://twitter.com",
"provider_name": "Twitter",
"version": "1.0"
}

From the response, the html field will be included on pages. In order to achieve this, we need an RTE plugin and a Groovy script that actually sends HTTP GET requests from Crafter Studio server to oEmbed Twitter API. The RTE plugin sends another HTTP request to this Groovy REST API and extracts HTML data from the response.
First of all, let’s take a look at the configuration for TinyMCE 5.


Go to Crafter Studio > Configuration > RTE (TinyMCE5) Configuration.

Add extended elements so that it won’t be stripped by Studio:

<extendedElements>script[src|async|defer|type|charset]</extendedElements>
Add new plugin to toolbar items:
<toolbarItems2>embed_tweet_static</toolbarItems2>
Add a link to the plugin source code:
<external_plugins> 
<embed_tweet_static><![CDATA[/studio/api/2/plugin/file?siteId={site}&type=tinymce&name=embed_tweet_static&filename=plugin_static.min.js]]></embed_tweet_static>
</external_plugins>

Create plugin folder and add the file to the correct location:

https://github.com/phuongnq/craftercms-rte-plugin-twitter/blob/master/build/rte/plugin_static.min.js

$ cd CRAFTER_HOME/data/repos/sites/SITE_NAME/sandbox/
$ mkdir -p CRAFTER_HOME/data/repos/sites/SITE_NAME/sandbox/config/studio/plugins/tinymce/embed_tweet_static
$ cp plugin_static.min.js CRAFTER_HOME/data/repos/sites/SITE_NAME/sandbox/config/studio/plugins/tinymce/embed_tweet_static/
$ git add .
$ git commit -m "Add plugin"

Note: We used a minified version of plugin_static.js. Source code of this file can be found here: https://github.com/phuongnq/craftercms-rte-plugin-twitter/blob/master/src/rte/plugin_static.js


For the next step, we add a Groovy script that actually sends requests to oEmbed AP.

Open Site Dashboard > scripts > rest

Add a new script with the name tweet.get.groovy. The content of this script is just a simple HTTP request.

https://github.com/phuongnq/craftercms-rte-plugin-twitter/blob/master/src/rest/tweet.get.groovy

def result = new URL("https://publish.twitter.com/oembed?url=https://twitter.com/Interior/status/" + params.tweetId).text;
return result

The script reads tweetId parameter from the query string then opens an HTTP request to oEmbed API.

Save and reload, the plugin should be available as mentioned in the previous section.

Add Tweet Embed Dynamic

While adding raw HTML works for most static pages, there are many cases in which we need to dynamically render content. For example, the application is a SPA one with frameworks like React or AngularJS. In such cases, we may want to dynamically render Embed Tweets along with the content rendering.

To serve this purpose, we only need to insert the Tweet ID to a page with a placeholder. While a user accesses the page, it dynamically replaces the placeholder content with actual Embed Tweets. Thanks to the Embedded Tweet JavaScript Factory Function, we can easily implement this approach. The placeholder is something like this:

[TWEET:ID_GOES_HERE]

Let’s configure TinyMCE 5 for this type of plugin.

Go to Crafter Studio > Configuration > RTE (TinyMCE5) Configuration.

Add plugin to toolbar items:

<toolbarItems2>embed_tweet_dynamic</toolbarItems2>

Add a link to the plugin source code:

<external_plugins>
<embed_tweet_dynamic><![CDATA[/studio/api/2/plugin/file?siteId={site}&type=tinymce&name=embed_tweet_dynamic&filename=plugin_dynamic.min.js]]></embed_tweet_dynamic>
</external_plugins>

Create plugin folder and add the following file:

https://github.com/phuongnq/craftercms-rte-plugin-twitter/blob/master/src/rte/plugin_dynamic.js

$ cd CRAFTER_HOME/data/repos/sites/SITE_NAME/sandbox/
$ mkdir -p CRAFTER_HOME/data/repos/sites/SITE_NAME/sandbox/config/studio/plugins/tinymce/embed_tweet_dynamic
$ cp plugin_dynamic.min.js $ CRAFTER_HOME/data/repos/sites/SITE_NAME/sandbox/config/studio/plugins/tinymce/embed_tweet_dynamic/
$ git add .
$ git commit -m "Add plugin"

Note: We used a minified version of plugin_static.js. Source code of this file can be found here: https://github.com/phuongnq/craftercms-rte-plugin-twitter/blob/master/src/rte/plugin_dynamic.js

As you may have noticed, this type of plugin only adds following snippet to pages:

<span class="tweet-embed">[TWEET:${data.tweetId}]</span>

Your application has to read tweetId at runtime and replace it with actual embedding Tweets. This is not a part of the plugin, but we also have some samples on how to render this.

Render using JavaScript:

https://github.com/phuongnq/craftercms-rte-plugin-twitter/blob/master/src/sample/javascript_app.html

Render using React:

https://github.com/phuongnq/craftercms-rte-plugin-twitter/blob/master/src/sample/react_app.js


In both cases, we traverse content and replace Tweet ID with actual embedding content by using createTweet function:

window.twttr.widgets.createTweet(tweetId, <html element>, <option>)

It is required to include https://platform.twitter.com/widgets.js to use this function. By using the createTweet function, we can also customize how the embedding Tweet should look like. Refer to this documentation for more detail on how to customize it.

Conclusion

In this article, we introduced how to create a TinyMCE plugin to embed a Tweet in the RTE within Crafter Studio. The TinyMCE-rich text editor within Crafter Studio is extensible. This article is just an example of how we can add a plugin to it.

You can also create your own unique plugins for TinyMCE to serve your specific requirements. To learn more check out CrafterCMS at https://craftercms.com and https://craftercms.org.