/**
 * @fileoverview Rule to enforce heading levels increment by one.
 * @author Nicholas C. Zakas
 */
//-----------------------------------------------------------------------------
// Imports
//-----------------------------------------------------------------------------
import { frontmatterHasTitle } from "../util.js";
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
/**
 * @import { MarkdownRuleDefinition } from "../types.js";
 * @typedef {"skippedHeading"} HeadingIncrementMessageIds
 * @typedef {[{ frontmatterTitle?: string }]} HeadingIncrementOptions
 * @typedef {MarkdownRuleDefinition<{ RuleOptions: HeadingIncrementOptions, MessageIds: HeadingIncrementMessageIds }>} HeadingIncrementRuleDefinition
 */
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------
export default /** @satisfies {HeadingIncrementRuleDefinition} */ ({
    meta: {
        type: "problem",
        docs: {
            recommended: true,
            description: "Enforce heading levels increment by one",
            url: "https://github.com/eslint/markdown/blob/main/docs/rules/heading-increment.md",
        },
        messages: {
            skippedHeading: "Heading level skipped from {{fromLevel}} to {{toLevel}}.",
        },
        schema: [
            {
                type: "object",
                properties: {
                    frontmatterTitle: {
                        type: "string",
                    },
                },
                additionalProperties: false,
            },
        ],
        defaultOptions: [
            {
                frontmatterTitle: "^(?!\\s*['\"]title[:=]['\"])\\s*\\{?\\s*['\"]?title['\"]?\\s*[:=]",
            },
        ],
    },
    create(context) {
        const [{ frontmatterTitle }] = context.options;
        const titlePattern = frontmatterTitle === "" ? null : new RegExp(frontmatterTitle, "iu");
        let lastHeadingDepth = 0;
        return {
            yaml(node) {
                if (frontmatterHasTitle(node.value, titlePattern)) {
                    lastHeadingDepth = 1;
                }
            },
            toml(node) {
                if (frontmatterHasTitle(node.value, titlePattern)) {
                    lastHeadingDepth = 1;
                }
            },
            json(node) {
                if (frontmatterHasTitle(node.value, titlePattern)) {
                    lastHeadingDepth = 1;
                }
            },
            heading(node) {
                if (lastHeadingDepth > 0 && node.depth > lastHeadingDepth + 1) {
                    context.report({
                        loc: node.position,
                        messageId: "skippedHeading",
                        data: {
                            fromLevel: lastHeadingDepth,
                            toLevel: node.depth,
                        },
                    });
                }
                lastHeadingDepth = node.depth;
            },
        };
    },
});
