Parse, inspect, transform, and serialize content through syntax trees
—
Processor configuration, data storage, and state management system with freezing capabilities for controlling processor modifications and sharing data across plugins.
Manages processor-specific data storage accessible to all plugins.
/**
* Get or set processor data
* @returns Complete data object when called with no arguments
*/
data(): Data;
/**
* Get specific data value
* @param key - Data key to retrieve
* @returns Value associated with the key
*/
data<Key extends keyof Data>(key: Key): Data[Key];
/**
* Set specific data key-value pair
* @param key - Data key to set
* @param value - Value to associate with key
* @returns Processor instance for chaining
*/
data<Key extends keyof Data>(key: Key, value: Data[Key]): Processor;
/**
* Replace entire data object
* @param dataset - New data object to set
* @returns Processor instance for chaining
*/
data(dataset: Data): Processor;Usage Examples:
import { unified } from "unified";
const processor = unified();
// Get all data
const allData = processor.data();
console.log(allData); // {}
// Set individual key-value pairs
processor
.data("author", "John Doe")
.data("version", "1.0.0")
.data("config", { strict: true });
// Get specific values
const author = processor.data("author"); // "John Doe"
const config = processor.data("config"); // { strict: true }
// Set entire data object
processor.data({
title: "My Document",
settings: { format: "html" },
metadata: { created: new Date() }
});
// Get complete data object
const data = processor.data();
// { title: "My Document", settings: {...}, metadata: {...} }Special data handling for parser and compiler settings via the settings key.
// Set settings via data method
processor.data("settings", {
bullet: "*",
emphasis: "_",
strong: "*"
});
// Access settings
const settings = processor.data("settings");
// Merge additional settings
const existingSettings = processor.data("settings") || {};
processor.data("settings", {
...existingSettings,
newSetting: "value"
});Plugins can access and modify processor data for cross-plugin communication.
function dataAwarePlugin(options = {}) {
// Access data during plugin setup
const existingConfig = this.data("config") || {};
// Merge plugin options with existing config
this.data("config", { ...existingConfig, ...options });
// Set plugin-specific data
this.data("pluginState", { initialized: true });
return function transformer(tree, file) {
// Access data during transformation
const config = this.data("config");
const pluginState = this.data("pluginState");
// Use data to guide transformation
if (config.strict && !pluginState.validated) {
// Perform strict validation
}
};
}
// Usage
processor
.use(dataAwarePlugin, { strict: true })
.use(anotherPlugin);Share data between plugins for coordinated behavior.
// First plugin sets shared data
function configPlugin(options) {
this.data("sharedConfig", {
theme: options.theme || "default",
features: options.features || []
});
}
// Second plugin uses shared data
function themedPlugin() {
return function transformer(tree, file) {
const config = this.data("sharedConfig");
if (config && config.theme === "dark") {
// Apply dark theme transformations
}
if (config && config.features.includes("syntax-highlight")) {
// Enable syntax highlighting
}
};
}
// Usage
processor
.use(configPlugin, {
theme: "dark",
features: ["syntax-highlight", "line-numbers"]
})
.use(themedPlugin);Freezes processor configuration to prevent further modifications.
/**
* Freeze processor to prevent configuration changes
* @returns The frozen processor instance
*/
freeze(): Processor;Usage Examples:
const processor = unified()
.use(someParser)
.use(someTransformer);
// Freeze the processor
const frozenProcessor = processor.freeze();
// Attempt to modify frozen processor (throws error)
try {
frozenProcessor.use(anotherPlugin);
} catch (error) {
console.log(error.message);
// "Cannot call `use` on a frozen processor..."
}
// Reading operations still work
const data = frozenProcessor.data(); // ✓ Works
const result = frozenProcessor.processSync("content"); // ✓ WorksCreate new unfrozen processors from existing configurations.
const baseProcessor = unified()
.use(commonParser)
.use(baseTransformer)
.freeze();
// Create variants without affecting base
const htmlProcessor = baseProcessor() // Call as function
.use(htmlCompiler);
const textProcessor = baseProcessor()
.use(textCompiler);
// Base processor remains unchanged
console.log(baseProcessor.frozen); // true
console.log(htmlProcessor.frozen); // false
console.log(textProcessor.frozen); // falseProcessors automatically freeze when processing methods are called.
const processor = unified()
.use(someParser)
.use(someTransformer);
console.log(processor.frozen); // false
// First processing call freezes the processor
const result = processor.parse("content");
console.log(processor.frozen); // true
// Subsequent modification attempts fail
try {
processor.use(anotherPlugin); // Throws error
} catch (error) {
console.log("Processor is now frozen");
}Configure processors based on runtime environment.
function createProcessor(env = "production") {
const processor = unified().use(baseParser);
// Environment-specific data
processor.data("environment", env);
processor.data("debug", env === "development");
if (env === "development") {
processor
.use(debugPlugin)
.use(validationPlugin, { strict: true });
} else {
processor
.use(optimizationPlugin)
.use(minificationPlugin);
}
return processor;
}
// Usage
const devProcessor = createProcessor("development");
const prodProcessor = createProcessor("production");Validate processor configuration before processing.
function validateConfig() {
return function validator(tree, file) {
const data = this.data();
// Check required configuration
if (!data.settings) {
throw new Error("Settings are required");
}
if (!data.settings.format) {
throw new Error("Output format must be specified");
}
// Validate configuration values
const validFormats = ["html", "markdown", "text"];
if (!validFormats.includes(data.settings.format)) {
throw new Error(`Invalid format: ${data.settings.format}`);
}
};
}
// Usage
processor
.use(configPlugin, { format: "html" })
.use(validateConfig)
.use(outputPlugin);Manage plugin-specific state across multiple transformations.
function statefulPlugin() {
// Initialize plugin state
this.data("pluginState", {
processedCount: 0,
cache: new Map(),
initialized: Date.now()
});
return function transformer(tree, file) {
const state = this.data("pluginState");
// Update state
state.processedCount++;
// Use cached results
const cacheKey = JSON.stringify(tree);
if (state.cache.has(cacheKey)) {
return state.cache.get(cacheKey);
}
// Process and cache result
const result = processTree(tree);
state.cache.set(cacheKey, result);
return result;
};
}"Cannot call \data` on a frozen processor"`undefinedhasOwnProperty)Install with Tessl CLI
npx tessl i tessl/npm-unified