Scully - Create A Custom Plugin

Scully follows the plugin system to process the pages at the time of the pre-rendering. It has various inbuilt plugins and community plugins.
 
In the previous article, Syntax highlighting in markdown for blog made with Scully, we have used the markdown plugin, which is the inbuilt plugin provided by Scully. While in the article, Using Copy To Clipboard Plugin To Add Copy Button In Code Snippets we have used one of the community plugins.

You can also create a custom plugin and use it in our application for handling the prerendering process. Scully has six main types of plugins.

In this article, we will see how to create a custom Scully plugin.  If you want to code along, clone or copy this GitHub repository.
 
Check out the previous Scully series articles,
Let's get started.
 
We will create a footer plugin, which will add the author name and blog updated date.
 
Footer Plugin

Creating a custom plugin for Scully is easy. We just need to follow the below steps:
  1. Create a plugin function,
    1. // pugin.ts  
    2.   
    3. import { registerPlugin, getPluginConfig } from '@scullyio/scully';  
    4.   
    5. export const myPlugin = 'myPlugin';  
    6.   
    7. const myFunctionPlugin = async (html: string): Promise<string> => {  
    8.   return html;  
    9. };  
    10.   
    11. const validator = async () => [];  
  2. Register a plugin,
    1. // plugin.ts  
    2.   
    3. registerPlugin('postProcessByHtml', myPlugin, myFunctionPlugin, validator);  
    - postProcessByHtml is one of the plugin types.

  3. Use the plugin,

    To use a custom plugin, we need to add it in scully.[projectName].config.ts
    1. // scully.[projectName].config.ts  
    2.   
    3. import { myPlugin }  from './scully/plugins/plugin';  
    4.   
    5. export const config: ScullyConfig = {  
    6.   ...  
    7.   defaultPostRenderers : [myPlugin],  
    8.   routes: {  
    9.     '/blog/:slug': {  
    10.       type: 'contentFolder',  
    11.       slug: {  
    12.         folder: "./blog"  
    13.       }  
    14.     },  
    15.   }  
    16. };  
At the time of Scully installation by default, it adds one plugin.ts file which we will use for creating a custom plugin.
 

Scully Plugin Types


There are six main types of plugins that allow code to be injected into various stages of the Scully process lifecycle. We can create a custom plugin for any type based on our requirements.
  1. router - plugins teach Scully how to get the required data to pre-render pages from the route params.
  2. postProcessByDom - is a kind of render plugin, which allows you to update the DOM. You will get the JSDOM object in the plugin function as an argument.
  3. postProcessByHtml - is a also a render plugin which executes after postProcessByDom. In this plugin function, you get an HTML string as an argument.
  4. fileHandler - plugin is used by the contentFolder plugin during the render process. The contentFolder plugin processes the folders for markdown files or another file type the folders may contain.
  5. routeDiscoveryDone - plugins are called automatically after all routes have been collected and all router plugins have finished.
  6. allDone - plugins are like routeDiscoveryDone plugins, except they are called after Scully finishes executing all its processes.

Create Footer Plugin


We will create a postProcessByDom plugin. Which will take DOM as an argument. 
  1. // plugin.ts    
  2. import {  
  3.     registerPlugin,  
  4.     getPluginConfig,  
  5.     HandledRoute  
  6. } from '@scullyio/scully';  
  7. import {  
  8.     JSDOM  
  9. } from 'jsdom';  
  10. export const footerPlugin = 'footerPlugin';  
  11. const footerPluginFunction = async (dom: JSDOM, route: HandledRoute): Promise < JSDOM > => {  
  12.     console.log('Route Data : ', route.data);  
  13.     let document = dom.window.document;  
  14.     let footer = document.createElement('footer');  
  15.     footer.className = 'blog-footer'  
  16.     footer.innerHTML = `<span> ✍ ${route.data.author} </span>     
  17.                       <span> 📅 ${new Date().toLocaleDateString()}</span>`  
  18.     document.querySelector('body').appendChild(footer);  
  19.     return dom;  
  20. };  
  21. const validator = async () => [];  
  22. registerPlugin('postProcessByDom', footerPlugin, footerPluginFunction, validator);   

Use Footer Plugin


To use this plugin we need to add it in defaultPostRenderers array of ScullyConfig, or if you want to add it for any specific routes you can set it in postRenderers, as shown below:
  1. import { ScullyConfig, setPluginConfig } from '@scullyio/scully';  
  2. import { footerPlugin }  from './scully/plugins/plugin';  
  3.   
  4. export const config: ScullyConfig = {  
  5.   projectRoot: "./src",  
  6.   projectName: "portfolio",  
  7.   outDir: './dist/static',  
  8.   routes: {  
  9.     '/blog/:slug': {  
  10.       type: 'contentFolder',  
  11.       postRenderers: [ footerPlugin ],  
  12.       slug: {  
  13.         folder: "./blog"  
  14.       }  
  15.     },  
  16.   }  
  17. };  
Add author in markdown meta details:
 
Blog Author Meta Details

Great!!! We have created the footer plugin, now take a build and test it.
 
Output
 
Take a build with the following command:
  1. npm run scully -- --scanRoutes && npm run scully:serve  
Now go to the blog page and verify the output.
 
Scully footer plugin output
 

Summary

 
In this article, we have seen how to create a custom Scully plugin. We have created a footer plugin that adds the blog meta details in the blog footer. You can create other plugins based on your requirement.
 
I hope you like this article. Please provide your valuable feedback and suggestions in the comment section🙂.
 
If you feel this is useful to others please like and share.


Similar Articles