I just started using NodeBB about a week ago. A project came up that required the use of a forum and being that I have such an affinity towards Node.js... the results of my search for open source forum software quickly narrowed down to NodeBB. Previously I've used both Discourse and PhpBB from both administrator and user standpoints, and I've been fairly pleased with both. While getting to know NodeBB more intimately, there has certainly been a few things that I disliked and that stood out almost immediately.
- The documentation could be more up to date.
- The Docker container was a bit wonky when trying to get it to work (another post), which pointed back to #1.
- Viewing post images left a lot to be desired as there is no built in gallery support and there werent any plugins for such. The images in posts were simply inlined.
- Uploading was limited to direct uploads to the server (future post about the Cloud Storage plugin I wrote)
Write a NodeBB Plugin (nodebb-plugin-lightgallery)
The solution to problem #3 above came in the form of writing a NodeBB plugin:
- GitHub - https://github.com/june07/nodebb-plugin-lightgallery
- NPM - https://www.npmjs.com/package/nodebb-plugin-lightgallery
This post will explain the general process of doing that...
LightGallery itself is modular and as such is made up of many different modules in addition to it's core:
$ npm install lightgallery lg-thumbnail lg-autoplay lg-video lg-fullscreen lg-pager lg-zoom lg-hash lg-share
As such I included all of those libraries in my plugin.json file which is the configuration file of a NodeBB plugin. Further, NodeBB operates with a hook architecture and the hook I was interested in is
filter:middleware.render which gets called before each page render and allows you to alter the page beforehand. Per the documentation which reads:
For example, a filter may be used to alter posts so that any occurrences of "apple" gets changed to "orange". Likewise, filters may be used to beautify content (i.e. code filters), or remove offensive words (profanity filters).
Our goal is to change every post such that markup is altered to match that required by LightGallery, and further we must instantiate the LightGallery plugin:
If you're familiar with Express middleware then this is a pretty easy concept to grasp. As I was still new to NodeBB and writing plugins for it, I chose the name "myfiltermethod" for the method that would be called on each
filter:middleware.render hook. The
We need a way to let the LightGallery plugin know about this new mapping, as it will want to look for assets from a more basic root path by default. The method I chose to solve this was to simply change the path in the LightGallery scss files and then re-compile the scss assets during build time which is all handled via Travis-CI build process. The highlighted lines show where the scss variables are changed before running Grunt for each of the LightGallery dependancy modules.
Once all of the dependancies are taken care of we need to actually write some code. In this case the code is pretty simple in that there is only a single module which is called by the
filter:middleware.render hook and inside of that module a single function
The updatePost function takes in the post data which is a JSON object with the markup held in the content key. We generate a
lightgalleryWrapper which maps to the required wrapper tag that LightGallery needs to identify which markup should be included in the image gallery. Note that we also key the wrapper's id with the post.pid such that multiple galleries can exist per page, in fact one per post.
<div id="lightgallery' + post.pid + '"></div>
Then we iterate through the content's markup finding all of the images and translate them to the markup required by LightGallery, assigning the final updated markup back to the content value of the post object.
post.content = html
Finally executing the callback at the end passing in null first (where the error object were to go if there were errors) and the data object.
return callback(null, data)
Instead of images opening inline as shown in the first gif below, using the nodebb-plugin-lightgallery plugin displays images in a beautiful image gallery, making not only viewing easier but also navigating, downloading, and otherwise interacting with the images in the post.
NodeBB WITHOUT the nodebb-plugin-lightgallery Plugin
NodeBB WITH the nodebb-plugin-lightgallery Plugin
So writing my first NodeBB plugin was fairly straight forward and while it didn't take too much effort, I feel that it delivers a HUGE improvement over a "stock" NodeBB install. The user experience is very much improved when using a gallery over having images open inline, particularly when it comes to forums. Next time I will write about the 2nd NodeBB plugin I decided to write which provides a way to offload images to external cloud providers (Cloudinary, ImageKit, and AWS S3) vs storing them locally on the NodeBB server.