Skip to Content
API Referenceformat-lint

@stesura/format-lint

A lint for how a document is built: formatting that belongs in styles, duplicate and broken styles, empty paragraphs used as spacing. The rules, guarantees and setup are in the Format cleanup guide. The panel and status bar are in @stesura/format-lint-react.

Plugin

formatLintPlugin

Recollects format suggestions a debounce after each doc change and keeps them, ranges mapped, in plugin state for the panel and the status bar. Root editors only: sub-editors’ content is part of the root doc.

Parameters:
NameTypeDefault
__0FormatLintPluginOptions
Returns:
Plugin<FormatLintPluginState>

FormatLintPluginOptions

NameTypeDefault
tolerancePxnumber

px; indents and spacing within this of a style’s value count as equal.

coverageThresholdnumber

Share (0–1) of a style’s paragraphs or text above which a value belongs in the style.

minClusterSizenumber

Paragraphs sharing one delta before it becomes a style.

colorTolerancenumber

CIEDE2000; a fixed colour closer than this to a theme colour is a near match (FMT-26).

rulesFormatRuleId[]

Only these rules run. Default: all.

ignorestring[]

Suggestion ids to drop from results and from “apply all”.

debounceMsnumber

Quiet time after the last edit before recollecting. Default 600 ms.

Engine

The engine is pure: state in, suggestions or a transaction out. Use it without the plugin to report on an imported document or from a server.

collectFormatSuggestions

Every suggestion for the document, in pass order. Each rule sees the doc as it is; what applying one changes for another is settled at apply time.

Parameters:
NameTypeDefault
stateOrDocEditorState | Node
optionsFormatLintOptions
Returns:
FormatSuggestion[]

applyFormatSuggestionsTr

Runs the selected fixes in ONE transaction, for composing; the command, applyFormatSuggestionsBulk, runs them in chunks. The engine recollects pass by pass on the transaction’s doc rather than trusting cached transforms, so ids are matched against what still applies; the rest come back as gone. "all" applies every fixable error and warning, plus hints only for rules named in options.rules.

Parameters:
NameTypeDefault
selectionstring[] | "all"
optionsApplyFormatOptions
Returns:
TransactionFn

getFormatSummary

The summary an applyFormatSuggestionsTr left on its transaction.

Parameters:
NameTypeDefault
trTransaction
Returns:
FormatSummary | undefined

DEFAULT_FORMAT_LINT_OPTIONS

Defaults read off the 2026-10-19 corpus survey (docs/partially-executed/format-cleanup-plan.md, Phase 0): indent drift below 3 px is cm/twip rounding, real choices start above 6 px; mark coverage is bimodal, with almost nothing between 60% and 90%.

NameTypeDefault
tolerancePxnumber

px; indents and spacing within this of a style’s value count as equal.

coverageThresholdnumber

Share (0–1) of a style’s paragraphs or text above which a value belongs in the style.

minClusterSizenumber

Paragraphs sharing one delta before it becomes a style.

colorTolerancenumber

CIEDE2000; a fixed colour closer than this to a theme colour is a near match (FMT-26).

rulesFormatRuleId[]

Only these rules run. Default: all.

ignorestring[]

Suggestion ids to drop from results and from “apply all”.

Categories

The panel groups rules into categories, and “Fix all” can apply only some of them through ApplyFormatOptions.only.

FORMAT_RULE_CATEGORIES

Each rule’s category, as the panel groups them.

NameTypeDefault
FMT-1FormatCategory
FMT-2FormatCategory
FMT-3FormatCategory
FMT-4FormatCategory
FMT-5FormatCategory
FMT-10FormatCategory
FMT-11FormatCategory
FMT-12FormatCategory
FMT-13FormatCategory
FMT-15FormatCategory
FMT-16FormatCategory
FMT-17FormatCategory
FMT-18FormatCategory
FMT-19FormatCategory
FMT-20FormatCategory
FMT-21FormatCategory
FMT-22FormatCategory
FMT-23FormatCategory
FMT-24FormatCategory
FMT-25FormatCategory
FMT-26FormatCategory

FORMAT_CATEGORIES

Categories in the order the panel lists them.

NameTypeDefault
lengthnumber
toString() => string
toLocaleString{ (): string; (locales: string | string[], options?: (NumberFormatOptions & DateTimeFormatOptions) | undefined): string; }
concat{ (...items: ConcatArray<FormatCategory>[]): FormatCategory[]; (...items: (FormatCategory | ConcatArray<FormatCategory>)[]): FormatCategory[]; }
join(separator?: string | undefined) => string
slice(start?: number | undefined, end?: number | undefined) => FormatCategory[]
indexOf(searchElement: FormatCategory, fromIndex?: number | undefined) => number
lastIndexOf(searchElement: FormatCategory, fromIndex?: number | undefined) => number
every{ <S extends FormatCategory>(predicate: (value: FormatCategory, index: number, array: readonly FormatCategory[]) => value is S, thisArg?: any): this is readonly S[]; (predicate: (value: FormatCategory, index: number, array: readonly FormatCategory[]) => unknown, thisArg?: any): boolean; }
some(predicate: (value: FormatCategory, index: number, array: readonly FormatCategory[]) => unknown, thisArg?: any) => boolean
forEach(callbackfn: (value: FormatCategory, index: number, array: readonly FormatCategory[]) => void, thisArg?: any) => void
map<U>(callbackfn: (value: FormatCategory, index: number, array: readonly FormatCategory[]) => U, thisArg?: any) => U[]
filter{ <S extends FormatCategory>(predicate: (value: FormatCategory, index: number, array: readonly FormatCategory[]) => value is S, thisArg?: any): S[]; (predicate: (value: FormatCategory, index: number, array: readonly FormatCategory[]) => unknown, thisArg?: any): FormatCategory[]; }
reduce{ (callbackfn: (previousValue: FormatCategory, currentValue: FormatCategory, currentIndex: number, array: readonly FormatCategory[]) => FormatCategory): FormatCategory; (callbackfn: (previousValue: FormatCategory, currentValue: FormatCategory, currentIndex: number, array: readonly FormatCategory[]) => FormatCategory...
reduceRight{ (callbackfn: (previousValue: FormatCategory, currentValue: FormatCategory, currentIndex: number, array: readonly FormatCategory[]) => FormatCategory): FormatCategory; (callbackfn: (previousValue: FormatCategory, currentValue: FormatCategory, currentIndex: number, array: readonly FormatCategory[]) => FormatCategory...
find{ <S extends FormatCategory>(predicate: (value: FormatCategory, index: number, obj: readonly FormatCategory[]) => value is S, thisArg?: any): S | undefined; (predicate: (value: FormatCategory, index: number, obj: readonly FormatCategory[]) => unknown, thisArg?: any): FormatCategory | undefined; }
findIndex(predicate: (value: FormatCategory, index: number, obj: readonly FormatCategory[]) => unknown, thisArg?: any) => number
entries() => ArrayIterator<[number, FormatCategory]>
keys() => ArrayIterator<number>
values() => ArrayIterator<FormatCategory>
includes(searchElement: FormatCategory, fromIndex?: number | undefined) => boolean
flatMap<U, This = undefined>(callback: (this: This, value: FormatCategory, index: number, array: FormatCategory[]) => U | readonly U[], thisArg?: This | undefined) => U[]
flat<A, D extends number = 1>(this: A, depth?: D | undefined) => FlatArray<A, D>[]
at(index: number) => FormatCategory | undefined
__@iterator@6565() => ArrayIterator<FormatCategory>
__@unscopables@6567{ readonly [x: number]: boolean | undefined; readonly length?: boolean; toString?: boolean; toLocaleString?: boolean; concat?: boolean; join?: boolean; slice?: boolean; indexOf?: boolean; lastIndexOf?: boolean; ... 17 more ...; readonly [Symbol.unscopables]?: boolean; }

rulesInCategories

The rules of the given categories, e.g. for ApplyFormatOptions.only.

Parameters:
NameTypeDefault
categoriesReadonlySet<FormatCategory>
Returns:
FormatRuleId[]

Commands

applyFormatSuggestions

Applies suggestions in one undo step, with formatApplyOptions, in chunks on a large document (a bulk command: dispatch it through the editor, or runBulkCommand headless). By default refuses while track changes is on (see trackChangesBlockedReason); force applies anyway.

Parameters:
NameTypeDefault
selectionstring[] | "all"
optionsApplyFormatOptions
Returns:
Command

refreshFormatSuggestions

Collects now instead of after the debounce, e.g. for a Refresh button. Not an undo step.

Parameters:
This function does not accept any parameters.
Returns:
Command

ignoreFormatSuggestion

Dismisses a suggestion for this document, for every collaborator.

Parameters:
NameTypeDefault
idstring
Returns:
Command

unignoreFormatSuggestion

Brings one dismissed suggestion back.

Parameters:
NameTypeDefault
idstring
Returns:
Command

clearFormatLintIgnore

Brings dismissed suggestions back.

Parameters:
This function does not accept any parameters.
Returns:
Command

getFormatLintIgnore

The doc’s dismissed suggestion ids (doc.attrs.formatLintIgnore).

Parameters:
NameTypeDefault
stateEditorState
Returns:
string[]

trackChangesBlockedReason

Why applying is refused right now: tracked formatting changes by the hundred.

Parameters:
NameTypeDefault
stateEditorState
Returns:
string | null

Agent issues

The IssueProvider that hands format-lint’s suggestions to the agent’s issue tools; pass it to createIssueTools in @stesura/ai.

formatLintIssues

Format-lint’s suggestions, for createIssueTools. Fixes are direct (styles, lists and direct formatting are document configuration) and, like the panel’s “apply”, refused while track changes is on.

NameTypeDefault
sourcestring
collect(state: EditorState) => AiIssue[]

The current findings, in document order.

apply(state: EditorState, fixes: readonly AiIssueFix[]) => AiIssueApplyResult

Applies fixes to issues collect returns. Tracked fixes come back as a plain edit the caller turns into suggestions; direct ones as the change itself. Omitted: nothing is fixable.

Types

FormatSuggestion

NameTypeDefault
idstring

Stable across re-runs: hash of rule and scope.

ruleFormatRuleId
severityFormatSeverity
guaranteeFormatGuarantee
scopeFormatScope
messagestring
changesFormatChanges
fixableboolean

False for report-only findings (no automatic fix).

ranges{ from: number; to: number; }[]

Doc ranges for decorations and go-to; empty for stylesheet-level findings.

detailFormatDetail

FormatDetail

What a finding is about, for a precise title: the one field it touches (absent when it spans several) and, for FMT-11, which of its checks found it.

NameTypeDefault
fieldFormatField
kind"field" | "near" | "cluster" | "snap"

FormatField

A paragraph field, or a character attr FMT-21 moves into a style.

NameTypeDefault
toString() => string
charAt(pos: number) => string
charCodeAt(index: number) => number
concat(...strings: string[]) => string
indexOf(searchString: string, position?: number | undefined) => number
lastIndexOf(searchString: string, position?: number | undefined) => number
localeCompare{ (that: string): number; (that: string, locales?: string | string[] | undefined, options?: CollatorOptions | undefined): number; (that: string, locales?: LocalesArgument, options?: CollatorOptions | undefined): number; }
match{ (regexp: string | RegExp): RegExpMatchArray | null; (matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; }
replace{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: { ...; }, replaceValue: string): string; (searchValue: { ...; }, replacer: (substring: string, ...args: any[]) => string): string; }
slice(start?: number | undefined, end?: number | undefined) => string
split{ (separator: string | RegExp, limit?: number | undefined): string[]; (splitter: { [Symbol.split](string: string, limit?: number | undefined): string[]; }, limit?: number | undefined): string[]; }
substring(start: number, end?: number | undefined) => string
toLowerCase() => string
toLocaleLowerCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
toUpperCase() => string
toLocaleUpperCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
trim() => string
lengthnumber
substr(from: number, length?: number | undefined) => string
valueOf() => string
codePointAt(pos: number) => number | undefined
includes(searchString: string, position?: number | undefined) => boolean
endsWith(searchString: string, endPosition?: number | undefined) => boolean
normalize{ (form: "NFC" | "NFD" | "NFKC" | "NFKD"): string; (form?: string | undefined): string; }
repeat(count: number) => string
startsWith(searchString: string, position?: number | undefined) => boolean
anchor(name: string) => string
big() => string
bold() => string
fixed() => string
fontcolor(color: string) => string
fontsize{ (size: number): string; (size: string): string; }
italics() => string
small() => string
strike() => string
sub() => string
sup() => string
padStart(maxLength: number, fillString?: string | undefined) => string
padEnd(maxLength: number, fillString?: string | undefined) => string
trimEnd() => string
trimStart() => string
trimLeft() => string
trimRight() => string
matchAll(regexp: RegExp) => RegExpStringIterator<RegExpExecArray>
replaceAll{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
at(index: number) => string | undefined
__@iterator@6565() => StringIterator<string>

FormatCategory

How the panel groups rules, e.g. to pick what “Fix all” applies.

NameTypeDefault
toString() => string
charAt(pos: number) => string
charCodeAt(index: number) => number
concat(...strings: string[]) => string
indexOf(searchString: string, position?: number | undefined) => number
lastIndexOf(searchString: string, position?: number | undefined) => number
localeCompare{ (that: string): number; (that: string, locales?: string | string[] | undefined, options?: CollatorOptions | undefined): number; (that: string, locales?: LocalesArgument, options?: CollatorOptions | undefined): number; }
match{ (regexp: string | RegExp): RegExpMatchArray | null; (matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; }
replace{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: { ...; }, replaceValue: string): string; (searchValue: { ...; }, replacer: (substring: string, ...args: any[]) => string): string; }
slice(start?: number | undefined, end?: number | undefined) => string
split{ (separator: string | RegExp, limit?: number | undefined): string[]; (splitter: { [Symbol.split](string: string, limit?: number | undefined): string[]; }, limit?: number | undefined): string[]; }
substring(start: number, end?: number | undefined) => string
toLowerCase() => string
toLocaleLowerCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
toUpperCase() => string
toLocaleUpperCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
trim() => string
lengthnumber
substr(from: number, length?: number | undefined) => string
valueOf() => string
codePointAt(pos: number) => number | undefined
includes(searchString: string, position?: number | undefined) => boolean
endsWith(searchString: string, endPosition?: number | undefined) => boolean
normalize{ (form: "NFC" | "NFD" | "NFKC" | "NFKD"): string; (form?: string | undefined): string; }
repeat(count: number) => string
startsWith(searchString: string, position?: number | undefined) => boolean
anchor(name: string) => string
big() => string
bold() => string
fixed() => string
fontcolor(color: string) => string
fontsize{ (size: number): string; (size: string): string; }
italics() => string
small() => string
strike() => string
sub() => string
sup() => string
padStart(maxLength: number, fillString?: string | undefined) => string
padEnd(maxLength: number, fillString?: string | undefined) => string
trimEnd() => string
trimStart() => string
trimLeft() => string
trimRight() => string
matchAll(regexp: RegExp) => RegExpStringIterator<RegExpExecArray>
replaceAll{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
at(index: number) => string | undefined
__@iterator@6565() => StringIterator<string>

FormatRuleId

Rule ids, as in docs/partially-executed/format-cleanup-plan.md.

NameTypeDefault
toString() => string
charAt(pos: number) => string
charCodeAt(index: number) => number
concat(...strings: string[]) => string
indexOf(searchString: string, position?: number | undefined) => number
lastIndexOf(searchString: string, position?: number | undefined) => number
localeCompare{ (that: string): number; (that: string, locales?: string | string[] | undefined, options?: CollatorOptions | undefined): number; (that: string, locales?: LocalesArgument, options?: CollatorOptions | undefined): number; }
match{ (regexp: string | RegExp): RegExpMatchArray | null; (matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; }
replace{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: { ...; }, replaceValue: string): string; (searchValue: { ...; }, replacer: (substring: string, ...args: any[]) => string): string; }
slice(start?: number | undefined, end?: number | undefined) => string
split{ (separator: string | RegExp, limit?: number | undefined): string[]; (splitter: { [Symbol.split](string: string, limit?: number | undefined): string[]; }, limit?: number | undefined): string[]; }
substring(start: number, end?: number | undefined) => string
toLowerCase() => string
toLocaleLowerCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
toUpperCase() => string
toLocaleUpperCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
trim() => string
lengthnumber
substr(from: number, length?: number | undefined) => string
valueOf() => string
codePointAt(pos: number) => number | undefined
includes(searchString: string, position?: number | undefined) => boolean
endsWith(searchString: string, endPosition?: number | undefined) => boolean
normalize{ (form: "NFC" | "NFD" | "NFKC" | "NFKD"): string; (form?: string | undefined): string; }
repeat(count: number) => string
startsWith(searchString: string, position?: number | undefined) => boolean
anchor(name: string) => string
big() => string
bold() => string
fixed() => string
fontcolor(color: string) => string
fontsize{ (size: number): string; (size: string): string; }
italics() => string
small() => string
strike() => string
sub() => string
sup() => string
padStart(maxLength: number, fillString?: string | undefined) => string
padEnd(maxLength: number, fillString?: string | undefined) => string
trimEnd() => string
trimStart() => string
trimLeft() => string
trimRight() => string
matchAll(regexp: RegExp) => RegExpStringIterator<RegExpExecArray>
replaceAll{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
at(index: number) => string | undefined
__@iterator@6565() => StringIterator<string>

FormatSeverity

error: the document misbehaves. warning: dirtier than it needs to be. hint: a judgement call, never applied by “apply all”.

NameTypeDefault
toString() => string
charAt(pos: number) => string
charCodeAt(index: number) => number
concat(...strings: string[]) => string
indexOf(searchString: string, position?: number | undefined) => number
lastIndexOf(searchString: string, position?: number | undefined) => number
localeCompare{ (that: string): number; (that: string, locales?: string | string[] | undefined, options?: CollatorOptions | undefined): number; (that: string, locales?: LocalesArgument, options?: CollatorOptions | undefined): number; }
match{ (regexp: string | RegExp): RegExpMatchArray | null; (matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; }
replace{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: { ...; }, replaceValue: string): string; (searchValue: { ...; }, replacer: (substring: string, ...args: any[]) => string): string; }
slice(start?: number | undefined, end?: number | undefined) => string
split{ (separator: string | RegExp, limit?: number | undefined): string[]; (splitter: { [Symbol.split](string: string, limit?: number | undefined): string[]; }, limit?: number | undefined): string[]; }
substring(start: number, end?: number | undefined) => string
toLowerCase() => string
toLocaleLowerCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
toUpperCase() => string
toLocaleUpperCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
trim() => string
lengthnumber
substr(from: number, length?: number | undefined) => string
valueOf() => string
codePointAt(pos: number) => number | undefined
includes(searchString: string, position?: number | undefined) => boolean
endsWith(searchString: string, endPosition?: number | undefined) => boolean
normalize{ (form: "NFC" | "NFD" | "NFKC" | "NFKD"): string; (form?: string | undefined): string; }
repeat(count: number) => string
startsWith(searchString: string, position?: number | undefined) => boolean
anchor(name: string) => string
big() => string
bold() => string
fixed() => string
fontcolor(color: string) => string
fontsize{ (size: number): string; (size: string): string; }
italics() => string
small() => string
strike() => string
sub() => string
sup() => string
padStart(maxLength: number, fillString?: string | undefined) => string
padEnd(maxLength: number, fillString?: string | undefined) => string
trimEnd() => string
trimStart() => string
trimLeft() => string
trimRight() => string
matchAll(regexp: RegExp) => RegExpStringIterator<RegExpExecArray>
replaceAll{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
at(index: number) => string | undefined
__@iterator@6565() => StringIterator<string>

FormatGuarantee

What a fix promises about rendering. lossless: every block renders identically. tolerance: differs by at most the configured tolerance. restructure: changes the document on purpose (hints only, one click each).

NameTypeDefault
toString() => string
charAt(pos: number) => string
charCodeAt(index: number) => number
concat(...strings: string[]) => string
indexOf(searchString: string, position?: number | undefined) => number
lastIndexOf(searchString: string, position?: number | undefined) => number
localeCompare{ (that: string): number; (that: string, locales?: string | string[] | undefined, options?: CollatorOptions | undefined): number; (that: string, locales?: LocalesArgument, options?: CollatorOptions | undefined): number; }
match{ (regexp: string | RegExp): RegExpMatchArray | null; (matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null; }
replace{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; (searchValue: { ...; }, replaceValue: string): string; (searchValue: { ...; }, replacer: (substring: string, ...args: any[]) => string): string; }
slice(start?: number | undefined, end?: number | undefined) => string
split{ (separator: string | RegExp, limit?: number | undefined): string[]; (splitter: { [Symbol.split](string: string, limit?: number | undefined): string[]; }, limit?: number | undefined): string[]; }
substring(start: number, end?: number | undefined) => string
toLowerCase() => string
toLocaleLowerCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
toUpperCase() => string
toLocaleUpperCase{ (locales?: string | string[] | undefined): string; (locales?: LocalesArgument): string; }
trim() => string
lengthnumber
substr(from: number, length?: number | undefined) => string
valueOf() => string
codePointAt(pos: number) => number | undefined
includes(searchString: string, position?: number | undefined) => boolean
endsWith(searchString: string, endPosition?: number | undefined) => boolean
normalize{ (form: "NFC" | "NFD" | "NFKC" | "NFKD"): string; (form?: string | undefined): string; }
repeat(count: number) => string
startsWith(searchString: string, position?: number | undefined) => boolean
anchor(name: string) => string
big() => string
bold() => string
fixed() => string
fontcolor(color: string) => string
fontsize{ (size: number): string; (size: string): string; }
italics() => string
small() => string
strike() => string
sub() => string
sup() => string
padStart(maxLength: number, fillString?: string | undefined) => string
padEnd(maxLength: number, fillString?: string | undefined) => string
trimEnd() => string
trimStart() => string
trimLeft() => string
trimRight() => string
matchAll(regexp: RegExp) => RegExpStringIterator<RegExpExecArray>
replaceAll{ (searchValue: string | RegExp, replaceValue: string): string; (searchValue: string | RegExp, replacer: (substring: string, ...args: any[]) => string): string; }
at(index: number) => string | undefined
__@iterator@6565() => StringIterator<string>

FormatScope

NameTypeDefault
kind"document" | "styles" | "lists" | "blocks"

FormatChanges

Dry-run summary of a fix. Counts, not transforms.

NameTypeDefault
stylesCreatedstring[]
stylesModifiedstring[]
stylesDeletedstring[]
stylesMergedRecord<string, string>

Deleted style → the style that absorbed it.

listsMergedRecord<string, string>
blocksChangednumber
blocksRemovednumber
marksStrippednumber
pinnednumber

Runs or blocks that keep (or gain) direct formatting so rendering holds.

FormatSummary

NameTypeDefault
appliedFormatSuggestion[]
gonestring[]

Requested ids that no longer resolve on the current document.

blockedstring | null

Set when nothing was applied because of blockedReason.

forcedboolean

Applied despite a blockedReason.

totalsFormatChanges

FormatLintOptions

NameTypeDefault
tolerancePxnumber

px; indents and spacing within this of a style’s value count as equal.

coverageThresholdnumber

Share (0–1) of a style’s paragraphs or text above which a value belongs in the style.

minClusterSizenumber

Paragraphs sharing one delta before it becomes a style.

colorTolerancenumber

CIEDE2000; a fixed colour closer than this to a theme colour is a near match (FMT-26).

rulesFormatRuleId[]

Only these rules run. Default: all.

ignorestring[]

Suggestion ids to drop from results and from “apply all”.

ApplyFormatOptions

NameTypeDefault
tolerancePxnumber

px; indents and spacing within this of a style’s value count as equal.

coverageThresholdnumber

Share (0–1) of a style’s paragraphs or text above which a value belongs in the style.

minClusterSizenumber

Paragraphs sharing one delta before it becomes a style.

colorTolerancenumber

CIEDE2000; a fixed colour closer than this to a theme colour is a near match (FMT-26).

rulesFormatRuleId[]

Only these rules run. Default: all.

ignorestring[]

Suggestion ids to drop from results and from “apply all”.

blockedReason(state: EditorState) => string | null

A reason not to apply (e.g. track changes on); force overrides it.

forceboolean
onlyFormatRuleId[]

Applies only these rules’ fixes. Unlike rules, which also decides what is collected and turns hints on for “all”, this only filters the apply.

guaranteesFormatGuarantee[]

Applies only findings with these guarantees, e.g. ["lossless"] for a fix that must not move layout. With “all”, it also takes the matching hints.

Last updated on