4. Your own pattern#

In this chapter, we write a pattern from scratch, and ship it in our own bundle. At the end, a badge appears on every element that carries the class pat-blicca.

4.1. A class-based pattern#

The file resources/pat-blicca/blicca.js contains a pattern in the current Patternslib style:

import { BasePattern } from "@patternslib/patternslib/src/core/basepattern";
import Parser from "@patternslib/patternslib/src/core/parser";
import registry from "@patternslib/patternslib/src/core/registry";

export const parser = new Parser("blicca");
parser.addArgument("color", "#0083be");
parser.addArgument("label", "Blicca override active");

class Pattern extends BasePattern {
    static name = "blicca";
    static trigger = ".pat-blicca";
    static parser = parser;

    init() {
        const badge = document.createElement("span");
        badge.textContent = `★ ${this.options.label}`;
        this.el.style.outline = `2px dashed ${this.options.color}`;
        this.el.append(badge);
    }
}

registry.register(Pattern);

Three things matter here:

  • The trigger is a plain CSS selector.

  • The Parser declares the options, and fills them from data-pat-blicca attributes, including inheritance from parent elements.

  • registry.register(Pattern) makes the registry scan the document, including content that arrives later through modals, pat-inject, or the folder contents view.

4.2. The bundle around it#

The webpack setup comes from @patternslib/dev, and the module federation plugin turns the bundle into a remote. The entry point resources/index.js only contains a dynamic import:

import("./overrides");

The dynamic import creates a split point. Webpack needs it to negotiate the shared dependencies with the Plone bundle at runtime, before our code runs.

The profile registers the built bundle in profiles/default/registry/bundles.xml:

<records
    interface="plone.base.interfaces.IBundleRegistry"
    prefix="plone.bundles/blicca-staticresourceoverride"
    >
  <value key="enabled">True</value>
  <value key="jscompilation">++plone++blicca.staticresourceoverride/bundles/blicca.staticresourceoverride-remote.min.js</value>
  <value key="depends">plone</value>
</records>

The depends value makes sure that the bundle loads after the host.

4.3. Exercise#

Start the watcher:

pnpm run watch

Edit a page, and give a paragraph the class pat-blicca in the TinyMCE source view. Save and observe the badge and the dashed outline.

Now pass options through the markup:

<p class="pat-blicca" data-pat-blicca="color: #d63384">With option.</p>

Then make it your own. Add a new option to the parser, and use it in init().

4.4. Checkpoint#

The badge and the outline appear on your paragraph. Changing data-pat-blicca changes the result.