Compiler Plugins

Plugins are a powerful feature in Nijor that allow you to define custom behavior at compile time. In fact, many core framework features—such as n:loop list rendering, inline on:event handling, and reactivity bindings—are built internally as compiler plugins. This design makes Nijor highly modular and extensible.

Using Plugins

To use a plugin, import its factory function and add it to the plugins array inside your project's nijor.config.js file:


        import compressPlugin from "@/plugins/compress.js";
        import analyticsPlugin from "@/plugins/analytics.js";

        export const plugins = [ 
            compressPlugin(), 
            analyticsPlugin() 
        ];
    

During the build phase, Nijor executes these plugins sequentially in the order they are defined inside the array.

Developing Custom Plugins

A Nijor compiler plugin is structured as an asynchronous factory function. It returns a secondary asynchronous function that receives the active compilation context and yields the modified component content and scripts.


        export default function customPlugin(pluginOptions) {

            return async function ({ document, scope, props, scripts, filename, module_type }) {
                // Custom compilation and DOM transformation logic goes here

                return {
                    name: "Custom Plugin Name",
                    body: document.body.innerHTML, // Yield the modified HTML
                    ...scripts                     // Yield the updated scripts
                };
            };
        
        }
    

Compilation Context Arguments

The plugin's execution handler receives a highly rich context object containing:

document: A JSDOM instance representing the component's parsed HTML DOM tree. You can use standard DOM APIs (e.g., querySelectorAll, setAttribute) to query and modify markup directly.

scope: A unique, randomized string identifier generated for the current component, layout, or page. This is useful for namespacing CSS or logic.

props: An array containing the parsed property attributes defined on the component's opening tag.

scripts: An object storing the generated JavaScript segments (see below).

filename: The absolute path of the file currently being compiled.

module_type: A string designating the current module classification. The value can be "component", "layout", or "page".

Manipulating Component Scripts

The scripts object contains three primary properties: main, global, and defer.

Best Practice: Avoid overwriting scripts.main or other script properties directly. Because they house compiler-generated bootstrap logic, overwriting them will break compilation output. Instead, always append your modifications:


        // Safely inject custom script behavior
        scripts.main += "// Additional custom compiler logic goes here;";
    

Under the Hood: Compiler Mechanics

To build robust plugins, it is helpful to understand how the Nijor compiler transforms a .nijor component. Internally, components are compiled into a structural initialization sequence:


        // Injected inside scripts.global
        const myComponent = new component(templateFn, callbackFn);
    

The Anatomy of Compiled Components

    scripts.global: Contains top-level declaration code, such as registering component initializers and importing external dependency scripts.

    templateFn: A function that runs whenever the template needs to render. It executes the code written inside your component's original <script> tag (except imports, which are lifted to the top level) and returns the generated markup.

    callbackFn: Executes immediately after the templateFn mounts the component's markup to the DOM, facilitating child component bootstrapping.

    scripts.defer: Dynamic script blocks that are executed inline inside the templateFn lifecycle scope.