import type { Token, TokenTree } from '../../parser/types.js'; /** * Adds a range of numbers (inclusive of both bounds) to a set. */ export declare function addRangeToSet(set: Set, start: number, end: number): void; /** * A line/column range within a file (1-based, inclusive of both ends). * Shares field names with `Token`'s start/end line/column so a `Token` can * be passed directly wherever a `FileRange` is expected. */ export interface FileRange { startLine: number; startColumn: number; endLine: number; endColumn: number; } /** * Returns whether two ranges (or Tokens) overlap anywhere. Ported from * markdownlint's helpers/helpers.cjs `hasOverlap`. */ export declare function hasOverlap(rangeA: FileRange, rangeB: FileRange): boolean; /** * Filter a token tree, or an arbitrary token array (accepted so * `blanksAroundLists`/MD032 can start the walk from `list.children` * instead of the whole tree), by predicate — walking depth-first. Ported * from upstream's `filterByPredicate(tokens, allowed, transformChildren)`: * `transformChildren`, when given, replaces a token's own `children` array * for traversal purposes only (the returned `result` array is unaffected) — * upstream uses this to redirect traversal into htmlFlow subtokens, and * MD032 uses it to stop descending into nested lists (so only *top-level* * lists are returned) and to skip "non-content" token subtrees entirely. * Omitting `transformChildren` walks every real child, matching every * batch 1/2 caller's usage (none needed it before MD032). */ export declare function filterByPredicate(tree: TokenTree | Token[], predicate: (token: Token) => boolean, transformChildren?: (token: Token) => Token[]): Token[]; /** * Gets a list of nested token descendants by type path. Each path element * matches one depth of descent and may be a single type or (per upstream's * own signature, `helpers/helpers.cjs`'s shared `getDescendantsByType`) an * array of alternative types to match at that depth — used by batch 5's * `link-image-style` (MD054) for `resourceDestination`'s * literal/raw-destination split and `autolink`'s email/protocol split. * Earlier batches (see `getHeadingText` below) predate this and call once * per alternative instead, merging results themselves; both styles coexist * since neither is wrong, but new callers needing an alternation can now * use a single call. */ export declare function getDescendantsByType(token: Token, typePath: readonly (string | readonly string[])[]): Token[]; /** * Gets the nearest parent of one of the specified types for a token. */ export declare function getParentOfType(token: Token, types: readonly string[]): Token | null; /** * Gets the heading level of an atx or setext heading token. Matches * upstream: looks for a direct child of type `atxHeadingSequence` or * `setextHeadingLine` (the setext underline is a direct child of * `setextHeading`, not nested further) and reads its level from the text. */ export declare function getHeadingLevel(heading: Token): number; /** * Gets the heading style of an atx or setext heading token: `'setext'` for * setext headings, `'atx'` for a plain atx heading (one `atxHeadingSequence` * child), or `'atx_closed'` for a closed atx heading (a trailing * `atxHeadingSequence` closing marker as a second direct-child sequence). */ export declare function getHeadingStyle(heading: Token): 'setext' | 'atx' | 'atx_closed'; /** * Gets the heading text of an atx or setext heading token. Descends into * `atxHeadingText`/`setextHeadingText` (nested arbitrarily deep under the * heading, e.g. inside inline containers) and concatenates all non-htmlText * descendant text, collapsing internal newlines (setext headings can span * multiple lines) to single spaces. */ export declare function getHeadingText(heading: Token): string; /** * Gets the blockquote prefix text (if any) for the specified line number, * e.g. `"> "` for a line inside a single-level blockquote. Upstream filters * a flat token list by type via `filterByTypes`; Recheck's `TokenTree` * already carries a flat list (`tree.flat`), so this takes the tree * directly rather than a pre-filtered token array. */ export declare function getBlockQuotePrefixText(tree: TokenTree, lineNumber: number, count?: number): string; /** * Returns true iff the input line is blank (contains nothing, whitespace, * blockquote markers, or HTML comments (unclosed start/end comments * allowed)). Ported from markdownlint's helpers/helpers.cjs `isBlankLine`. */ export declare function isBlankLine(line: string): boolean; /** * Set of token types that do not contain document content (used to skip * over "non-content" tokens — indentation, blank lines, container prefixes * — when scanning for a document's first meaningful token). Ported from * markdownlint's helpers/micromark-helpers.cjs `nonContentTokens`. */ export declare const nonContentTokens: Set; /** * Returns the last line number (1-based, inclusive) of the document's YAML * frontmatter block, or 0 if there is none. * * Upstream markdownlint slices frontmatter out of `content` entirely * before tokenizing (see markdownlint's `removeFrontMatter`) — every * rule's `params.lines`/token stream is already frontmatter-free, with * `frontMatterLines.length` added back only when reporting an error's line * number. Recheck's parser instead keeps a `yaml` token (and all its * descendant tokens — `yamlFence`, `yamlValue`, etc. — individually * present in `tree.flat`, a full depth-first flattening) as real content. * Rules that scan `ctx.lines` by index, or walk `ctx.tree.flat` from the * top of the document looking for the first "real" token, must skip every * line up to and including this one to match upstream's behavior — see * first-line-h1.ts, single-h1.ts, and line-length.ts for call sites. */ export declare function getFrontmatterEndLine(tree: TokenTree): number; /** * Returns true iff the document's YAML front matter contains a title — i.e. * the `pattern` regex matches at least one of the front matter block's lines. * * WHY THIS EXISTS: it ports upstream markdownlint's `front_matter_title` * rule option (implemented there by helpers/helpers.cjs's own * `frontMatterHasTitle`), which exists on exactly three upstream rules — * MD001 (our heading-increment), MD025 (single-h1), and MD041 * (first-line-h1); see * https://github.com/DavidAnson/markdownlint/blob/main/doc/md001.md. * When the front matter declares a title, it counts as the document's * implicit top-level (h1) heading: * - heading-increment then expects the first body heading to be an h2; * - single-h1 treats it as the document's one H1, so EVERY body h1 is a * violation; * - first-line-h1 is satisfied by it outright and checks nothing else. * * The default pattern is `^\s*"?title"?\s*[:=]`: a `title` key, optionally * double-quoted, followed by `:` (YAML) or `=` (TOML-style front matter), * matched case-insensitively. Each of the three rules declares that default * in its own `defaults` object — exactly as each upstream rule declares its * own default — and this helper only encapsulates the matching. * * CONTRACT: `pattern` is the raw config value (`ctx.config.frontMatterTitle`); * configuring the empty string `''` (or a nullish value) disables the * behavior entirely — this helper then always returns false — matching * upstream's documented "specify `""` for `front_matter_title`" opt-out. * * Upstream builds the regex with the `i` flag only and tests it against each * front matter LINE individually (`frontMatterLines.some(...)`), where * `frontMatterLines` is the whole regex-matched front matter block — * INCLUDING both delimiter fence lines — split on line endings (see * markdownlint's `removeFrontMatter`). Recheck's parser keeps that same * block as one `yaml` token (see getFrontmatterEndLine's doc comment above) * whose text spans opening fence through closing fence with no trailing * newline, so splitting it on `newLineRe` reproduces upstream's lines * exactly, and the regex is tested per line here too. (Testing the whole * block with `im` instead is NOT equivalent: a custom pattern containing a * literal `\n`, or one where `\s*`/`[\s\S]*` can absorb a line ending — * e.g. `author:.*\s*title` — would match across lines, which upstream * never does.) */ export declare function frontMatterHasTitle(tree: TokenTree, pattern: unknown): boolean; /** * Returns true iff the token is an HTML comment (``) that is * valid per the CommonMark spec (comment body doesn't start with `>` or * `->`, and doesn't end with `-`). Ported from markdownlint's * helpers/micromark-helpers.cjs `isHtmlFlowComment`. */ export declare function isHtmlFlowComment(token: Token): boolean; /** * Replaces the content of valid CommonMark HTML comments with the `.` * "safe" character, preserving every line/column position in the rest of * the document (never removes characters, never touches `\r`/`\n`). * Ported from markdownlint's helpers/helpers.cjs `clearHtmlCommentText`. * * This is upstream's OWN pre-processing pass -- run once, globally, before * `params.lines` is computed -- so that rules doing plain text/line * scanning (as opposed to token-tree scanning) never see real content * inside an HTML comment: trailing whitespace inside a comment isn't * "trailing whitespace" (MD009), a tab inside a comment isn't a "hard * tab" (MD010), reversed-link syntax inside a comment isn't a broken link * (MD011), etc. Token-tree-based scanning (e.g. MD033/MD037, which read * `params.parsers.micromark.tokens`) is unaffected -- those tokens are * built from the ORIGINAL, uncleared content upstream, matching how * recheck's own token tree (`ctx.tree`) is never cleared either; only * `ctx.lines` (see core/runner.ts) uses this cleared text. */ export declare function clearHtmlCommentText(text: string): string; /** * Returns true iff the heading is a DocFX tab heading (an atx heading whose * entire text is a single link with a `#tab/...` destination) — see * https://dotnet.github.io/docfx/docs/markdown.html?tabs=linux%2Cdotnet#tabs. * Ported from markdownlint's helpers/micromark-helpers.cjs `isDocfxTab`. */ export declare const endOfLineHtmlEntityRe: RegExp; export declare const endOfLineGemojiCodeRe: RegExp; export declare const allPunctuation = ".,;:!?\u3002\uFF0C\uFF1B\uFF1A\uFF01\uFF1F"; export declare const allPunctuationNoQuestion: string; /** * Escapes a string for safe use inside a RegExp character class/pattern. * Ported from markdownlint's helpers/helpers.cjs `escapeForRegExp`. */ export declare function escapeForRegExp(str: string): string; /** * Replaces lone (unpaired) surrogate code units with U+FFFD, matching the * behavior of `String.prototype.toWellFormed()` (ES2024). Recheck's * `tsconfig.json` targets ES2021 (shared across the whole package, not * something this rule port should widen), so `link-fragments` (MD051) — * the only upstream rule using `.toWellFormed()` (on heading/fragment text * before `encodeURIComponent`, which throws on lone surrogates) — calls * this instead of the native method. */ export declare function toWellFormedString(str: string): string; /** * HTML tag information: whether it's a closing tag and its (lowercased-by- * caller-if-needed) name. Ported from markdownlint's * helpers/micromark-helpers.cjs `getHtmlTagInfo`. */ export interface HtmlTagInfo { close: boolean; name: string; } /** * Gets information about the tag in an HTML token (an `htmlText` token's * opening `` or closing ``), or `null` if the token's text * doesn't start with a recognizable tag (e.g. an HTML comment). Ported from * markdownlint's helpers/micromark-helpers.cjs `getHtmlTagInfo`. */ export declare function getHtmlTagInfo(token: Token): HtmlTagInfo | null; /** * Builds a RegExp for matching the specified HTML attribute (e.g. `alt=`, * `id=`) within a raw HTML tag's text, capturing its (optionally quoted) * value. Ported from markdownlint's helpers/helpers.cjs `getHtmlAttributeRe`. */ export declare function getHtmlAttributeRe(name: string): RegExp; /** * Truncates long text for use in error context, keeping the start, end, or * both ends depending on which end(s) matter. Ported from markdownlint's * helpers/helpers.cjs `ellipsify`. */ export declare function ellipsify(text: string, start?: boolean, end?: boolean): string; export declare function isDocfxTab(heading: Token | null | undefined): boolean; export declare function normalizeReference(s: string): string; /** One usage site of a reference/shortcut label: `[lineIndex, columnIndex, length]` (0-based line/column), matching upstream's `number[][]` shape exactly so MD052's line/column math ports verbatim. */ export type ReferenceDatum = [lineIndex: number, columnIndex: number, length: number]; export interface GetReferenceLinkImageDataResult { /** Normalized label -> usage sites, for "full"/"collapsed" reference syntax (`[text][label]`, `[label][]`). */ references: Map; /** Normalized label -> usage sites, for "shortcut" syntax (`[label]`) and footnote calls (`[^label]`). */ shortcuts: Map; /** Normalized label -> `[lineIndex, destinationText]` for each `[label]: destination` (or footnote `[^label]: ...`) definition. */ definitions: Map; /** `[label, lineIndex]` for each definition after the first one seen for that label. */ duplicateDefinitions: [string, number][]; } /** * Returns information about reference-style links/images and their * definitions across the whole document: which labels are defined, which * are used (split into "full/collapsed" `references` vs "shortcut" * `shortcuts`, since shortcut syntax is ambiguous with plain bracketed * text), and which definitions are duplicates. Ported from markdownlint's * helpers/helpers.cjs `getReferenceLinkImageData` (there, cached per-lint- * run by lib/cache.mjs; Recheck's token rules have no shared per-run cache * — see no-empty-links.ts's doc comment for the established precedent — so * each of MD051/052/053/054 calls this fresh over the same tree). * * DEVIATION: upstream additionally detects reference syntax that fails to * resolve to any definition at all (`undefinedReferenceShortcut/Collapsed/ * Full`) by monkeypatching micromark's internal `labelEnd` tokenizer * (lib/micromark-parse.mjs) to synthesize tokens when label resolution * backtracks to failure. Recheck's parser (src/parser/index.ts) is a much * thinner micromark wrapper with no equivalent hook, and reproducing that * shim correctly is a parser-level change out of scope for a rule port. * Without it, an *undefined* reference/shortcut never becomes a `link`/ * `image`/`gfmFootnoteCall` token in Recheck's tree in the first place — * it decomposes into plain `data` tokens — so there is no token for this * function to inspect for that case via the token-shape path alone. * `scanUndefinedReferences` below is a conservative, best-effort text-scan * fallback (restricted to direct `data`/`lineEnding` children of a single * container, requiring non-nested single-bracket-depth text with no `]` * inside — mirroring the upstream shim's own `!text.includes("]")` guard) * so MD052 (whose entire purpose is detecting undefined references) is not * a permanent no-op; it is not a byte-for-byte port of the shim and may * miss or mis-slice pathological/multi-line cases the real shim handles * via micromark's own backtracking state. MD053's `duplicateDefinitions`/ * `definitions` and MD054's `definitions` lookups don't depend on this * fallback at all (they only need successfully-resolved usages), so this * deviation is fully scoped to MD052. */ export declare function getReferenceLinkImageData(tree: TokenTree): GetReferenceLinkImageDataResult; export interface ImageDestination { /** The `image` token itself — use its position/text for reporting. */ token: Token; /** * The image's destination exactly as written in the source: either the * inline `(path "title")` destination (raw or angle-bracket literal), or * the resolved reference/collapsed/shortcut definition's destination. */ destination: string; } /** * Resolves every `image` token in the tree to its destination path/URL — * both inline syntax (`![alt](path "title")`, including angle-bracket * literal destinations) and reference syntax (`![alt][ref]`, `![alt][]`, * `![alt]`), the latter resolved through `getReferenceLinkImageData`'s * `definitions` map the same way `link-image-style.ts` (MD054) resolves a * reference link/image's destination for its autolink-eligibility check. * An image whose reference never resolves to a definition never becomes an * `image` token in the first place (see `getReferenceLinkImageData`'s * DEVIATION note above) — there's no token to report for those here, * matching every other AST-based rule's treatment of the same tree. * * Shared by `rules/scope/max-image-size.ts` (the rule that flags oversized * images) and `core/files.ts`'s `extractImageReferences` (the on-disk * metadata loader): a single extraction pass so both sides always agree on * exactly which destination string keys a given image's on-disk stats in * `ScopeRuleContext.fileMetadata.images`. */ export declare function getImageDestinations(tree: TokenTree): ImageDestination[]; //# sourceMappingURL=helpers.d.ts.map