<commit_before># Customization

## Tags
The [`TagDefinition`](../src/def.js) class defines the properties of a tag type. The parser uses this to determine how to process a tag.

`BBTagDef` extends `TagDefinition` to make simple BBCode tags easier to define.
```js
import {BBTagDef} from 'bbcode/bbcode';

let tag1 = new BBTagDef( 'b' );  // [b][/b]
```
Or without the convenience class `BBTagDef`.
```js
import {BBTagFrmtr} from 'bbcode/bbcode';
import {TagDefinition} from 'bbcode/markup-def';

let tag = new TagDefinition( new BBTagFrmtr( 'b' ) ); // [b][/b]
```

### Children
The children parameter should be an array of tag identifiers. An empty array means no child tags are allowed (parsed) and `null` allows all (default).
```js
new BBTagDef( 'b', [] );    // none: [b][i]...[/i][/b] => format: [b]...[/b]
new BBTagDef( 'b', ['i'] ); // allow i:  [b][i][/i][/b] => format: [b][i][/i][/b]
```

### Attributes
The attributes parameter should be an array of definitions (`AttributeDefinition`). The default is all allowed (`null`) like children.
```js
import {AttributeDefinition} from 'bbcode/markup-def';
import {BBAttrFrmtr, BBTagDef} from 'bbcode/bbcode';

let attribute = new AttributeDefinition( new BBAttrFrmtr( 'url' ) ); // an attribute named 'url'

let tag = new BBTagDef( 'url', null, [attribute] );
```
In BBCode (formatting and parsing) any tag with an attribute with the same name can _self-attribute_: `[url url=""][/url]` or `[url=""][/url]`


### Formatters
Formatters transform the parsed result to a target format. The `BBTagDef` above automatically creates a simple BBCode formatter. 
```js
import {HtmlTagFrmtr} from 'bbcode/html';
import {BBTagFrmtr} from 'bbcode/bbcode';
import {TagDefinition} from 'bbcode/markup-def';

let tag = new TagDefinition( [new BBTagFrmtr( 'url' ), new HtmlTagFormatter( 'a' )] ); // change `[url]` to `<a>`
```

There are a number of existing formatters for transforming bbcode to html in [bb-html](../src/bb-html.js).

#### Attribute Formatters
* `StyleFrmtr` is used when a bbcode attribute maps to a CSS style value. The identifier (first parameter) is the CSS property.
```js
// color="red" -> style="background-color: red;"
new AttributeDefinition( [new BBAttrFrmtr( 'color' ), new StyleFrmtr( 'background-color' )] );
```
* `StyleNumFrmtr` is a specialized version of `StyleFrmtr` but to use with styles that are numbers with units. 
```js
// indent="#" -> style="text-indent: #px;"
new AttributeDefinition( [new BBAttrFrmtr( 'indent' ), new StyleNumFrmtr( 'text-indent', 'px' )] );
```
* `AttrTagFrmtr` creates a temporary tag from the attribute value to be added as the top child to the parent tag. Pass it a `TagDefinition` and the attribute value will be inserted into this temporary tag.
* `ClassFrmtr` takes the attribute value and adds it to the html `class` attribute.

#### Tag Formatters
* `CToATagFrmtr` checks for a required attribute and tries to fill it in with any text content when missing. This makes tags like `[url]link[/url]` and `[url=link]text[/url]` possible.
* `AttrJoinTagFrmtr` joins the given attribute value with the tag name to create a new tag in its place. This is used by the header tag: `[header=3]` maps to `<h3>`


#### Formatter Properties
Constant attributes that will be applied during the transform.
```js
import {CssClass, CssProp} from 'bbcode/bb-html';
import {HtmlTagFrmtr} from 'bbcode/html';
import {BBTagFrmtr} from 'bbcode/bbcode';

// <tag-id class="classes here"></tag-id>
new HtmlTagFrmtr( 'tag-id', { attributes: new CssClass( 'classes', 'here' ) } ); 

// <tag-id style="text-transform: capitalize;" class="some-class"></tag-id>
new HtmlTagFrmtr( 'tag-id', { attributes: [new CssProp( 'text-transform' ), new CssClass( 'some-class' ) } );

// [tag-id attr="value"]
new BBTagFrmtr( 'tag-id', { attributes: { identifier: 'attr', value: 'value' } } );
```
Styles and classes may be set directly like the last example sets `attr` to `value`; `CssProp` and `CssClass` help prevent overwriting existing values.

**Void tags** are tags that have no children and no closing tag (like `<img>`). Set the `is_void` property to true and the tag will be rendered as such.
```js
// [not-void][/not-void] -> <void>
new TagDefinition( [new BBTagFrmtr( 'not-void' ), new HtmlTagFrmtr( 'void', { is_void: true } )] );
```
If the tag was originally not void (like the bbcode tag above) it may contain children. By default those children will be formatted and appear as siblings. To prevent this set `void_children` to `false`.

## Validators

[Validators](../src/validator.js) are used during parse to validate identifiers and values. The `char` method is called for each character individually and if the parse action is successful the `string` method is used to do a complete validation of the value.
* `Validator` is the basic validator and always succeeds.
* `Invalidator` is the opposite of `Validator`
* `FallbackValidator` takes a primary and secondary validator. If the primary fails it attemps the secondary.
* `CompositeValidator` contains any number of validators and all must validate successfully or validation fails.
* `RegexValidator` takes and uses a regex in `string`. `char` always passes.
* `IdentifierValidator` allows numbers (0-9) letters (a-z, A-Z) and hyphen (-).<commit_msg>doc: typo<commit_after># Customization

## Tags
The [`TagDefinition`](../src/def.js) class defines the properties of a tag type. The parser uses this to determine how to process a tag.

`BBTagDef` extends `TagDefinition` to make simple BBCode tags easier to define.
```js
import {BBTagDef} from 'bbcode/bbcode';

let tag1 = new BBTagDef( 'b' );  // [b][/b]
```
Or without the convenience class `BBTagDef`.
```js
import {BBTagFrmtr} from 'bbcode/bbcode';
import {TagDefinition} from 'bbcode/markup-def';

let tag = new TagDefinition( new BBTagFrmtr( 'b' ) ); // [b][/b]
```

### Children
The children parameter should be an array of tag identifiers. An empty array means no child tags are allowed (parsed) and `null` allows all (default).
```js
new BBTagDef( 'b', [] );    // none: [b][i]...[/i][/b] => format: [b]...[/b]
new BBTagDef( 'b', ['i'] ); // allow i:  [b][i][/i][/b] => format: [b][i][/i][/b]
```

### Attributes
The attributes parameter should be an array of definitions (`AttributeDefinition`). The default is all allowed (`null`) like children.
```js
import {AttributeDefinition} from 'bbcode/markup-def';
import {BBAttrFrmtr, BBTagDef} from 'bbcode/bbcode';

let attribute = new AttributeDefinition( new BBAttrFrmtr( 'url' ) ); // an attribute named 'url'

let tag = new BBTagDef( 'url', null, [attribute] );
```
In BBCode (formatting and parsing) any tag with an attribute with the same name can _self-attribute_: `[url url=""][/url]` or `[url=""][/url]`


### Formatters
Formatters transform the parsed result to a target format. The `BBTagDef` above automatically creates a simple BBCode formatter. 
```js
import {HtmlTagFrmtr} from 'bbcode/html';
import {BBTagFrmtr} from 'bbcode/bbcode';
import {TagDefinition} from 'bbcode/markup-def';

let tag = new TagDefinition( [new BBTagFrmtr( 'url' ), new HtmlTagFormatter( 'a' )] ); // change `[url]` to `<a>`
```

There are a number of existing formatters for transforming bbcode to html in [bb-html](../src/bb-html.js).

#### Attribute Formatters
* `StyleFrmtr` is used when a bbcode attribute maps to a CSS style value. The identifier (first parameter) is the CSS property.
```js
// color="red" -> style="background-color: red;"
new AttributeDefinition( [new BBAttrFrmtr( 'color' ), new StyleFrmtr( 'background-color' )] );
```
* `StyleNumFrmtr` is a specialized version of `StyleFrmtr` but to use with styles that are numbers with units. 
```js
// indent="#" -> style="text-indent: #px;"
new AttributeDefinition( [new BBAttrFrmtr( 'indent' ), new StyleNumFrmtr( 'text-indent', 'px' )] );
```
* `AttrTagFrmtr` creates a temporary tag from the attribute value to be added as the top child to the parent tag. Pass it a `TagDefinition` and the attribute value will be inserted into this temporary tag.
* `ClassFrmtr` takes the attribute value and adds it to the html `class` attribute.

#### Tag Formatters
* `CToATagFrmtr` checks for a required attribute and tries to fill it in with any text content when missing. This makes tags like `[url]link[/url]` and `[url=link]text[/url]` possible.
* `AttrJoinTagFrmtr` joins the given attribute value with the tag name to create a new tag in its place. This is used by the header tag: `[header=3]` maps to `<h3>`


#### Formatter Properties
Constant attributes that will be applied during the transform.
```js
import {CssClass, CssProp} from 'bbcode/bb-html';
import {HtmlTagFrmtr} from 'bbcode/html';
import {BBTagFrmtr} from 'bbcode/bbcode';

// <tag-id class="classes here"></tag-id>
new HtmlTagFrmtr( 'tag-id', { attributes: new CssClass( 'classes', 'here' ) } ); 

// <tag-id style="text-transform: capitalize;" class="some-class"></tag-id>
new HtmlTagFrmtr( 'tag-id', { attributes: [new CssProp( 'text-transform' ), new CssClass( 'some-class' ) } );

// [tag-id attr="value"]
new BBTagFrmtr( 'tag-id', { attributes: { identifier: 'attr', value: 'value' } } );
```
Styles and classes may be set directly like the last example sets `attr` to `value`; `CssProp` and `CssClass` help prevent overwriting existing values.

**Void tags** are tags that have no children and no closing tag (like `<img>`). Set the `is_void` property to true and the tag will be rendered as such.
```js
// [not-void][/not-void] -> <void>
new TagDefinition( [new BBTagFrmtr( 'not-void' ), new HtmlTagFrmtr( 'void', { is_void: true } )] );
```
If the tag was originally not void (like the bbcode tag above) it may contain children. By default those children will be formatted and appear as siblings. To prevent this set `void_children` to `false`.

## Validators

[Validators](../src/validator.js) are used during parse to validate identifiers and values. The `char` method is called for each character individually and if the parse action is successful the `string` method is used to do a complete validation of the value.
* `Validator` is the basic validator and always succeeds.
* `Invalidator` is the opposite of `Validator`
* `FallbackValidator` takes a primary and secondary validator. If the primary fails it attempts the secondary.
* `CompositeValidator` contains any number of validators and all must validate successfully or validation fails.
* `RegexValidator` takes and uses a regex in `string`. `char` always passes.
* `IdentifierValidator` allows numbers (0-9) letters (a-z, A-Z) and hyphen (-).
{'fraction_non_alphanumeric': 0.13632498819083608, 'fraction_numerical': 0.000944733112895607, 'mean_word_length': 4.691397849462366, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 29, 'https://': 0, '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': '3466065', 'n_tokens_mistral': 3306, 'n_tokens_neox': 3245, 'n_words': 1341}