<commit_before># Creating Rules

Textlint's AST(Abstract Syntax Tree) is defined these pages.

- [txtnode.d.ts](./txtnode.d.ts)
- [txtnode.md](./txtnode.md)
    - If you want to know AST of a text, use [Online Parsing Demo](./txtnode.md#online-parsing-demo)

Each rules are represented by a object with several properties.
The properties are equivalent to AST node types from TxtNode.

The basic source code format for a rule is:

```js
/**
 * @param {RuleContext} context
 */
module.exports = function (context) {
    // rule object
    var exports = {};
    exports[context.Syntax.Document] = function (node) {
    };
    exports[context.Syntax.Paragraph] = function (node) {
    };
    exports[context.Syntax.Str] = function (node) {
        var text = context.getSource(node);
        if(/found wrong use-case/.test.(text){
            // report error
            context.report(node, new context.RuleError("found wrong"));
        }
    };
    exports[context.Syntax.Break] = function (node) {
    };
    return exports;
};
```

If your rule wants to know when an `Str` node is found in the AST, then add a method called `context.Syntax.Str`, such as:

```js
module.exports = function (context) {
    var exports = {};
    exports[context.Syntax.Str] = function (node) {
        // this method is called
    };
    return exports;
};
```

By default, the method matching a node name is called during the traversal when the node is first encountered(This is called **Enter**), on the way down the AST.

You can also specify to visit the node on the other side of the traversal, as it comes back up the tree(This is called **Leave**), but adding `:exit` to the end of the node type, such as:


```js
module.exports = function (context) {
    var exports = {};
    exports[context.Syntax.Str + ":exit"] = function (node) {
        // this method is called
    };
    return exports;
};
```

[visualize-txt-traverse](https://github.com/azu/visualize-txt-traverse "azu/visualize-txt-traverse") help you better understand this traversing.

![gif visualize-txt-traverse](http://gyazo.com/155c68f0f9ff35e0a549d655a787c01e.gif)

**related information:**

- [azu/visualize-txt-traverse](https://github.com/azu/visualize-txt-traverse "azu/visualize-txt-traverse")
- [textlint/txt-ast-traverse](https://github.com/textlint/txt-ast-traverse "textlint/txt-ast-traverse")
- [estools/estraverse](https://github.com/estools/estraverse "estools/estraverse")

## RuleContext

RuleContext object has following property:

- `Syntax.*` is const values of [TxtNode type](./txtnode.md).
    - e.g.) `context.Syntax.Str`
    - [lib/parser/union-syntax.js](../lib/parser/union-syntax.js)
- `RuleError(<message>)` is like Error object.
    - e.g.) `new context.RuleError("found rule error")`
- `report(<node>, <ruleError>)` is a method reports a message from one of the rules.
    - e.g.) `context.report(node, new context.RuleError("found rule error"));`
- `getSource(<node>)`  is a method gets the source code for the given node.
    - e.g.) `context.getSource(node); // => "text"`
- `getFilePath()` return file path that is linting target.
    - e.g.) `context.getFilePath(): // => /path/to/file.md or undefined` 

See also [Working with Rules](http://eslint.org/docs/developer-guide/working-with-rules.html "Working with Rules") on ESLint.

## Report error

You will use mainly method is `context.report()`, which publishes a error (defined in each rules).

For example:

```js
module.exports = function (context) {
    var exports = {};
    exports[context.Syntax.Str] = function (node) {
        // get source code of this `node`
        var text = context.getSource(node);
        if(/found wrong use-case/.test.(text){
            // report error
            context.report(node, new context.RuleError("found wrong"));
        }
    };
    return exports;
};
```

## Example: creating `no-todo` rules.

This example aim to found `- [ ]` and `todo:` texts.

Rule file name is equal to rule ID(i.e., no-todo.js for rule ID no-todo).

File Name: `no-todo.js`

```js
"use strict"
/**
 * @param {RuleContext} context
 */
module.exports = function (context) {
    var exports = {};
    // When `node`'s type is `Str` come, call this callback.
    /*
    e.g.)
        # Header
<commit_msg>docs(async): add async example<commit_after># Creating Rules

Textlint's AST(Abstract Syntax Tree) is defined these pages.

- [txtnode.d.ts](./txtnode.d.ts)
- [txtnode.md](./txtnode.md)
    - If you want to know AST of a text, use [Online Parsing Demo](./txtnode.md#online-parsing-demo)

Each rules are represented by a object with several properties.
The properties are equivalent to AST node types from TxtNode.

The basic source code format for a rule is:

```js
/**
 * @param {RuleContext} context
 */
module.exports = function (context) {
    // rule object
    var exports = {};
    exports[context.Syntax.Document] = function (node) {
    };
    exports[context.Syntax.Paragraph] = function (node) {
    };
    exports[context.Syntax.Str] = function (node) {
        var text = context.getSource(node);
        if(/found wrong use-case/.test.(text){
            // report error
            context.report(node, new context.RuleError("found wrong"));
        }
    };
    exports[context.Syntax.Break] = function (node) {
    };
    return exports;
};
```

If your rule wants to know when an `Str` node is found in the AST, then add a method called `context.Syntax.Str`, such as:

```js
module.exports = function (context) {
    var exports = {};
    exports[context.Syntax.Str] = function (node) {
        // this method is called
    };
    return exports;
};
```

By default, the method matching a node name is called during the traversal when the node is first encountered(This is called **Enter**), on the way down the AST.

You can also specify to visit the node on the other side of the traversal, as it comes back up the tree(This is called **Leave**), but adding `:exit` to the end of the node type, such as:


```js
module.exports = function (context) {
    var exports = {};
    exports[context.Syntax.Str + ":exit"] = function (node) {
        // this method is called
    };
    return exports;
};
```

[visualize-txt-traverse](https://github.com/azu/visualize-txt-traverse "azu/visualize-txt-traverse") help you better understand this traversing.

![gif visualize-txt-traverse](http://gyazo.com/155c68f0f9ff35e0a549d655a787c01e.gif)

**related information:**

- [azu/visualize-txt-traverse](https://github.com/azu/visualize-txt-traverse "azu/visualize-txt-traverse")
- [textlint/txt-ast-traverse](https://github.com/textlint/txt-ast-traverse "textlint/txt-ast-traverse")
- [estools/estraverse](https://github.com/estools/estraverse "estools/estraverse")

## RuleContext

RuleContext object has following property:

- `Syntax.*` is const values of [TxtNode type](./txtnode.md).
    - e.g.) `context.Syntax.Str`
    - [lib/parser/union-syntax.js](../lib/parser/union-syntax.js)
- `RuleError(<message>)` is like Error object.
    - e.g.) `new context.RuleError("found rule error")`
- `report(<node>, <ruleError>)` is a method reports a message from one of the rules.
    - e.g.) `context.report(node, new context.RuleError("found rule error"));`
- `getSource(<node>)`  is a method gets the source code for the given node.
    - e.g.) `context.getSource(node); // => "text"`
- `getFilePath()` return file path that is linting target.
    - e.g.) `context.getFilePath(): // => /path/to/file.md or undefined` 

See also [Working with Rules](http://eslint.org/docs/developer-guide/working-with-rules.html "Working with Rules") on ESLint.

## Report error

You will use mainly method is `context.report()`, which publishes a error (defined in each rules).

For example:

```js
module.exports = function (context) {
    var exports = {};
    exports[context.Syntax.Str] = function (node) {
        // get source code of this `node`
        var text = context.getSource(node);
        if(/found wrong use-case/.test.(text){
            // report error
            context.report(node, new context.RuleError("found wrong"));
        }
    };
    return exports;
};
```

### How to write async task in the rule

Return Promise object in the node function and the rule work asynchronously.

```js
export default function (context) {
    return {
        [Syntax.Str](node){
            // textlint wait for resolved the promise.
            return new Promise((resolve, reject) => {
                // async task
            });
        }
    }
}
```

## Example: creating `no-todo` rules.

This example aim to found `- [ ]` and `todo:` texts.

Rule file name is equal to rule ID(i.e., no-todo.js for rule ID no-todo).

File Name: `no-todo.js`

```js
"use strict"
/**
 * @param {RuleContext} context
 */
module.exports = function (context) {
    var exports = {};
    // When `node`'s type is `Str` come, call this callback.
    /*
    e.g.)
        # Header

{'fraction_non_alphanumeric': 0.1433687744823727, 'fraction_numerical': 0.004700615556799104, 'mean_word_length': 3.0897025171624715, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 16, 'https://': 8, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3700943', 'n_tokens_mistral': 2836, 'n_tokens_neox': 2737, 'n_words': 862}