Technical previewShare feedback

Search

Search documentation

Natural language plugins

Updated Nov 1, 2026

Natural-language plugins parse prose into nlcst and check or rewrite it. The checks report messages on the file and leave the text as it is. Reach them from Markdown through md.toNaturalLanguage or from HTML through html.toNaturalLanguage.

The tables list each option as Pipeline takes it, by its JSON key and type; each plugin struct's own fields and Rust types are on docs.rs.

nl.parse

Parses natural language into an nlcst tree of paragraphs, sentences, words and punctuation.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Smartypants::default())
    .with(nl::Stringify)
    .freeze()?
    .process("\"Hi\" -- she said...")?;
output.value
// “Hi” — she said…

Follows retext-english.

OptionTypeDefaultDescription
languageLanguageThe rules sentences and words are found by.

Language

The language nl.parse reads: parse-latin's rules, or parse-english's on top of them.

Takes "latin" | "english".

nl.equality

Warns about insensitive, inconsiderate wording.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Equality::default())
    .with(nl::Stringify)
    .freeze()?
    .process("Hey guys, the chairman is here.")?;
output.file.messages[0].reason
// Unexpected potentially insensitive use of `guys`, in somes cases `people`, ` …

Follows retext-equality.

OptionTypeDefaultDescription
ignorestring[] | nullnullPhrases not to warn about.
binaryboolean | nullnullWhether a phrase used next to its counterpart (he or she) is fine.

nl.passive

Warns about the passive voice.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Passive::default())
    .with(nl::Stringify)
    .freeze()?
    .process("The cake was eaten.")?;
output.file.messages[0].reason
// Unexpected use of the passive voice

Follows retext-passive.

OptionTypeDefaultDescription
ignorestring[] | nullnullParticiples not to warn about.

nl.readability

Warns about sentences too hard to read for a target age.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Readability { age: Some(12.0), ..Default::default() })
    .with(nl::Stringify)
    .freeze()?
    .process("The constitutionally mandated intergovernmental reconciliation procedures necessitate comprehensive multilateral deliberation.")?;
output.file.messages[0].reason
// Unexpected hard to read sentence, according to 6 out of 7 algorithms

Follows retext-readability.

OptionTypeDefaultDescription
agenumber | nullnullThe age of the target audience: 16 by default.
thresholdnumber | nullnullThe share of algorithms that must find a sentence too hard: 4/7 by default.
minWordsnumber | nullnullThe fewest words a sentence needs to be checked: 5 by default.

nl.repeatedWords

Warns about a word written twice in a row.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::RepeatedWords)
    .with(nl::Stringify)
    .freeze()?
    .process("It is the the best.")?;
output.file.messages[0].reason
// Unexpected repeated `the`, remove one occurrence

Follows retext-repeated-words.

No options.

nl.sentenceSpacing

Warns about the spaces between sentences: one by default.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::SentenceSpacing::default())
    .with(nl::Stringify)
    .freeze()?
    .process("One.  Two.")?;
output.file.messages[0].reason
// Unexpected 2 spaces between sentence, expected 1 space

Follows retext-sentence-spacing.

OptionTypeDefaultDescription
preferredSpacing | nullThe spacing expected between sentences: 1 or "space" (the default), 2 or "double-space", 0 or "newline".

Spacing

A spacing between sentences, as a count of spaces or by name.

Takes number | string.

nl.stringify

Serializes nlcst back into text.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Stringify)
    .freeze()?
    .process("Same text out.")?;
output.value
// Same text out.

Follows retext-stringify.

No options.

nl.smartypants

Turns straight quotes, dashes, dots and backticks into their typographic forms.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Smartypants::default())
    .with(nl::Stringify)
    .freeze()?
    .process("\"It's\" -- fine...")?;
output.value
// “It’s” — fine…

Follows retext-smartypants.

OptionTypeDefaultDescription
backticksBackticksTurn double backticks and double straight single quotes into double quotes; all turns single ones into single quotes too, and needs quotes: false.
closingQuotesQuoteCharacters | nullThe closing quotes to use: ” and ’ by default.
dashesDashesTurn two dashes into an em dash; oldschool and inverted treat three too.
ellipsesEllipsesTurn three dots into an ellipsis, with spaces between them or without.
openingQuotesQuoteCharacters | nullThe opening quotes to use: “ and ‘ by default.
quotesboolean | nulltrueTurn straight quotes into smart ones.

Backticks

Takes boolean | "all".

QuoteCharacters

The quote characters to use for double and single quotes.

OptionTypeDefaultDescription
doublestring
singlestring

Dashes

Takes boolean | "oldschool" | "inverted".

Ellipses

Takes boolean | "spaced" | "unspaced".

nl.quotes

Warns about quotes and apostrophes that are not the preferred kind, smart by default.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Quotes::default())
    .with(nl::Stringify)
    .freeze()?
    .process("He said \"hi\".")?;
output.file.messages[0].reason
// Unexpected straight quote `"`, expected `“`

Follows retext-quotes.

OptionTypeDefaultDescription
preferredQuoteStyle | nullThe style of quotes and apostrophes to prefer: smart by default.
smartstring[] | nullnullSmart quotes by nesting level, each one character or an opening and closing pair: ["“”", "‘’"] by default.
straightstring[] | nullnullStraight quotes by nesting level: ["\"", "'"] by default.

QuoteStyle

A style of quotes: straight (") or smart (“”).

Takes "smart" | "straight".

nl.contractions

Warns about missing or misplaced apostrophes in contractions.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::Contractions::default())
    .with(nl::Stringify)
    .freeze()?
    .process("Dont do that.")?;
output.file.messages[0].reason
// Unexpected missing apostrophe in `Dont`, expected `Don’t`

Follows retext-contractions.

OptionTypeDefaultDescription
allowLiteralsboolean | nullfalseAlso check contractions written as literals, such as “hasnt”.
straightboolean | nullfalseExpect straight apostrophes (') instead of smart ones (’).

nl.indefiniteArticle

Warns about a and an used before the wrong sound.

use textlane::{Processor, nl};

let output = Processor::new()
    .with(nl::Parse::default())
    .with(nl::IndefiniteArticle)
    .with(nl::Stringify)
    .freeze()?
    .process("It is a apple.")?;
output.file.messages[0].reason
// Unexpected article `a` before `apple`, expected `an`

Follows retext-indefinite-article.

No options.

Created with ❤ and Livemark