Data Manipulation
Transformers modify the document object tree. Use the onTransform hook to rename fields, normalize data types, or parse complex nested structures that aren't supported by the core parser.
Extend Texkit's capabilities with community plugins. Learn how to package a custom transformer, validator, or formatter for the wider ecosystem.
By Sarah Jenkins • Senior DevRel • October 24, 2023
Compose. Compile. Ship.
Texkit is designed to be extensible. The plugin API is built on Node.js, exposing a clear, functional contract for developers to hook into the document lifecycle. You don't need to understand the entire core engine to contribute — you only need to understand where your specific transformation fits.
At its core, the API is a collection of stage hooks. Each hook corresponds to a specific moment in the document pipeline: when it is parsed, when it is validated, when it is transformed, and when it is emitted.
Plugins typically fall into one of three architectural categories, each handling a specific responsibility in the pipeline.
Transformers modify the document object tree. Use the onTransform hook to rename fields, normalize data types, or parse complex nested structures that aren't supported by the core parser.
Validators ensure data integrity. Implement onValidate to run JSON Schema checks, custom business rules, or required field presence checks before the document is rendered.
Formatters handle the final output. Use onRender to inject custom HTML snippets, generate specific file formats like PDF or SVG, or perform post-processing on the rendered HTML.
Let's build a simple plugin that reads a CSV file embedded in a document, parses it into a JSON table, and makes it accessible to the template engine.
Create a new file named csv-transformer.js:
// csv-transformer.js
const fs = require('fs');
const { parse } = require('csv-parse/sync');
module.exports = {
name: 'csv-table-transformer',
version: '1.0.0',
// Hook into the transform stage
onTransform: async (ctx) => {
// Look for a frontmatter property named 'csvData'
if (!ctx.meta.csvData) return;
const filePath = ctx.meta.csvData;
// Check if the file exists locally
if (!fs.existsSync(filePath)) {
throw new Error(`CSV file not found at ${filePath}`);
}
// Parse the CSV content
const records = parse(fs.readFileSync(filePath, 'utf-8'), {
columns: true,
skip_empty_lines: true
});
// Attach the parsed data to the document context
ctx.document.tables = ctx.document.tables || {};
ctx.document.tables.csv = records;
}
};
texkit plugin:testBefore publishing, you must ensure your plugin doesn't break the pipeline. Texkit includes a dedicated testing harness.
Run the following command in your plugin directory:
This command spins up a sandbox environment, loads your plugin, and executes a suite of synthetic documents to verify that your hooks return valid results and handle edge cases (like missing files or malformed CSVs) gracefully.
Once your tests pass and your package.json is configured with the correct entry point, you are ready to publish.
Texkit plugins must follow a naming convention to ensure they are discoverable. All community plugins must use the texkit- prefix.
For example, a plugin named @my-org/my-awesome-plugin would be renamed to texkit-my-awesome-plugin for the public registry.
After publishing to npm, we recommend submitting your plugin to the official Texkit Community Plugin Registry. This is a curated list of vetted plugins that users can browse directly through the Texkit Cloud dashboard.
Submitting to the registry is free and helps your plugin get found by thousands of developers looking to extend Texkit's capabilities.