/**
 * @fileoverview Rule to require or disallow metadata for fenced code blocks.
 * @author TKDev7
 */
//-----------------------------------------------------------------------------
// Type Definitions
//-----------------------------------------------------------------------------
/**
 * @import { MarkdownRuleDefinition } from "../types.js";
 * @typedef {"missingMetadata" | "disallowedMetadata"} FencedCodeMetaMessageIds
 * @typedef {["always" | "never"]} FencedCodeMetaOptions
 * @typedef {MarkdownRuleDefinition<{ RuleOptions: FencedCodeMetaOptions, MessageIds: FencedCodeMetaMessageIds }>} FencedCodeMetaRuleDefinition
 */
//-----------------------------------------------------------------------------
// Rule Definition
//-----------------------------------------------------------------------------
export default /** @satisfies {FencedCodeMetaRuleDefinition} */ ({
    meta: {
        type: "problem",
        docs: {
            recommended: false,
            description: "Require or disallow metadata for fenced code blocks",
            url: "https://github.com/eslint/markdown/blob/main/docs/rules/fenced-code-meta.md",
        },
        messages: {
            missingMetadata: "Missing code block metadata.",
            disallowedMetadata: "Code block metadata is not allowed.",
        },
        schema: [
            {
                enum: ["always", "never"],
            },
        ],
        defaultOptions: ["always"],
    },
    create(context) {
        const [mode] = context.options;
        const { sourceCode } = context;
        return {
            code(node) {
                const lineText = sourceCode.lines[node.position.start.line - 1];
                const fenceLineText = lineText.slice(node.position.start.column - 1);
                if (mode === "always") {
                    if (node.lang && !node.meta) {
                        const langIndex = fenceLineText.indexOf(node.lang);
                        context.report({
                            loc: {
                                start: node.position.start,
                                end: {
                                    line: node.position.start.line,
                                    column: node.position.start.column +
                                        langIndex +
                                        node.lang.length,
                                },
                            },
                            messageId: "missingMetadata",
                        });
                    }
                    return;
                }
                if (node.meta) {
                    const metaIndex = fenceLineText.lastIndexOf(node.meta);
                    context.report({
                        loc: {
                            start: {
                                line: node.position.start.line,
                                column: node.position.start.column + metaIndex,
                            },
                            end: {
                                line: node.position.start.line,
                                column: node.position.start.column +
                                    metaIndex +
                                    node.meta.trimEnd().length,
                            },
                        },
                        messageId: "disallowedMetadata",
                    });
                }
            },
        };
    },
});
