plugin-conversation (a README Experience)

A plugin for Micro.blog with a partial for including replies and webmentions for post pages. The plugin also supports blacklisting individual responses to prevent their appearance. Its code lives here

Let's see … where to start. How about we change things up for this one and start with how you can get your mentions to show up on your post pages.

Showing Up is Half the Battle

You'll need a custom theme you can edit. Holler if you don't have one and you don't know how to get one (or the thought of doing so makes you nervous). The file you'll want to edit (don't create a new template, find it in the list of files … under Custom Templates if you've edited it before and under Templates for *Your Base Theme* if haven't (in which case editing the file will create one under Custom Templates) is layouts/post/single.html. Locate the spot in the HTML where you'd like the mentions to appear and insert the following:

{{ if (templates.Exists "partials/plugin-conversation/conversation.html") }}
{{ partial "plugin-conversation/conversation.html" . }}
{{ end }}

Boom, you're done. Congrats.

Now if you happen to post a README, like so, that happens to spark a Micro.blog conversation like so…

you can totally have that conversation displayed at the bottom of the posted README like so:

Of course, the replies won't be limited to those originating from Micro.blog. What we're actually displaying here are webmentions that have been received for a post.

Wait … WTF is a Webmention

Honestly, it doesn't really matter that you know WTF a webmention happens to be. The inquisitive can find out more about webmentions here. The cool thing is that @manton has you setup to receive them. When you do, they appear right along with the Micro.blog replies. If you are cross-posting to Twitter, have a look at Bridgy. Connect your account to your blog and when you have a post like … say … this one … that you drop into tweets kinda like this…

or like this…

you can totally have the reply tweets garnered and displayed at the bottom of the post kinda like:

Let's look at the configurable bits of the plugin.

The Configurable Bits

I don't feel like repeating myself this morning. Have a peek at the other READMEs to see how my plugins use data template files and how to persist them outside of the plugin's directory. This bit here may be helpful.

This plugin utilizes three configuration files: Config.toml, Filter.toml, and Style.toml (all of which are located in the data/plugin_conversation subdirectory.

Let's have a look at each of them.

Config.toml

The first file we'll look at lives at data/plugin_conversation/Config.toml and it looks like this:

# Debug and build related parameters.
#####################################

# Theme version, printed to HTML comment when the plugin loads.
#
Version = '3.0.4'

# Whether to print HTML comments for debugging purposes.
#
DebugPrint = false

# Whether to provide subresource integrity by generating a 
# base64-encoded cryptographic hash and attaching a .Data.Integrity
# property containing an integrity string, which is made up of the
# name of the hash function, one hyphen and the base64-encoded hash sum.
#
Fingerprint = true

# Output style for /assets/sass/conversation.scss. 
# Valid options are nested, expanded, compact and compressed
#
SassOutput = 'compressed'

This file contains what have become standard parameters for my plugins. Version is used to inject an HTML comment into the page <head>. DebugPrint will dump the parameter values as parsed by the plugin into an HTML comment (also located in the page <head>). The other two parameters control linking and compression for the generated stylesheet.

Filter.toml

The second file we'll look at lives at data/plugin_conversation/Filter.toml and it looks like this:

# Filtering the display of conversation items.
##############################################

# An array of the ids of conversation items to hide.
#
HiddenItems = []

Let's explain by example. Say you've managed to tweet something linking to one of your posts that makes sense in the Twittersphere…

but not so much in the context of the linked post:

If you view the page source of your post to locate the comment…

<div id="12416291" class="u-comment h-cite">
    <a class="u-author h-card" href="https://twitter.com/moondeerdotblog">
      <img class="u-photo" src="https://pbs.twimg.com/profile_images/1419836243592941569/l2U3vTrg.jpg">
      <span class="p-nickname">Moondeer</span>
    </a>
    <p class="e-content p-name"><a href="https://micro.blog/Moondeer">[@Moondeer](https://micro.blog/Moondeer)</a> <a href="https://twitter.com/search?q=%23MoodyThisMorning">#MoodyThisMorning</a> 
<a class="u-mention" href="https://moondeer.blog/2022/01/14/in-case-anyone.html"></a></p>
    <a class="u-url" href="https://brid.gy/post/twitter/moondeerdotblog/1486416644553404419">
      <small>
        <time class="dt-published">7:40 PM • Jan 26, 2022</time>
      </small>
    </a>
  </div><

take the id value and stick it in the HiddenItems array…

# Filtering the display of conversation items.
##############################################

# An array of the ids of conversation items to hide.
#
HiddenItems = [ '12416291' ]

then, once your site rebuilds, the undesirable comment will generate HTML with an additional attribute inserted into the opening <div> tag…

<div id="12416291" class="u-comment h-cite" hidden="">

and it totally won't be included at the bottom of the post:

Style.toml

The last file we'll look at lives at data/plugin_conversation/Style.toml and it looks like this:

# Parameters for styling conversation items
###########################################

# The class name to assign to the conversation items wrapper.
#
WrapperID = 'conversation-items'

# Sass block to apply to the conversation items wrapper.
#
Wrapper = ''

# Sass block to apply to item wrappers.
#
Item = ''

# Sass block to apply to the item content wrapper.
#
Content = ''

# Sass block to apply to item author wrappers.
#
Author = ''

# Sass block to apply to avatars.
#
Avatar = ''

# Sass block to apply to item author names.
#
Name = ''

# Sass block to apply to item links.
#
ItemLink = ''

# Sass block to apply to item publish dates.
#
PublishDate = ''

[Variables]

# The width and height for the avatar image.
#
Avatar.Diameter = '64px'

# The shape of the avatar image: square or circle.
#
Avatar.Shape = 'circle'

# The CSS box shadow property value applied to the avatar image.
#
Avatar.BoxShadow = '0 0 0 3px #FFFFFF, 0 0 0 4px #EEEEEE'

These are all parameters that are used to generate the Sass file (that generates the CSS file). Any valid CSS is also valid Sass (as we are using Sass' SCSS syntax here). Here's how the parameters fill in the Sass template:

@import "vendor/rfs";

$avatar_diameter: /* Variables.Avatar.Diameter */;

#/* WrapperID */ {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  margin-top: 2rem;
  /* Wrapper */
  
  .u-comment {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    /* Item */
    
    .u-author {
      display: flex;
      align-items: center;
      gap: 1ch;
      /* Author */
      
      .u-photo {
        width: $avatar_diameter;
        height: $avatar_diameter;
        box-shadow: /* Variables.Avatar.BoxShadow */;            
        border-radius: $avatar_diameter * .5; /* iff Variables.Avatar.Shape = circle */
        /* Avatar */
        
      }
      
      .p-nickname {        
        @media (min-width: 1024px) {
           margin-top: $avatar_diameter * -.5; 
        }
 
        /* Name */
        
      }
      
    }
    
    .e-content {
      padding: 0;
      margin: 0;
      
     a.u-mention:empty { display: none;}

      @media (min-width: 1024px) {
        &::first-line { padding-left: $avatar_diameter * 1.1; }
        :first-child { padding-left: $avatar_diameter * 1.1; }
        margin-top: $avatar_diameter * -.5;
      }
      
      /* Content */
      
    }
    
    .u-url {
      margin-top: 0;
      padding-top: 0;
      /* Link */
      
      .dt-published {
        /* PublishDate */
      }
    
    }
    
  }
  
}

Alrighty, then. As always, holler with any question. Signing off. ☾𐂂 out.