{"record":{"id":"fcc231bc9cae4d4f","repo":"swc-project/swc","slug":"endtagviolatesnestingrules","errorCode":"EndTagViolatesNestingRules","errorMessage":"End tag \"{tag_name}\" violates nesting rules","messagePattern":"End tag \"(.+?)\" violates nesting rules","errorType":"validation","errorClass":"swc_html_parser::error::Error","httpStatus":null,"severity":"warning","filePath":"crates/swc_html_parser/src/parser/mod.rs","lineNumber":7343,"sourceCode":"            if formatting_element_stack_index.is_some()\n                && !self\n                    .open_elements_stack\n                    .has_node_in_scope(&formatting_element.1)\n            {\n                self.errors.push(Error::new(\n                    token_and_info.span,\n                    ErrorKind::NoElementToCloseButEndTagSeen(subject),\n                ));\n\n                return Ok(());\n            }\n\n            let formatting_element_stack_index = formatting_element_stack_index.unwrap();\n\n            // 6.\n            if let Some(node) = self.open_elements_stack.items.last() {\n                if !is_same_node(node, &formatting_element.1) {\n                    self.errors.push(Error::new(\n                        token_and_info.span,\n                        ErrorKind::EndTagViolatesNestingRules(subject.clone()),\n                    ));\n                }\n            }\n\n            // 7.\n            let furthest_block = self\n                .open_elements_stack\n                .items\n                .iter()\n                .enumerate()\n                .skip(formatting_element_stack_index)\n                .find(|&(_, open_element)| self.is_special_element(open_element))\n                .map(|(i, h)| (i, h.clone()));\n\n            // 8.\n            if furthest_block.is_none() {","sourceCodeStart":7325,"sourceCodeEnd":7361,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_html_parser/src/parser/mod.rs#L7325-L7361","documentation":"Step 6 of the adoption agency algorithm (crates/swc_html_parser/src/parser/mod.rs:7343): when a formatting end tag is processed and the current node (top of the open elements stack) is not the formatting element itself, the end tag 'violates nesting rules'. The parser reports the error and then performs the full adoption agency run — reconstructing active formatting elements and re-parenting nodes — which is exactly the famous `<b><p>x</b>` transformation.","triggerScenarios":"Parsing `<b>1<p>2</b>3` or `<a href><div>click</a>` — a formatting end tag whose element is in scope but not the current node, forcing the parser to run the re-parenting machinery instead of a simple pop.","commonSituations":"Classic WYSIWYG output (`<b>` wrapped around block elements); anchor tags opened around divs/li; sanitizers stripping block elements inside inline formatting; HTML emails where styling spans wrap paragraphs.","solutions":["Close the formatting element before opening the block element: <b>1</b><p>2</p>","Move the formatting inside the block: <p><b>2</b></p>","Use CSS (font-weight, color) instead of wrapping block content in formatting tags","Expect re-parented output from recovery — snapshot-test normalized HTML for such inputs"],"exampleFix":"<!-- before -->\n<b>1<p>2</b>3\n<!-- after -->\n<b>1</b><p><b>2</b></p>3","handlingStrategy":"validation","validationCode":"// Reject inline formatting elements containing block-level children\nconst BLOCK = /^(div|p|ul|ol|li|table|tr|td|th|h[1-6]|section|article|blockquote|form|pre|hr)$/i;\nfunction assertNoInlineAroundBlocks(html: string): void {\n  for (const m of html.matchAll(/<(b|i|em|strong|u|s|a|span|font)\\b[^>]*>([\\s\\S]*?)<\\/\\1>/gi)) {\n    if (BLOCK.test((m[2].match(/^\\s*<([a-zA-Z0-9]+)/) || [])[1] || '')) {\n      throw new Error(`<${m[1]}> wraps a block element`);\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":"for err in parser.take_errors() {\n    if let ErrorKind::EndTagViolatesNestingRules(name) = &err.kind {\n        // adoption agency will re-parent nodes; snapshot-test the output\n    }\n}","preventionTips":["Close formatting tags before opening block elements (the classic <b><p></b> fix)","Prefer CSS styling over wrapping blocks in formatting tags","Configure WYSIWYG editors to enforce inline-content models"],"tags":["html","adoption-agency","nesting-rules","formatting-elements","parse-error"],"backgroundTag":"html5-parse-error","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}