Plugin
Each plugin is an npm module with a name in the format of textlint-plugin-<plugin-name>
.
For example, @textlint/textlint-plugin-markdown
is a textlint plugin.
Processor
Plugin has a Processor
that is required.
// index.js
export default {
Processor: require("./YourProcessor")
};
Processor
class defined pre/post process of the file and available file types.
textlint support .txt
and .md
by default. These are implemented as Processor
plugin.
Processor
class example code:
// TextProcessor.js
import { parse } from "txt-to-ast";
export default class TextProcessor {
constructor(options = {}) {
this.options = options;
// support "extension" option
this.extensions = options.extensions ? options.extensions : [];
}
// available ".ext" list
// user can add own custom extension as "extensions" option
availableExtensions() {
return [".txt", ".text"].concat(this.extensions);
}
// define pre/post process
// in other words, parse and generate process
processor(ext) {
return {
preProcess(text, filePath) {
// parsed result is an AST object
// AST is consist of TxtNode
// https://github.com/textlint/textlint/blob/master/docs/txtnode.md
return parse(text);
},
postProcess(messages, filePath) {
return {
messages,
filePath: filePath ? filePath : "<text>"
};
}
};
}
}
Processor
class should implement these methods.
availableExtensions(): string[]
It should return supported extension name list.
Notes:
textlint@10<= support static availableExtensions(): string[]
.
The static method is deprecated in textlint@11.
you should implement availableExtensions()
method as instance method.
processor(ext)
processor()
method should return an object that have preProcess
and postProcess
method.
preProcess(text, filePath)
preProcess
method should return TxtParentNode
object or { text: string, ast: TxtParentNode }
object.
Also, preProcess
method can return Promise<TxtParentNode> | Promise<{ text: string, ast: TxtParentNode }>
.
If you want to parse text asynchronous, please return an Promise object.
TxtParentNode
object is an Abstract Syntax Tree (AST) of the text.
You should check the AST using @textlint/ast-tester.
import { test, isTxtAST } from "@textlint/ast-tester";
// your implement
import yourParse from "your-parser";
// recommenced: test much pattern test
const AST = yourParse("This is text");
// Validate AST
test(AST); // if the AST is invalid, then throw Error
isTxtAST(AST); // true or false
If you want to know TxtParentNode
, see TxtAST interface documents.
text format
Target file(text format) -> AST(by your plugin) for Target file
If your plugin handle text format, you can just return a TxtParentNode
object.
class ExampleProcessor {
availableExtensions() {
return [".example"];
}
processor() {
return {
preProcess() {
return AST_OBJECT;
},
postProcess(messages, filePath) {
return {
filePath: filePath || "<example>",
messages
};
}
};
}
}
binary format
Target file(binary format) -> Intermediate text(by your plugin) -> AST(by your plugin) for Intermediate text
If your plugin handle intermediate text, you should return a { text: string, ast: TxtParentNode }
object.
textlint can not handle a binary format, and your plugin should return intermediate text for your AST.
class BinaryExampleProcessor {
availableExtensions() {
return [".binary-example"];
}
processor() {
return {
preProcess() {
return {
text: PASUDUE_TEXT,
ast: AST_OBJECT
};
},
postProcess(messages, filePath) {
return {
filePath: filePath || "<example>",
messages
};
}
};
}
}
For more details, see https://github.com/textlint/textlint/issues/649
postProcess(messages, filePath)
postProcess
method should return { messages, filePath }
.
Also, postProcess
method can return Promise<{ messages, filePath }>
.
filePath
argument may be undefined when text was input from stdin.
Plugin configuration
You can use Processor plugin in the same way a plugin.
{
"plugins": [
"<Processor Plugin>"
]
}
options
You can pass options to your plugin from .textlintrc.json
.
{
"plugins": {
"pluginName": processorOption
}
}
You can receive the processorOption
via constructor arguments.
export default class YourProcessor {
constructor(options) {
this.options = options; // <= processorOption!
}
// ...
}
:memo: Processor's option value is {}
(empty object) by default.
If not set plugin's option in .textlintrc.json
, textlint pass {}
as options
.
export default class YourProcessor {
constructor(options) {
this.options = options; // {}
}
// ...
}
Publishing
If you want to publish your textlint plugin, see following documents.
Package name convention
textlint plugin package naming should have textlint-plugin-
prefix.
textlint-plugin-<name>
@scope/textlint-plugin-<name>
- textlint supports Scoped packages
Example: @textlint/textlint-plugin-markdown
textlint user use it by setting following:
{
"plugins": {
"@textlint/markdown": true
}
}
Also, textlint user can set options to the plugin.
{
"plugins": {
"@textlint/markdown": {
"extensions": [".custom-ext"]
}
}
}
Keywords
You should add textlintplugin
to npm's keywords
{
"name": "textlint-plugin-format-name",
"keywords": [
"textlintplugin"
]
}
Plugin Example
(limited) XML plugin
For more plugins, See Processor Plugin List.
Built-in plugin
textlint has built-in plugins