import { BaseRuleVisitor, isInlineElement, isBlockElement } from "./rule-utils.js";
class BlockInsideInlineVisitor extends BaseRuleVisitor {
    inlineStack = [];
    isValidHTMLOpenTag(node) {
        return !!(node.open_tag && node.open_tag.type === "AST_HTML_OPEN_TAG_NODE");
    }
    getElementType(tagName) {
        const isInline = isInlineElement(tagName);
        const isBlock = isBlockElement(tagName);
        const isUnknown = !isInline && !isBlock;
        return { isInline, isBlock, isUnknown };
    }
    addViolationMessage(tagName, isBlock, openTag) {
        const parentInline = this.inlineStack[this.inlineStack.length - 1];
        const elementType = isBlock ? "Block-level" : "Unknown";
        this.addOffense(`${elementType} element \`<${tagName}>\` cannot be placed inside inline element \`<${parentInline}>\`.`, openTag.tag_name.location, "error");
    }
    visitInlineElement(node, tagName) {
        this.inlineStack.push(tagName);
        super.visitHTMLElementNode(node);
        this.inlineStack.pop();
    }
    visitBlockElement(node) {
        const savedStack = [...this.inlineStack];
        this.inlineStack = [];
        super.visitHTMLElementNode(node);
        this.inlineStack = savedStack;
    }
    visitHTMLElementNode(node) {
        if (!this.isValidHTMLOpenTag(node)) {
            super.visitHTMLElementNode(node);
            return;
        }
        const openTag = node.open_tag;
        const tagName = openTag.tag_name?.value.toLowerCase();
        if (!tagName) {
            super.visitHTMLElementNode(node);
            return;
        }
        const { isInline, isBlock, isUnknown } = this.getElementType(tagName);
        if ((isBlock || isUnknown) && this.inlineStack.length > 0) {
            this.addViolationMessage(tagName, isBlock, openTag);
        }
        if (isInline) {
            this.visitInlineElement(node, tagName);
            return;
        }
        this.visitBlockElement(node);
    }
}
export class HTMLNoBlockInsideInlineRule {
    name = "html-no-block-inside-inline";
    check(node) {
        const visitor = new BlockInsideInlineVisitor(this.name);
        visitor.visit(node);
        return visitor.offenses;
    }
}
//# sourceMappingURL=html-no-block-inside-inline.js.map