Awesomify anything or anyone with OpenFaaS!

While I’ve been lurking about the OpenFaaS Community I haven’t really had the wherewithal to actually get myself knuckled-down to build something that might be classed as useful or fun. To remedy that I finally came up with a new idea for a function that I can publish into the FaaS Store. I’m calling this function “Awesomify”. It will take any text you throw at it and make it awesome!

Photo by Jon Tyson on Unsplash

First thing I need is a Kubernetes cluster. After a quick trip down to Marks and Sparks to fill my trolly with juicy servers, I remembered that this is supposed to be serverless computing, plus M&S is a clothing store so I wouldn’t get servers there anyway. Putting the servers back on the shelves I instead fired up Google Cloud’s dashboard and ordered some Kubernetes with a side order of Chips (Fries for folk over the pond).

Following the OpenFaaS documentation and my serverless system is now fully deployed, and it was easy (mostly, I had a couple of hiccups from following the docs too closely which I’ve filed bugs about so they should get resolved soon).

The function

Now to my function. Which language or framework should I use to build it? NodeJS? Pass. Go? Hmm, interesting idea, but nah. BASH? Now you’re talking; you can’t get more esoteric than that! Let’s write an entire function using BASH…

Photo by Luca Bravo on Unsplash

For my function to work, I need some sound clips. So pulling out my scissors I found a cassette of Tegan and Sara’s greatest hits and started hacking away. After 36 hours of toil, I finally had a series of clips that are usable and a large pile of wasted audio tape.

The only thing missing now is a voice generator. While I could use a cloudy serverless service such as Amazon’s Polly or Google’s Cloud TTS I decided that open source was the way forward. There’s a little-known project called Mycroft which creates a completely open source Intelligent Assistant like Amazon Echo, Google Assistant, or Apple Siri. They have released a piece of code they named “Mimic” to perform text to speech duties.

As an aside, my good friend Alan Pope from Canonical lent his voice to the Mimic TTS engine and the Mycroft assistant so this choice of engine was even more fun for me.

With the function taking shape I felt ready to publish a trial run onto my test cluster on Google Cloud. Two hours after publishing it and tweeting a few times the function has been hit 396 times and nobody has complained since I increased the timeouts and minimum instance count from their defaults.

Photo by William Stitt on Unsplash

And we’re off to the races!

A Pull Request is now into the OpenFaaS Store GitHub repository to add the function for anybody to use with a simple clickity-doodle. If you don’t have or want your own instance of the function you may use the test that is still operational. You just need to point your web browser to https://openfaas.bowlhat.net/function/awesomify?q=OpenFaaS. By changing the text after the “?” you can tailor what is awesome to your own needs. (Make sure you replace spaces in the text with a + symbol because addresses need to be “URL Encoded”)

A few examples I’ve tried are:


My source code is published at GitHub.

Pure CSS Loading Animation

Showcasing my skills in Web Development where I am constantly pushing the boundaries, here is my CSS Loading Animation. The experiment here uses CSS keyframes to achieve 60 frames per second animation without repainting the elements.

To build the animated object (the spinner) I use a pair of incomplete CSS Triangle tricks. When you combine the CSS Triangle trick with border-radius you find you can curve one edge of the triangle. However, I probably reinvented this method, but I haven’t seen any prior art.  The nice Home button on this site’s menu bar shows how I use a single rounded triangle.

As I saw that the single rounded triangle worked quite well. So, I started experimenting, leading me to the complete circle design you see in the spinner.

The effect is created by hacking the CSS Triangle trick to display two opposing triangles instead of one directional arrow. This is created with two non-transparent borders instead of one, which would create a single arrow:

.selector {
    border-left: 25px solid transparent;
    border-right: 25px solid transparent;
    border-top: 25px solid #eee;
    border-bottom: 25px solid #eee;
}

Once we have the opposing triangles we apply a 50% border radius on the element. This forces a circular appearance with two slices and two gaps. Finally, we create a sibling using the :after CSS selector providing the remaining two slices in the gaps from the first element:

.selector:after {
    border-left: 25px solid #ccc;
    border-right: 25px solid #ccc;
    border-top: 25px solid transparent;
    border-bottom: 25px solid transparent;
}

The first example shows an effect similar to Apple’s “Beach Ball”. Both elements animate together. Because the same look can be achieved without two separate elements, the second demo shows a use for keeping them separate:

So, we use two separate elements to create this slightly different effect. Here, we animate each pair of opposite triangles separately. The effect is somewhat pleasing:

How to make the A-Z Listing plugin for WordPress use a different Index Letter for a post

This post talks about our A-Z Listing Plugin, which is available on WordPress.org.

How did we get here?

After a long battle with a very considerate person in the WordPress.org forums where I repeatedly failed to get them working with various attempts at writing code they could drop into their site, I decided I needed to write it up and explain how to do this once and for all.

The scenario

  • You have a series of posts with Proper Nouns (people’s names) as their title
  • You want to index them on their Family Name (sometimes called the “Last Name”)

The concept is fairly simple, in that you need to hook into the filter that I’ve provided and return the right result with the index letter changed. This is the rub in my attempt at helping the person on WordPress.org in that I really didn’t understand my own code well enough, despite having written it, so I kept suggesting non-working solutions.

The final code

add_filter( 'a_z_listing_item_indices', 'my_a_z_index_filter', 10, 3 );

function my_a_z_index_filter( $indices, $item, $item_type ) {
    // make sure we're filtering the right post type
    if ( 'post-type-we-want' === get_post_type( $item ) ) {
        // pull the title and get the first letter of the second word
        $full_name = explode( ' ', $item->post_title );

        // the last word is in the last element of $title_parts so check it is there
        $last_name = array_pop( $full_name );

        // ensure we actually found a last name
        if ( $last_name )  {
            // cut the first letter out for our index
            $index = substr( $last_name, 0, 1 );

            // set up a new empty array
            $indices = array();

            // only the first names are left in $full_name. Join them together again
            $first_names = join( ' ', $full_name );

            // Now put the last name first and separate with a comma+space from the first names
            $formatted_name = "{$last_name}, {$first_names}";

            // add the new name associated with the item into the new array we created
            $indices[ $index ][] = array(
                'title' => $formatted_name,
                'item' => $item,
            );

            // return a new array with our new index letter instead of the
            // indices already discovered by the plugin
            return $indices;
        }
    }

    // if we get here we didn't override the indices so return
    // those already discovered.
    return $indices;
}

The new way (Jan 2019)

Since this post was published I have added a new filter that is much more friendly to use. The new filter does not require a specific format for the return value. Instead, it just needs an array of letters for the post to be indexed against.

add_filter( 'a_z_listing_item_index_letter', 'my_a_z_index_filter', 10, 3 );

function my_a_z_index_filter( $index_letters, $item, $item_type ) {
    // make sure we're filtering the right post type
    if ( 'post-type-we-want' === get_post_type( $item ) ) {
        // pull the title and get the first letter of the second word
        $full_name = explode( ' ', $item->post_title );

        // the last word is in the last element of $title_parts so check it is there
        $last_name = array_pop( $full_name );

        // ensure we actually found a last name
        if ( $last_name )  {
            // cut the first letter out for our index
            $index = substr( $last_name, 0, 1 );

            // set up a new empty array overwriting the old indices
            $index_letters = array( $index );
        }
    }

    // return the indices item's indices
    return $index_letters;
}

Advanced composition of Polymer Webcomponents

In a request for help sent to the Polymer web components mailing list, a user wondered about lists specifically based on the example provided in the Shop Demo that the Polymer team created. This user wanted to understand how to change the list so that it may use a different markup to the one provided for in the original example.

As I thought about and researched this problem I encountered a stack overflow post that talks about a parent providing the markup for a dom-repeat template inside a child’s shadow root. This lead me to experimentation with multiple levels of nesting where only the top-level element or document provided the markup templates for a list and the list items within that list.

Markup included in the document

My top-level document that I settled upon dictates how the children behave. Notably, each element’s innards are wrapped inside a <template> to prevent display when the child elements stamp the light dom into their shadow root.

<my-list items="[[items]]">
  <template item-outer>
    <my-list-item item="[[item]]">
      <template item-inner>
        <img src="[[item.icon]]" />
      </template>
    </my-list-item>
  </template>
</my-list>

The reference to a variable named items maps to the following array of objects (purely an example):

[
  { title: "cat", icon: "https://placekitten.com/128/128/" },
  { title: "random", icon: "https://unsplash.it/128/128/" }
]

The magic isn’t so much in the above invocation, but the individual elements my-list, and my-list-item. They both follow similar layout but need slight differences due to the my-list-item not being able to hijack a dom-repeat template like the my-list is able to.

The my-list Element

<dom-module id="my-list">
  <template>
    <content></content>
    <template is="dom-repeat" id="repeater" items="[[items]]></template>
  </template>
  <script>
    Polymer({
      is: "my-list",
      properties: {
        items: {
          type: Array,
          value: function() { return []; },
          notify: true
        }
      },
      ready: function() {
        this.$.repeater.templatize(this.querySelector('[item-outer]'));
        Polymer.Bind.prepareModel(this.$.repeater);
        Polymer.Base.prepareModelNotifyPath(this.$.repeater);
      }
    });
    </script>
</dom-module>

The magic is achieved via the combination of the insertion point (<content></content>) providing the templated contents from the light dom, and the templatize() function. The function takes a querySelector match of the <template> tag from the light dom by matching on an attribute I assigned. Because I then assign that template to the dom-repeater template stub inside the element definition when the dom-repeat cycles through the items array and stamps itself to this element’s shadow root it will use the code from the light dom as the actual rendered output for each item.

This element has a property that holds the items array, which is then assigned to the dom-repeat template for iteration.

The my-list-item Element

With very similar behaviour to the my-list element, the my-list-item element is largely identical with only minor differences to account for using a <template> that doesn’t, unlike the dom-repeat above, stamp itself to the DOM automatically.

<dom-module id="my-list-item">
  <template>
    <p>[[item.title]]</p>
    <content></content>
    <template is="dom-template" id="tmpl"></template>
  </template>
  <script>
    Polymer({
      is: "my-list-item",
      properties: {
        item: {
          type: Object,
          value: function() { return {}; },
          notify: true
        }
      },
      ready: function() {
        this.$.tmpl.templatize(this.querySelector('[item-inner]'));
        Polymer.Bind.prepareModel(this.$.tmpl);
        Polymer.Base.prepareModelNotifyPath(this.$.tmpl);
        var stamped = this.$.tmpl.stamp({item: this.item});
        this.appendChild(stamped.root);
      }
    });
  </script>
</dom-module>

This element has a property which holds a single item object as provided by the dom-repeat in our parent element my-list. We follow the same pattern as in the list element excepting that, due to using a <template> which does not automatically stamp itself into the DOM, we include two extra lines of javascript, which I’ve highlighted in bold above.

The first extra line stamps the template into a variable with the item property passed through to the template under the same name. Finally, we add the stamped template into the shadow root with appendChild().

I have immortalised the full code in a working example at Codepen

What now?

With this example, it should be possible to see how advanced composition can be achieved allowing for complex scenarios where supporting elements can provide for themselves to be extended without their knowledge. The example of a list taking a list-item template is the most obvious one given our nascent experience with web components, but it is clear that developing this concept can open many new patterns and behaviours.

If you’re a web developer and still haven’t dipped your toe into the pool of web components and Polymer then I urge you to read more and try out some simple examples. Take your own website and find one thing, no matter how small, which is repeated over multiple pages but currently takes more code to reproduce than you’d like. With that thing, try turning it into a fully self-contained web component and replace ever instance of it throughout your site with an instance of the component instead. Finally start thinking of other more complex things that are repeated and try componentizing those, too. Before you know it I hope that you’ll be knee-deep into the world of components and are better-off for it.

Furthering your skillset

Some resources that are helpful for beginner and advanced developer alike include:

Stop discouraging women!

This post is inspired by an advert that I saw on youtube that highlights the damage that can happen to a young woman's psyche with simple behaviour patterns such as telling the woman that she needs to be pretty or even just telling her she is pretty.

I thoroughly agree with the sentiment that many of our brightest female engineers, mathematicians and developers are being discouraged before they even know that they have an interest or aptitude for technical subjects. The Raspberry Pi Foundation is helping in the general push to get more children and young adults to discover the computing realm, but we still have a long way to go until the numbers of children progressing into technical subjects at college and beyond are back where they were in the late 1980s and 1990s.

Moreso the disparity between male and female students on these STEM courses is very evident. We, as a society, need to encourage young adult women to discover an interest in technical or scientific endeavours. The more we can balance the scales the better and more-equal the world will be. This is not just a benefit to the communities that are currently biased toward males but the world, in general, will benefit with new points-of-view pushing technical and scientific discoveries which will filter into every-day life whether the general population realise it or not.

Equality is not just about ensuring that people aren't discriminated based on gender, age, religion, race, sexual orientation, or planet-of-birth; a truly equal society benefits not just those that might previously be discriminated but those that would be the discriminators, equally!

All about the WordPress Fields API

You have probably heard about the effort lead by Scott Clark with guidance from Helen Hou-Sandi to develop a WordPress Feature Plugin mysteriously entitled “WordPress Fields API”. So what is it, what does it do, and why should you care?

Feature Plugins

First-up we need to understand what a Feature Plugin is in relation to WordPress Core:

When the WordPress community decided that we needed a major rewrite of the Administration screens it was realised that such an invasive change would be difficult to develop within Core’s source-code repository. The reasoning is that regular releases of WordPress are likely to be required before the MP6 (as the admin revamp was called) code was ready for the World.

As an upshot of this dichotomy between regular releases and long-term development of code that is likely to be broken many times before it’s ready, the plan was concocted to do the development of MP6 as a plugin. As this plugin was planned to be merged into WordPress Core when it became ready it was dubbed a “feature plugin”. Thus the concept of Feature Plugins was born, and now most larger development efforts are worked-on in this manner.

What is the Fields API then?

Now we know what a Feature Plugin is, we can explore what the Fields API is:

As you’ve probably guessed, and I alluded to above, the Fields API is being developed as a Feature Plugin. The idea behind this feature is to provide an API that WordPress and plugins & themes can utilise to add arbitrary data structures to every object that WordPress handles. These objects include posts, both from the in-built post-types and custom post types, navigation menu items, comments, users, and settings.

Why do I care?

While it may not be something you interact with knowingly, the Fields API should pervade everything you do with WordPress no matter whether you’re a visitor, member, author, or administrator. Every time you enter data into a WordPress site we hope that this will be via a form-field created, output, and saved, by the Fields API.

Plugins and themes will be able to use the API to replace all their custom solutions for form-fields. A previous attempt at unifying some of the admin area settings pages was implemented which we call the Settings API. However, this is only part of the battle, and we anticipate that the Fields API will serve as the back-end to the Settings API in addition to being used elsewhere by non-settings-related forms.

When can I get it?

Thus far a small dedicated team including myself and lead by Scott have been working on getting a proof-of-concept out of the door for user-profile screens. This effort is nearing readiness but there will still be a lot of work to complete once this POC is done. Right now the feature plugin isn’t ready for testing but we hope that it will be soon. If you’re interested in helping-out with development you can join us on the WordPress Slack channel #core-fields where several people hang-out and discuss plans. The source-code for the WordPress Fields API Feature Plugin is hosted at github under Scott’s account; please Fork the code, comment on or create issues in the tracker, fix bugs, and file Pull Requests if you spot anything you can help with or can advise improvements or talking-points about.

TimThumb EOL (finally!)

The Make WordPress blog has finally signalled the end of a disastrous piece of software that made many WordPress sites insecure. TimThumb is/was supposed to allow embedding of images at any dimensions without requiring WordPress to previously have created the variant. The project has been used by many, many, themes available on commercial sites such as ThemeForest and also quite a few that have been published in WordPress.org’s repositories.

TimThumb EOL

The problem is that the project has been plagued by insecurity after vulnerability after blatant holes ever since it launched. Thankfully WordPress.org has signalled that their hosted repositories will no longer allow TimThumb to be included in plugins or themes uploaded from now-on. That means new plugins and themes cannot be added with the code, but still allows existing plugins and themes to have a period of respite as the plugin isn’t being retroactively banned just yet.

The move, in my opinion, is long overdue but at least it’s done now and we can all move forward using more standardised methods such as the in-built add_image_size functionality that Core provides out of the box.

add_image_size()

WordPress custom menu fields

I’ve packaged-up a plugin that I wrote a while ago for a project that I worked on which required a WordPress site’s menu items to have a separately addressable excerpt field which could override the linked page’s in-built excerpt.

The plugin that I’ve now released was half of the resolution to this requirement, which allows for simple programmatic field additions to the menu system.

Custom Menu Fields is available at the WordPress.org plugin repo.

To use this plugin all one needs to do is install and activate the plugin as normal and then include a snippet similar to below in their theme’s functions.php (or custom plugin code. Just be sure it loads earlier than the ‘init’ action!):

<?php
add_action('init', 'menu_excerpt__add_menu_field');
function menu_excerpt__add_menu_field() {
     if (!is_callable('bh_add_custom_menu_fields'))
         return;
     bh_add_custom_menu_fields(array(
         'excerpt' => array(
            'description' => 'Excerpt',
            'type' => 'textarea',
            )));
}
?>

Now you can get access to the ‘excerpt’ field by using the attribute on the menu variable you assign when you get the menu from WordPress.

e.g. to print the excerpt created above:

$menu = wp_nav_menu('theme_location' => 'your-theme-location-name', 'echo' => false);
print $menu->excerpt;

LOVESPAM

We all receive them, and we all ignore them, but sometimes they can reveal interesting things. e.g.

Don’t you love spams that come from a n00bie spammer who just paid for access to a “one-click spam everyone” tool, but didn’t read the documentation? What follows below is a true spam that I received today with no alterations whatsoever (excepting the headers which I’ve removed from the top of the message to try to reduce it’s size a bit – they have no bearing other than to detail how Google delivered it. The subject is an interesting one, because I didn’t know “Lucas” was in a “Star Wars legal fight”. However, the important bit to note about the email is the address they try to send me to.

Subject: Lucas loses Star Wars legal fight
Date: Sat, 30 Nov 2013 21:58:47 +0400
From: "::Pharmacy Exspress::"<gundar@bankvrn.ru>
Message-ID: <AA7F23F84E5C563AAD12B3ABC5FE9415@bankvrn.ru>
X-Priority: 3
X-Mailer: PHPMailer 5.1 (phpmailer.sourceforge.net)
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="------------09040400202040105050206"

This is a multi-part message in MIME format.
--------------09040400202040105050206
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="iso-8859-2"

 The new joy of ssex life!!!Solutions for providing a volcano power to you in bed. Your girl will be amused with how steady and wooden your bone-on is! This is a super pilule for every man!http://ssseexkxual.{dom}/?vdvbvivgvfvedj

--------------09040400202040105050206
Content-Transfer-Encoding: 7bit
Content-Type: text/html; charset="windows-1250"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body bgcolor="#ffffff" text="#000000">
    <CENTER><DIV style="margin: 0 auto;text-align:center;width:350px;"> 
<DIV>The new joy of ssex life!!!</DIV>
<hr width="200">
<FONT face="Tahoma" size="2">Solutions for providing a volcano power to you in bed. <br>Your girl will be amused with how steady and wooden your bone-on is! <br>This is a super pilule for every man!</FONT>
<hr width="200">
<A href="http://ssseexkxual.{dom}/?vdvbvivgvfvedj"><B>http://ssseexkxual.{dom}/?vdvbvivgvfvedj</B></A>
</DIV></CENTER>
  </body>
</html>

--------------09040400202040105050206--

Yes, folks, it really is the age-old “I’m too stupid to fill out all the replacements properly when mail-merging” problem. Only in this instance it successfully prevents me from looking a fool by clicking the link and signing up to whatever they’re advertising and not receiving anything other than a hefty bill from fraudsters. Wait, stop looking at me like that; it only happened that one time!