Write Your Own Plugin
As we mentioned in the previous section, plugin can access the Relno API and can be used to implement custom features. In this section, we will learn how to write a plugin.
Plugin Structure
A Relno plugin is a function that registers lifecycle hooks and custom sections. The function will be called by Relno when building the generator. Relno provides a function to provide typechecking for the plugin. In the following example, we create a plugin and export it as RelnoExamplePlugin
.
import {
defineRelnoPlugin,
} from "relno";
export const RelnoExamplePlugin = defineRelnoPlugin(async (generator) => {
// register lifecycle hooks and custom sections here
...
});
Register Lifecycle Hooks
Relno provides a set of lifecycle hooks that can be used to customize the behavior of Relno. You can register a lifecycle hook by calling the addHook
method of the generator. addHook
method takes two parameters: the lifecycle hook and the callback function. The callback function will be called when the lifecycle hook is triggered. The callback function will be called with the generator and the context as parameters. The context contains the information that is relevant to the lifecycle hook. For this example, we register a BeforeGenerate
hook. The BeforeGenerate
hook is triggered before the generator starts to generate the release note. The context contains the commits that are included in the release note.
export const RelnoExamplePlugin = defineRelnoPlugin(async (generator) => {
generator.addHook(
Lifecycle.BeforeGenerate,
async (generator: Generator, context: BeforeGenerateContext) => {
const commits = context.commits;
// do something with the commits object
},
);
});
Register Custom Sections
Relno provides custom section support. You can register a custom section by calling the addSection
method of the generator. addSection
method needs a section object as parameter. The section object controll the rendering logic of the section. For this example, we register a custom section named mySection
and render it simply. The parse
method of the section object will be called when the generator starts to parse mySection
section. sectionNode
parameter is the AST node parsed by parser. The parse
method should return a SectionNode
object. You should parse the children of the sectionNode
and return the result. Relno provides a parseNode
method to parse a node recursively. If the node is a section node, it will parse the node recursively. If the node is a text node, it will render the node and the expression syntax will be evaluated. The following example pass a variable named testVariable
to the parseNode
method.
import { Generator, Section, SectionNode, TemplateNodeType } from "relno";
class MySection extends Section {
public constructor() {
super("mySection");
}
public async parse(
generator: Generator,
sectionNode: SectionNode,
): Promise<SectionNode> {
const result: SectionNode = {
type: TemplateNodeType.Section,
name: sectionNode.name,
tags: sectionNode.tags,
children: [],
};
for (const child of sectionNode.children) {
result.children.push(
await generator.parseNode(generator, child, {
// pass variables, the variables will be available in the section
testVariable: "test",
}),
);
}
return result;
}
}
export const RelnoExamplePlugin = defineRelnoPlugin(async (generator) => {
generator.addSection(new MySection());
});