Skip to content

Latest commit

 

History

History
287 lines (217 loc) · 7.38 KB

plugin.md

File metadata and controls

287 lines (217 loc) · 7.38 KB
id title
plugin
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 #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!
    }
    // ...
}

📝 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>

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