[{"data":1,"prerenderedAt":62},["Reactive",2],{"blog-post-markdown-content-validation-automated-quality-assurance":3},{"slug":4,"title":5,"description":6,"excerpt":7,"date":8,"category":9,"author":10,"keywords":11,"readingMinutes":12,"html":13,"headings":14,"tools":37,"related":38},"markdown-content-validation-automated-quality-assurance","Markdown Content Validation and Automated Quality Assurance: Complete Guide for Documentation Excellence and Team Workflows","Master automated Markdown content validation with comprehensive quality assurance systems. Learn validation rules, automated testing, CI/CD integration, and quality metrics for professional documentation workflows.","Automated Markdown content validation and quality assurance systems enable professional documentation teams to maintain consistency, accuracy, and excellence across large content repositories…","2025-10-11","Tutorial","Matthew Rathbone","markdown validation, content quality assurance, automated markdown testing, documentation QA, markdown linting, content validation tools, documentation quality metrics, markdown CI/CD",27,"\u003Cp>Automated Markdown content validation and quality assurance systems enable professional documentation teams to maintain consistency, accuracy, and excellence across large content repositories while reducing manual review overhead and ensuring compliance with organizational standards. By implementing comprehensive validation workflows, automated testing pipelines, and quality metrics dashboards, technical teams can scale documentation processes without sacrificing content quality or user experience.\u003C/p>\n\u003Ch2 id=\"why-master-automated-content-validation\">Why Master Automated Content Validation?\u003C/h2>\n\u003Cp>Professional content validation provides essential benefits for documentation workflows:\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Consistency Enforcement\u003C/strong>: Automatically ensure adherence to style guides, formatting standards, and organizational conventions\u003C/li>\n\u003Cli>\u003Cstrong>Error Prevention\u003C/strong>: Catch syntax errors, broken links, missing metadata, and content issues before publication\u003C/li>\n\u003Cli>\u003Cstrong>Quality Metrics\u003C/strong>: Track documentation health through automated scoring, readability analysis, and compliance measurement  \u003C/li>\n\u003Cli>\u003Cstrong>Team Scalability\u003C/strong>: Enable distributed teams to contribute while maintaining unified quality standards\u003C/li>\n\u003Cli>\u003Cstrong>Continuous Improvement\u003C/strong>: Identify patterns in content issues to refine processes and improve documentation systems\u003C/li>\n\u003C/ul>\n\u003Ch2 id=\"foundation-validation-systems\">Foundation Validation Systems\u003C/h2>\n\u003Ch3 id=\"core-content-validation-framework\">Core Content Validation Framework\u003C/h3>\n\u003Cp>Building comprehensive validation systems for Markdown documentation:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\"># markdown_validator.py - Comprehensive content validation system\u003C/span>\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> re\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> os\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> yaml\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> json\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> requests\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> pathlib \u003Cspan class=\"hljs-keyword\">import\u003C/span> Path\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> typing \u003Cspan class=\"hljs-keyword\">import\u003C/span> \u003Cspan class=\"hljs-type\">Dict\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>, \u003Cspan class=\"hljs-type\">Optional\u003C/span>, \u003Cspan class=\"hljs-type\">Tuple\u003C/span>, \u003Cspan class=\"hljs-type\">Any\u003C/span>\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> dataclasses \u003Cspan class=\"hljs-keyword\">import\u003C/span> dataclass\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> enum \u003Cspan class=\"hljs-keyword\">import\u003C/span> Enum\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> urllib.parse \u003Cspan class=\"hljs-keyword\">import\u003C/span> urlparse, urljoin\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> subprocess\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> datetime \u003Cspan class=\"hljs-keyword\">import\u003C/span> datetime, timedelta\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">ValidationSeverity\u003C/span>(\u003Cspan class=\"hljs-title class_ inherited__\">Enum\u003C/span>):\n    ERROR = \u003Cspan class=\"hljs-string\">&quot;error&quot;\u003C/span>\n    WARNING = \u003Cspan class=\"hljs-string\">&quot;warning&quot;\u003C/span>\n    INFO = \u003Cspan class=\"hljs-string\">&quot;info&quot;\u003C/span>\n\n\u003Cspan class=\"hljs-meta\">@dataclass\u003C/span>\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">ValidationResult\u003C/span>:\n    rule_id: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\n    severity: ValidationSeverity\n    message: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\n    file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\n    line_number: \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">int\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    column: \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">int\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    context: \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    fix_suggestion: \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">ContentValidator\u003C/span>:\n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self, config_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span> = \u003Cspan class=\"hljs-string\">&quot;validation_config.yaml&quot;\u003C/span>\u003C/span>):\n        self.config = self.load_config(config_path)\n        self.results = []\n        self.file_cache = {}\n        \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">load_config\u003C/span>(\u003Cspan class=\"hljs-params\">self, config_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Load validation configuration from YAML file&quot;&quot;&quot;\u003C/span>\n        default_config = {\n            \u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;frontmatter&#x27;\u003C/span>: {\n                    \u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;required_fields&#x27;\u003C/span>: [\u003Cspan class=\"hljs-string\">&#x27;title&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;description&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;author&#x27;\u003C/span>],\n                    \u003Cspan class=\"hljs-string\">&#x27;optional_fields&#x27;\u003C/span>: [\u003Cspan class=\"hljs-string\">&#x27;keywords&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;category&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;tags&#x27;\u003C/span>],\n                    \u003Cspan class=\"hljs-string\">&#x27;date_format&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;title_max_length&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">100\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;description_max_length&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">200\u003C/span>\n                },\n                \u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>: {\n                    \u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;require_h1&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;max_heading_length&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">80\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;no_duplicate_headings&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;heading_case&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;title&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># title, sentence, lower, upper\u003C/span>\n                    \u003Cspan class=\"hljs-string\">&#x27;no_empty_headings&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>\n                },\n                \u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>: {\n                    \u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;check_external&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;check_internal&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;allow_fragments&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;timeout&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">10\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;retry_count&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">2\u003C/span>\n                },\n                \u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>: {\n                    \u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;require_alt_text&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;max_size_mb&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">5\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;allowed_formats&#x27;\u003C/span>: [\u003Cspan class=\"hljs-string\">&#x27;jpg&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;jpeg&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;png&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;gif&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;webp&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;svg&#x27;\u003C/span>],\n                    \u003Cspan class=\"hljs-string\">&#x27;check_dimensions&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;min_width&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">200\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;max_width&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">2000\u003C/span>\n                },\n                \u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>: {\n                    \u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;min_word_count&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">100\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;max_line_length&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">120\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;no_trailing_whitespace&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;consistent_list_markers&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;require_blank_lines&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>\n                },\n                \u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>: {\n                    \u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;require_language_tags&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;validate_syntax&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;max_line_length&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">100\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;no_hardcoded_secrets&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>\n                },\n                \u003Cspan class=\"hljs-string\">&#x27;accessibility&#x27;\u003C/span>: {\n                    \u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;heading_hierarchy&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;link_text_descriptive&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;table_headers&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                    \u003Cspan class=\"hljs-string\">&#x27;color_contrast_warnings&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>\n                }\n            },\n            \u003Cspan class=\"hljs-string\">&#x27;file_patterns&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;include&#x27;\u003C/span>: [\u003Cspan class=\"hljs-string\">&#x27;**/*.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;**/*.markdown&#x27;\u003C/span>],\n                \u003Cspan class=\"hljs-string\">&#x27;exclude&#x27;\u003C/span>: [\u003Cspan class=\"hljs-string\">&#x27;node_modules/**&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;.git/**&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;_site/**&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;vendor/**&#x27;\u003C/span>]\n            },\n            \u003Cspan class=\"hljs-string\">&#x27;output&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;format&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;json&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># json, junit, checkstyle, sarif\u003C/span>\n                \u003Cspan class=\"hljs-string\">&#x27;file&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;validation_results.json&#x27;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;console&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;details&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>\n            }\n        }\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> os.path.exists(config_path):\n            \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(config_path, \u003Cspan class=\"hljs-string\">&#x27;r&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n                user_config = yaml.safe_load(f)\n                \u003Cspan class=\"hljs-comment\"># Merge with default config\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> self.deep_merge(default_config, user_config)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> default_config\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">deep_merge\u003C/span>(\u003Cspan class=\"hljs-params\">self, base: \u003Cspan class=\"hljs-type\">Dict\u003C/span>, override: \u003Cspan class=\"hljs-type\">Dict\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Deep merge configuration dictionaries&quot;&quot;&quot;\u003C/span>\n        result = base.copy()\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> key, value \u003Cspan class=\"hljs-keyword\">in\u003C/span> override.items():\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> key \u003Cspan class=\"hljs-keyword\">in\u003C/span> result \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-built_in\">isinstance\u003C/span>(result[key], \u003Cspan class=\"hljs-built_in\">dict\u003C/span>) \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-built_in\">isinstance\u003C/span>(value, \u003Cspan class=\"hljs-built_in\">dict\u003C/span>):\n                result[key] = self.deep_merge(result[key], value)\n            \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n                result[key] = value\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> result\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_file\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[ValidationResult]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate a single Markdown file&quot;&quot;&quot;\u003C/span>\n        self.results = []\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> os.path.exists(file_path):\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;file_exists&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">f&#x27;File does not exist: \u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>&#x27;\u003C/span>,\n                file_path=file_path\n            ))\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> self.results\n        \n        \u003Cspan class=\"hljs-comment\"># Read and cache file content\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(file_path, \u003Cspan class=\"hljs-string\">&#x27;r&#x27;\u003C/span>, encoding=\u003Cspan class=\"hljs-string\">&#x27;utf-8&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n            content = f.read()\n            lines = content.split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>)\n        \n        self.file_cache[file_path] = {\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>: content, \u003Cspan class=\"hljs-string\">&#x27;lines&#x27;\u003C/span>: lines}\n        \n        \u003Cspan class=\"hljs-comment\"># Run validation rules\u003C/span>\n        self.validate_frontmatter(file_path, content, lines)\n        self.validate_headings(file_path, content, lines)\n        self.validate_links(file_path, content, lines)\n        self.validate_images(file_path, content, lines)\n        self.validate_content_structure(file_path, content, lines)\n        self.validate_code_blocks(file_path, content, lines)\n        self.validate_accessibility(file_path, content, lines)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> self.results\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_frontmatter\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate YAML frontmatter&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;frontmatter&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Extract frontmatter\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> content.startswith(\u003Cspan class=\"hljs-string\">&#x27;---&#x27;\u003C/span>):\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;frontmatter_missing&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">&#x27;Missing YAML frontmatter&#x27;\u003C/span>,\n                file_path=file_path,\n                line_number=\u003Cspan class=\"hljs-number\">1\u003C/span>,\n                fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add YAML frontmatter starting with ---&#x27;\u003C/span>\n            ))\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Find frontmatter boundaries\u003C/span>\n        end_marker = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> i, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines[\u003Cspan class=\"hljs-number\">1\u003C/span>:], \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> line.strip() == \u003Cspan class=\"hljs-string\">&#x27;---&#x27;\u003C/span>:\n                end_marker = i\n                \u003Cspan class=\"hljs-keyword\">break\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> end_marker \u003Cspan class=\"hljs-keyword\">is\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>:\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;frontmatter_malformed&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">&#x27;Frontmatter not properly closed&#x27;\u003C/span>,\n                file_path=file_path,\n                line_number=\u003Cspan class=\"hljs-number\">1\u003C/span>,\n                fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add closing --- after frontmatter&#x27;\u003C/span>\n            ))\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Parse frontmatter YAML\u003C/span>\n        frontmatter_lines = lines[\u003Cspan class=\"hljs-number\">1\u003C/span>:end_marker]\n        frontmatter_text = \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>.join(frontmatter_lines)\n        \n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            frontmatter = yaml.safe_load(frontmatter_text)\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> yaml.YAMLError \u003Cspan class=\"hljs-keyword\">as\u003C/span> e:\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;frontmatter_yaml_error&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">f&#x27;Invalid YAML in frontmatter: \u003Cspan class=\"hljs-subst\">{e}\u003C/span>&#x27;\u003C/span>,\n                file_path=file_path,\n                line_number=\u003Cspan class=\"hljs-number\">1\u003C/span>,\n                context=frontmatter_text[:\u003Cspan class=\"hljs-number\">100\u003C/span>]\n            ))\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-built_in\">isinstance\u003C/span>(frontmatter, \u003Cspan class=\"hljs-built_in\">dict\u003C/span>):\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;frontmatter_not_dict&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">&#x27;Frontmatter must be a YAML dictionary&#x27;\u003C/span>,\n                file_path=file_path,\n                line_number=\u003Cspan class=\"hljs-number\">1\u003C/span>\n            ))\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Check required fields\u003C/span>\n        required_fields = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;frontmatter&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;required_fields&#x27;\u003C/span>]\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> field \u003Cspan class=\"hljs-keyword\">in\u003C/span> required_fields:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> field \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> frontmatter \u003Cspan class=\"hljs-keyword\">or\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> frontmatter[field]:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">f&#x27;frontmatter_missing_\u003Cspan class=\"hljs-subst\">{field}\u003C/span>&#x27;\u003C/span>,\n                    severity=ValidationSeverity.ERROR,\n                    message=\u003Cspan class=\"hljs-string\">f&#x27;Missing required frontmatter field: \u003Cspan class=\"hljs-subst\">{field}\u003C/span>&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=self.find_field_line(frontmatter_lines, field),\n                    fix_suggestion=\u003Cspan class=\"hljs-string\">f&#x27;Add \u003Cspan class=\"hljs-subst\">{field}\u003C/span>: &quot;value&quot; to frontmatter&#x27;\u003C/span>\n                ))\n        \n        \u003Cspan class=\"hljs-comment\"># Validate field constraints\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;title&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> frontmatter:\n            title_length = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(\u003Cspan class=\"hljs-built_in\">str\u003C/span>(frontmatter[\u003Cspan class=\"hljs-string\">&#x27;title&#x27;\u003C/span>]))\n            max_length = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;frontmatter&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;title_max_length&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> title_length &gt; max_length:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;frontmatter_title_too_long&#x27;\u003C/span>,\n                    severity=ValidationSeverity.WARNING,\n                    message=\u003Cspan class=\"hljs-string\">f&#x27;Title too long (\u003Cspan class=\"hljs-subst\">{title_length}\u003C/span> chars, max \u003Cspan class=\"hljs-subst\">{max_length}\u003C/span>)&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=self.find_field_line(frontmatter_lines, \u003Cspan class=\"hljs-string\">&#x27;title&#x27;\u003C/span>)\n                ))\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;description&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> frontmatter:\n            desc_length = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(\u003Cspan class=\"hljs-built_in\">str\u003C/span>(frontmatter[\u003Cspan class=\"hljs-string\">&#x27;description&#x27;\u003C/span>]))\n            max_length = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;frontmatter&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;description_max_length&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> desc_length &gt; max_length:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;frontmatter_description_too_long&#x27;\u003C/span>,\n                    severity=ValidationSeverity.WARNING,\n                    message=\u003Cspan class=\"hljs-string\">f&#x27;Description too long (\u003Cspan class=\"hljs-subst\">{desc_length}\u003C/span> chars, max \u003Cspan class=\"hljs-subst\">{max_length}\u003C/span>)&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=self.find_field_line(frontmatter_lines, \u003Cspan class=\"hljs-string\">&#x27;description&#x27;\u003C/span>)\n                ))\n        \n        \u003Cspan class=\"hljs-comment\"># Validate date format\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> frontmatter:\n            date_format = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;frontmatter&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;date_format&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                datetime.strptime(\u003Cspan class=\"hljs-built_in\">str\u003C/span>(frontmatter[\u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>]), date_format)\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span> ValueError:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;frontmatter_invalid_date&#x27;\u003C/span>,\n                    severity=ValidationSeverity.ERROR,\n                    message=\u003Cspan class=\"hljs-string\">f&#x27;Invalid date format, expected \u003Cspan class=\"hljs-subst\">{date_format}\u003C/span>&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=self.find_field_line(frontmatter_lines, \u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>),\n                    fix_suggestion=\u003Cspan class=\"hljs-string\">f&#x27;Use date format: \u003Cspan class=\"hljs-subst\">{date_format}\u003C/span>&#x27;\u003C/span>\n                ))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">find_field_line\u003C/span>(\u003Cspan class=\"hljs-params\">self, frontmatter_lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>], field: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">int\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Find line number of a frontmatter field&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> i, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(frontmatter_lines, \u003Cspan class=\"hljs-number\">2\u003C/span>):  \u003Cspan class=\"hljs-comment\"># +2 for 0-index and --- line\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> line.strip().startswith(\u003Cspan class=\"hljs-string\">f&#x27;\u003Cspan class=\"hljs-subst\">{field}\u003C/span>:&#x27;\u003C/span>):\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> i\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_headings\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate heading structure and formatting&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        heading_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;^(#{1,6})\\s+(.+)$&#x27;\u003C/span>)\n        found_h1 = \u003Cspan class=\"hljs-literal\">False\u003C/span>\n        seen_headings = \u003Cspan class=\"hljs-built_in\">set\u003C/span>()\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">match\u003C/span> = heading_pattern.\u003Cspan class=\"hljs-keyword\">match\u003C/span>(line)\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            level = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>))\n            heading_text = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">2\u003C/span>).strip()\n            \n            \u003Cspan class=\"hljs-comment\"># Check for H1\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> level == \u003Cspan class=\"hljs-number\">1\u003C/span>:\n                found_h1 = \u003Cspan class=\"hljs-literal\">True\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Check for empty headings\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;no_empty_headings&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> heading_text:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;heading_empty&#x27;\u003C/span>,\n                    severity=ValidationSeverity.ERROR,\n                    message=\u003Cspan class=\"hljs-string\">&#x27;Empty heading found&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=line_num,\n                    context=line,\n                    fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add content to the heading or remove it&#x27;\u003C/span>\n                ))\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Check heading length\u003C/span>\n            max_length = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;max_heading_length&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(heading_text) &gt; max_length:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;heading_too_long&#x27;\u003C/span>,\n                    severity=ValidationSeverity.WARNING,\n                    message=\u003Cspan class=\"hljs-string\">f&#x27;Heading too long (\u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(heading_text)}\u003C/span> chars, max \u003Cspan class=\"hljs-subst\">{max_length}\u003C/span>)&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=line_num,\n                    context=heading_text[:\u003Cspan class=\"hljs-number\">50\u003C/span>] + \u003Cspan class=\"hljs-string\">&#x27;...&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(heading_text) &gt; \u003Cspan class=\"hljs-number\">50\u003C/span> \u003Cspan class=\"hljs-keyword\">else\u003C/span> heading_text\n                ))\n            \n            \u003Cspan class=\"hljs-comment\"># Check for duplicate headings\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;no_duplicate_headings&#x27;\u003C/span>]:\n                heading_lower = heading_text.lower()\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> heading_lower \u003Cspan class=\"hljs-keyword\">in\u003C/span> seen_headings:\n                    self.results.append(ValidationResult(\n                        rule_id=\u003Cspan class=\"hljs-string\">&#x27;heading_duplicate&#x27;\u003C/span>,\n                        severity=ValidationSeverity.WARNING,\n                        message=\u003Cspan class=\"hljs-string\">f&#x27;Duplicate heading: \u003Cspan class=\"hljs-subst\">{heading_text}\u003C/span>&#x27;\u003C/span>,\n                        file_path=file_path,\n                        line_number=line_num,\n                        context=heading_text\n                    ))\n                seen_headings.add(heading_lower)\n            \n            \u003Cspan class=\"hljs-comment\"># Check heading case\u003C/span>\n            case_style = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;heading_case&#x27;\u003C/span>]\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> case_style == \u003Cspan class=\"hljs-string\">&#x27;title&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">and\u003C/span> heading_text != heading_text.title():\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;heading_case_title&#x27;\u003C/span>,\n                    severity=ValidationSeverity.INFO,\n                    message=\u003Cspan class=\"hljs-string\">&#x27;Heading should use title case&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=line_num,\n                    context=heading_text,\n                    fix_suggestion=\u003Cspan class=\"hljs-string\">f&#x27;Change to: \u003Cspan class=\"hljs-subst\">{heading_text.title()}\u003C/span>&#x27;\u003C/span>\n                ))\n        \n        \u003Cspan class=\"hljs-comment\"># Check for required H1\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;headings&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;require_h1&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> found_h1:\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;heading_missing_h1&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">&#x27;Document missing H1 heading&#x27;\u003C/span>,\n                file_path=file_path,\n                line_number=\u003Cspan class=\"hljs-number\">1\u003C/span>,\n                fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add a main heading with # at the top of the document&#x27;\u003C/span>\n            ))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_links\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate internal and external links&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Find all markdown links\u003C/span>\n        link_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;\\[([^\\]]*)\\]\\(([^)]+)\\)&#x27;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> link_pattern.finditer(line):\n                link_text = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>)\n                link_url = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">2\u003C/span>)\n                \n                \u003Cspan class=\"hljs-comment\"># Skip empty links\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> link_url:\n                    self.results.append(ValidationResult(\n                        rule_id=\u003Cspan class=\"hljs-string\">&#x27;link_empty_url&#x27;\u003C/span>,\n                        severity=ValidationSeverity.ERROR,\n                        message=\u003Cspan class=\"hljs-string\">&#x27;Link with empty URL&#x27;\u003C/span>,\n                        file_path=file_path,\n                        line_number=line_num,\n                        context=\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>)\n                    ))\n                    \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n                \n                \u003Cspan class=\"hljs-comment\"># Check link text\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> link_text:\n                    self.results.append(ValidationResult(\n                        rule_id=\u003Cspan class=\"hljs-string\">&#x27;link_empty_text&#x27;\u003C/span>,\n                        severity=ValidationSeverity.WARNING,\n                        message=\u003Cspan class=\"hljs-string\">&#x27;Link with empty text&#x27;\u003C/span>,\n                        file_path=file_path,\n                        line_number=line_num,\n                        context=\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>),\n                        fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add descriptive link text&#x27;\u003C/span>\n                    ))\n                \n                \u003Cspan class=\"hljs-comment\"># Validate internal links\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;check_internal&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">and\u003C/span> self.is_internal_link(link_url):\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.validate_internal_link(file_path, link_url):\n                        self.results.append(ValidationResult(\n                            rule_id=\u003Cspan class=\"hljs-string\">&#x27;link_broken_internal&#x27;\u003C/span>,\n                            severity=ValidationSeverity.ERROR,\n                            message=\u003Cspan class=\"hljs-string\">f&#x27;Broken internal link: \u003Cspan class=\"hljs-subst\">{link_url}\u003C/span>&#x27;\u003C/span>,\n                            file_path=file_path,\n                            line_number=line_num,\n                            context=\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>)\n                        ))\n                \n                \u003Cspan class=\"hljs-comment\"># Validate external links\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;check_external&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">and\u003C/span> self.is_external_link(link_url):\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.validate_external_link(link_url):\n                        self.results.append(ValidationResult(\n                            rule_id=\u003Cspan class=\"hljs-string\">&#x27;link_broken_external&#x27;\u003C/span>,\n                            severity=ValidationSeverity.WARNING,\n                            message=\u003Cspan class=\"hljs-string\">f&#x27;Broken external link: \u003Cspan class=\"hljs-subst\">{link_url}\u003C/span>&#x27;\u003C/span>,\n                            file_path=file_path,\n                            line_number=line_num,\n                            context=\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>)\n                        ))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">is_internal_link\u003C/span>(\u003Cspan class=\"hljs-params\">self, url: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">bool\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check if URL is an internal link&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> url.startswith((\u003Cspan class=\"hljs-string\">&#x27;http://&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;https://&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;mailto:&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;tel:&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;ftp://&#x27;\u003C/span>))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">is_external_link\u003C/span>(\u003Cspan class=\"hljs-params\">self, url: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">bool\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check if URL is an external link&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> url.startswith((\u003Cspan class=\"hljs-string\">&#x27;http://&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;https://&#x27;\u003C/span>))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_internal_link\u003C/span>(\u003Cspan class=\"hljs-params\">self, base_file: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, link_url: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">bool\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate internal link exists&quot;&quot;&quot;\u003C/span>\n        base_dir = os.path.dirname(base_file)\n        \n        \u003Cspan class=\"hljs-comment\"># Handle fragments\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;#&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> link_url:\n            file_part, fragment = link_url.split(\u003Cspan class=\"hljs-string\">&#x27;#&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">1\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> file_part:  \u003Cspan class=\"hljs-comment\"># Same-page fragment\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> self.validate_fragment(base_file, fragment)\n            link_url = file_part\n        \n        \u003Cspan class=\"hljs-comment\"># Resolve relative path\u003C/span>\n        target_path = os.path.normpath(os.path.join(base_dir, link_url))\n        \n        \u003Cspan class=\"hljs-comment\"># Check if file exists\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> os.path.exists(target_path):\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">True\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Try with .md extension if not present\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> target_path.endswith(\u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> os.path.exists(target_path + \u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>):\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">True\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">False\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_external_link\u003C/span>(\u003Cspan class=\"hljs-params\">self, url: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">bool\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate external link is accessible&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            timeout = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;timeout&#x27;\u003C/span>]\n            retry_count = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;retry_count&#x27;\u003C/span>]\n            \n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> attempt \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">range\u003C/span>(retry_count + \u003Cspan class=\"hljs-number\">1\u003C/span>):\n                \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                    response = requests.head(url, timeout=timeout, allow_redirects=\u003Cspan class=\"hljs-literal\">True\u003C/span>)\n                    \u003Cspan class=\"hljs-keyword\">return\u003C/span> response.status_code &lt; \u003Cspan class=\"hljs-number\">400\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">except\u003C/span> requests.RequestException:\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> attempt == retry_count:\n                        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">False\u003C/span>\n                    \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> Exception:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">False\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_fragment\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, fragment: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">bool\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check if fragment/anchor exists in file&quot;&quot;&quot;\u003C/span>\n        content = self.file_cache[file_path][\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>]\n        \n        \u003Cspan class=\"hljs-comment\"># Look for heading that matches fragment\u003C/span>\n        heading_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;^#+\\s+(.+)$&#x27;\u003C/span>, re.MULTILINE)\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> heading_pattern.finditer(content):\n            heading_text = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>)\n            \u003Cspan class=\"hljs-comment\"># Convert heading to URL fragment format\u003C/span>\n            heading_fragment = re.sub(\u003Cspan class=\"hljs-string\">r&#x27;[^a-zA-Z0-9\\-_]&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;-&#x27;\u003C/span>, heading_text.lower())\n            heading_fragment = re.sub(\u003Cspan class=\"hljs-string\">r&#x27;-+&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;-&#x27;\u003C/span>, heading_fragment).strip(\u003Cspan class=\"hljs-string\">&#x27;-&#x27;\u003C/span>)\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> heading_fragment == fragment:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">True\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">False\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_images\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate image references and properties&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        image_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;!\\[([^\\]]*)\\]\\(([^)]+)\\)&#x27;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> image_pattern.finditer(line):\n                alt_text = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>)\n                image_url = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">2\u003C/span>)\n                \n                \u003Cspan class=\"hljs-comment\"># Check alt text\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;require_alt_text&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> alt_text:\n                    self.results.append(ValidationResult(\n                        rule_id=\u003Cspan class=\"hljs-string\">&#x27;image_missing_alt&#x27;\u003C/span>,\n                        severity=ValidationSeverity.WARNING,\n                        message=\u003Cspan class=\"hljs-string\">&#x27;Image missing alt text&#x27;\u003C/span>,\n                        file_path=file_path,\n                        line_number=line_num,\n                        context=\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>),\n                        fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add descriptive alt text for accessibility&#x27;\u003C/span>\n                    ))\n                \n                \u003Cspan class=\"hljs-comment\"># Validate image file\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.is_internal_link(image_url):\n                    self.validate_image_file(file_path, image_url, line_num, \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_image_file\u003C/span>(\u003Cspan class=\"hljs-params\">self, base_file: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, image_url: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, line_num: \u003Cspan class=\"hljs-built_in\">int\u003C/span>, context: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate image file properties&quot;&quot;&quot;\u003C/span>\n        base_dir = os.path.dirname(base_file)\n        image_path = os.path.normpath(os.path.join(base_dir, image_url))\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> os.path.exists(image_path):\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;image_file_missing&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">f&#x27;Image file not found: \u003Cspan class=\"hljs-subst\">{image_url}\u003C/span>&#x27;\u003C/span>,\n                file_path=base_file,\n                line_number=line_num,\n                context=context\n            ))\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Check file extension\u003C/span>\n        allowed_formats = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;allowed_formats&#x27;\u003C/span>]\n        file_ext = os.path.splitext(image_path)[\u003Cspan class=\"hljs-number\">1\u003C/span>].lower().lstrip(\u003Cspan class=\"hljs-string\">&#x27;.&#x27;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> file_ext \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> allowed_formats:\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;image_invalid_format&#x27;\u003C/span>,\n                severity=ValidationSeverity.WARNING,\n                message=\u003Cspan class=\"hljs-string\">f&#x27;Image format not allowed: \u003Cspan class=\"hljs-subst\">{file_ext}\u003C/span> (allowed: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-string\">&quot;, &quot;\u003C/span>.join(allowed_formats)}\u003C/span>)&#x27;\u003C/span>,\n                file_path=base_file,\n                line_number=line_num,\n                context=context\n            ))\n        \n        \u003Cspan class=\"hljs-comment\"># Check file size\u003C/span>\n        file_size_mb = os.path.getsize(image_path) / (\u003Cspan class=\"hljs-number\">1024\u003C/span> * \u003Cspan class=\"hljs-number\">1024\u003C/span>)\n        max_size = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;images&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;max_size_mb&#x27;\u003C/span>]\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> file_size_mb &gt; max_size:\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;image_too_large&#x27;\u003C/span>,\n                severity=ValidationSeverity.WARNING,\n                message=\u003Cspan class=\"hljs-string\">f&#x27;Image too large: \u003Cspan class=\"hljs-subst\">{file_size_mb:\u003Cspan class=\"hljs-number\">.1\u003C/span>f}\u003C/span>MB (max \u003Cspan class=\"hljs-subst\">{max_size}\u003C/span>MB)&#x27;\u003C/span>,\n                file_path=base_file,\n                line_number=line_num,\n                context=context,\n                fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Optimize image size or use web-optimized format&#x27;\u003C/span>\n            ))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_content_structure\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate overall content structure and formatting&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Word count check\u003C/span>\n        word_count = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(content.split())\n        min_words = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;min_word_count&#x27;\u003C/span>]\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> word_count &lt; min_words:\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;content_too_short&#x27;\u003C/span>,\n                severity=ValidationSeverity.INFO,\n                message=\u003Cspan class=\"hljs-string\">f&#x27;Content may be too short: \u003Cspan class=\"hljs-subst\">{word_count}\u003C/span> words (min \u003Cspan class=\"hljs-subst\">{min_words}\u003C/span>)&#x27;\u003C/span>,\n                file_path=file_path,\n                line_number=\u003Cspan class=\"hljs-number\">1\u003C/span>\n            ))\n        \n        \u003Cspan class=\"hljs-comment\"># Line length check\u003C/span>\n        max_line_length = self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;max_line_length&#x27;\u003C/span>]\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(line) &gt; max_line_length:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;line_too_long&#x27;\u003C/span>,\n                    severity=ValidationSeverity.INFO,\n                    message=\u003Cspan class=\"hljs-string\">f&#x27;Line too long: \u003Cspan class=\"hljs-subst\">{\u003Cspan class=\"hljs-built_in\">len\u003C/span>(line)}\u003C/span> chars (max \u003Cspan class=\"hljs-subst\">{max_line_length}\u003C/span>)&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=line_num,\n                    context=line[:\u003Cspan class=\"hljs-number\">50\u003C/span>] + \u003Cspan class=\"hljs-string\">&#x27;...&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(line) &gt; \u003Cspan class=\"hljs-number\">50\u003C/span> \u003Cspan class=\"hljs-keyword\">else\u003C/span> line\n                ))\n        \n        \u003Cspan class=\"hljs-comment\"># Trailing whitespace check\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;content&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;no_trailing_whitespace&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> line.endswith(\u003Cspan class=\"hljs-string\">&#x27; &#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">or\u003C/span> line.endswith(\u003Cspan class=\"hljs-string\">&#x27;\\t&#x27;\u003C/span>):\n                    self.results.append(ValidationResult(\n                        rule_id=\u003Cspan class=\"hljs-string\">&#x27;trailing_whitespace&#x27;\u003C/span>,\n                        severity=ValidationSeverity.INFO,\n                        message=\u003Cspan class=\"hljs-string\">&#x27;Line has trailing whitespace&#x27;\u003C/span>,\n                        file_path=file_path,\n                        line_number=line_num,\n                        fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Remove trailing whitespace&#x27;\u003C/span>\n                    ))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_code_blocks\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate code blocks and syntax&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        code_block_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;^```(\\w*)$&#x27;\u003C/span>)\n        in_code_block = \u003Cspan class=\"hljs-literal\">False\u003C/span>\n        code_language = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n        code_start_line = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">match\u003C/span> = code_block_pattern.\u003Cspan class=\"hljs-keyword\">match\u003C/span>(line)\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> in_code_block:\n                \u003Cspan class=\"hljs-comment\"># Start of code block\u003C/span>\n                in_code_block = \u003Cspan class=\"hljs-literal\">True\u003C/span>\n                code_language = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>)\n                code_start_line = line_num\n                \n                \u003Cspan class=\"hljs-comment\"># Check for language tag\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;require_language_tags&#x27;\u003C/span>] \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> code_language:\n                    self.results.append(ValidationResult(\n                        rule_id=\u003Cspan class=\"hljs-string\">&#x27;code_block_missing_language&#x27;\u003C/span>,\n                        severity=ValidationSeverity.WARNING,\n                        message=\u003Cspan class=\"hljs-string\">&#x27;Code block missing language tag&#x27;\u003C/span>,\n                        file_path=file_path,\n                        line_number=line_num,\n                        context=line,\n                        fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add language identifier after ```&#x27;\u003C/span>\n                    ))\n                    \n            \u003Cspan class=\"hljs-keyword\">elif\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">and\u003C/span> in_code_block:\n                \u003Cspan class=\"hljs-comment\"># End of code block\u003C/span>\n                in_code_block = \u003Cspan class=\"hljs-literal\">False\u003C/span>\n                code_language = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n                code_start_line = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n                \n            \u003Cspan class=\"hljs-keyword\">elif\u003C/span> in_code_block:\n                \u003Cspan class=\"hljs-comment\"># Inside code block - check for secrets\u003C/span>\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;code_blocks&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;no_hardcoded_secrets&#x27;\u003C/span>]:\n                    self.check_for_secrets(file_path, line, line_num)\n        \n        \u003Cspan class=\"hljs-comment\"># Check for unclosed code blocks\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> in_code_block:\n            self.results.append(ValidationResult(\n                rule_id=\u003Cspan class=\"hljs-string\">&#x27;code_block_unclosed&#x27;\u003C/span>,\n                severity=ValidationSeverity.ERROR,\n                message=\u003Cspan class=\"hljs-string\">&#x27;Unclosed code block&#x27;\u003C/span>,\n                file_path=file_path,\n                line_number=code_start_line,\n                fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add closing ``` to close the code block&#x27;\u003C/span>\n            ))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">check_for_secrets\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, line: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, line_num: \u003Cspan class=\"hljs-built_in\">int\u003C/span>\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check for hardcoded secrets in code&quot;&quot;&quot;\u003C/span>\n        secret_patterns = [\n            \u003Cspan class=\"hljs-string\">r&#x27;(?i)(password|pwd|pass)\\s*[=:]\\s*[&quot;\\&#x27;]?[a-zA-Z0-9!@#$%^&amp;*()_+\\-=\\[\\]{};\\&#x27;:&quot;\\\\|,.&lt;&gt;/?]{8,}&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">r&#x27;(?i)(api[_-]?key|apikey)\\s*[=:]\\s*[&quot;\\&#x27;]?[a-zA-Z0-9]{20,}&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">r&#x27;(?i)(secret|token)\\s*[=:]\\s*[&quot;\\&#x27;]?[a-zA-Z0-9]{16,}&#x27;\u003C/span>,\n            \u003Cspan class=\"hljs-string\">r&#x27;(?i)(private[_-]?key)\\s*[=:]\\s*[&quot;\\&#x27;]?-----BEGIN&#x27;\u003C/span>,\n        ]\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> pattern \u003Cspan class=\"hljs-keyword\">in\u003C/span> secret_patterns:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> re.search(pattern, line):\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;code_hardcoded_secret&#x27;\u003C/span>,\n                    severity=ValidationSeverity.WARNING,\n                    message=\u003Cspan class=\"hljs-string\">&#x27;Possible hardcoded secret detected&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=line_num,\n                    context=line[:\u003Cspan class=\"hljs-number\">50\u003C/span>] + \u003Cspan class=\"hljs-string\">&#x27;...&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(line) &gt; \u003Cspan class=\"hljs-number\">50\u003C/span> \u003Cspan class=\"hljs-keyword\">else\u003C/span> line,\n                    fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Use environment variables or placeholders for secrets&#x27;\u003C/span>\n                ))\n                \u003Cspan class=\"hljs-keyword\">break\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_accessibility\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate accessibility compliance&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;accessibility&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Check heading hierarchy\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;accessibility&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;heading_hierarchy&#x27;\u003C/span>]:\n            self.validate_heading_hierarchy(file_path, lines)\n        \n        \u003Cspan class=\"hljs-comment\"># Check descriptive link text\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;accessibility&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;link_text_descriptive&#x27;\u003C/span>]:\n            self.validate_descriptive_links(file_path, lines)\n        \n        \u003Cspan class=\"hljs-comment\"># Check table headers\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> self.config[\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;accessibility&#x27;\u003C/span>][\u003Cspan class=\"hljs-string\">&#x27;table_headers&#x27;\u003C/span>]:\n            self.validate_table_headers(file_path, lines)\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_heading_hierarchy\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check proper heading hierarchy (no skipping levels)&quot;&quot;&quot;\u003C/span>\n        heading_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;^(#{1,6})\\s+(.+)$&#x27;\u003C/span>)\n        previous_level = \u003Cspan class=\"hljs-number\">0\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">match\u003C/span> = heading_pattern.\u003Cspan class=\"hljs-keyword\">match\u003C/span>(line)\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            current_level = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>))\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> previous_level &gt; \u003Cspan class=\"hljs-number\">0\u003C/span> \u003Cspan class=\"hljs-keyword\">and\u003C/span> current_level &gt; previous_level + \u003Cspan class=\"hljs-number\">1\u003C/span>:\n                self.results.append(ValidationResult(\n                    rule_id=\u003Cspan class=\"hljs-string\">&#x27;accessibility_heading_hierarchy&#x27;\u003C/span>,\n                    severity=ValidationSeverity.WARNING,\n                    message=\u003Cspan class=\"hljs-string\">f&#x27;Heading level skipped (h\u003Cspan class=\"hljs-subst\">{previous_level}\u003C/span> -&gt; h\u003Cspan class=\"hljs-subst\">{current_level}\u003C/span>)&#x27;\u003C/span>,\n                    file_path=file_path,\n                    line_number=line_num,\n                    context=line,\n                    fix_suggestion=\u003Cspan class=\"hljs-string\">f&#x27;Use h\u003Cspan class=\"hljs-subst\">{previous_level + \u003Cspan class=\"hljs-number\">1\u003C/span>}\u003C/span> instead of h\u003Cspan class=\"hljs-subst\">{current_level}\u003C/span>&#x27;\u003C/span>\n                ))\n            \n            previous_level = current_level\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_descriptive_links\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check for non-descriptive link text&quot;&quot;&quot;\u003C/span>\n        link_pattern = re.\u003Cspan class=\"hljs-built_in\">compile\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;\\[([^\\]]*)\\]\\(([^)]+)\\)&#x27;\u003C/span>)\n        non_descriptive = [\u003Cspan class=\"hljs-string\">&#x27;click here&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;read more&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;here&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;link&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;more&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;this&#x27;\u003C/span>]\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> \u003Cspan class=\"hljs-keyword\">match\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> link_pattern.finditer(line):\n                link_text = \u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">1\u003C/span>).lower().strip()\n                \n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> link_text \u003Cspan class=\"hljs-keyword\">in\u003C/span> non_descriptive:\n                    self.results.append(ValidationResult(\n                        rule_id=\u003Cspan class=\"hljs-string\">&#x27;accessibility_link_text&#x27;\u003C/span>,\n                        severity=ValidationSeverity.INFO,\n                        message=\u003Cspan class=\"hljs-string\">f&#x27;Non-descriptive link text: &quot;\u003Cspan class=\"hljs-subst\">{link_text}\u003C/span>&quot;&#x27;\u003C/span>,\n                        file_path=file_path,\n                        line_number=line_num,\n                        context=\u003Cspan class=\"hljs-keyword\">match\u003C/span>.group(\u003Cspan class=\"hljs-number\">0\u003C/span>),\n                        fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Use descriptive text that explains the link destination&#x27;\u003C/span>\n                    ))\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_table_headers\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check that tables have proper headers&quot;&quot;&quot;\u003C/span>\n        in_table = \u003Cspan class=\"hljs-literal\">False\u003C/span>\n        table_start = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> line_num, line \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">enumerate\u003C/span>(lines, \u003Cspan class=\"hljs-number\">1\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;|&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> line \u003Cspan class=\"hljs-keyword\">and\u003C/span> line.strip().startswith(\u003Cspan class=\"hljs-string\">&#x27;|&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">and\u003C/span> line.strip().endswith(\u003Cspan class=\"hljs-string\">&#x27;|&#x27;\u003C/span>):\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> in_table:\n                    in_table = \u003Cspan class=\"hljs-literal\">True\u003C/span>\n                    table_start = line_num\n                    \n                    \u003Cspan class=\"hljs-comment\"># Check if next line is separator\u003C/span>\n                    \u003Cspan class=\"hljs-keyword\">if\u003C/span> line_num &lt; \u003Cspan class=\"hljs-built_in\">len\u003C/span>(lines):\n                        next_line = lines[line_num]  \u003Cspan class=\"hljs-comment\"># line_num is 1-indexed\u003C/span>\n                        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> re.\u003Cspan class=\"hljs-keyword\">match\u003C/span>(\u003Cspan class=\"hljs-string\">r&#x27;^\\|[\\s\\-\\|:]+\\|$&#x27;\u003C/span>, next_line.strip()):\n                            self.results.append(ValidationResult(\n                                rule_id=\u003Cspan class=\"hljs-string\">&#x27;accessibility_table_headers&#x27;\u003C/span>,\n                                severity=ValidationSeverity.INFO,\n                                message=\u003Cspan class=\"hljs-string\">&#x27;Table may be missing header row&#x27;\u003C/span>,\n                                file_path=file_path,\n                                line_number=table_start,\n                                context=line,\n                                fix_suggestion=\u003Cspan class=\"hljs-string\">&#x27;Add header row with | --- | separators&#x27;\u003C/span>\n                            ))\n            \u003Cspan class=\"hljs-keyword\">elif\u003C/span> in_table \u003Cspan class=\"hljs-keyword\">and\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;|&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> line:\n                in_table = \u003Cspan class=\"hljs-literal\">False\u003C/span>\n                table_start = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">generate_report\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Generate comprehensive validation report&quot;&quot;&quot;\u003C/span>\n        total_results = \u003Cspan class=\"hljs-built_in\">len\u003C/span>(self.results)\n        \n        \u003Cspan class=\"hljs-comment\"># Count by severity\u003C/span>\n        severity_counts = {\n            ValidationSeverity.ERROR: \u003Cspan class=\"hljs-number\">0\u003C/span>,\n            ValidationSeverity.WARNING: \u003Cspan class=\"hljs-number\">0\u003C/span>,\n            ValidationSeverity.INFO: \u003Cspan class=\"hljs-number\">0\u003C/span>\n        }\n        \n        \u003Cspan class=\"hljs-comment\"># Count by rule\u003C/span>\n        rule_counts = {}\n        \n        \u003Cspan class=\"hljs-comment\"># Group by file\u003C/span>\n        file_results = {}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> result \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.results:\n            severity_counts[result.severity] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            rule_counts[result.rule_id] = rule_counts.get(result.rule_id, \u003Cspan class=\"hljs-number\">0\u003C/span>) + \u003Cspan class=\"hljs-number\">1\u003C/span>\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> result.file_path \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> file_results:\n                file_results[result.file_path] = []\n            file_results[result.file_path].append(result)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;summary&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;total_issues&#x27;\u003C/span>: total_results,\n                \u003Cspan class=\"hljs-string\">&#x27;errors&#x27;\u003C/span>: severity_counts[ValidationSeverity.ERROR],\n                \u003Cspan class=\"hljs-string\">&#x27;warnings&#x27;\u003C/span>: severity_counts[ValidationSeverity.WARNING],\n                \u003Cspan class=\"hljs-string\">&#x27;info&#x27;\u003C/span>: severity_counts[ValidationSeverity.INFO],\n                \u003Cspan class=\"hljs-string\">&#x27;files_with_issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(file_results),\n                \u003Cspan class=\"hljs-string\">&#x27;most_common_issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">sorted\u003C/span>(rule_counts.items(), key=\u003Cspan class=\"hljs-keyword\">lambda\u003C/span> x: x[\u003Cspan class=\"hljs-number\">1\u003C/span>], reverse=\u003Cspan class=\"hljs-literal\">True\u003C/span>)[:\u003Cspan class=\"hljs-number\">5\u003C/span>]\n            },\n            \u003Cspan class=\"hljs-string\">&#x27;results_by_file&#x27;\u003C/span>: file_results,\n            \u003Cspan class=\"hljs-string\">&#x27;all_results&#x27;\u003C/span>: [self.result_to_dict(r) \u003Cspan class=\"hljs-keyword\">for\u003C/span> r \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.results],\n            \u003Cspan class=\"hljs-string\">&#x27;generated_at&#x27;\u003C/span>: datetime.now().isoformat()\n        }\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">result_to_dict\u003C/span>(\u003Cspan class=\"hljs-params\">self, result: ValidationResult\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Convert ValidationResult to dictionary&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;rule_id&#x27;\u003C/span>: result.rule_id,\n            \u003Cspan class=\"hljs-string\">&#x27;severity&#x27;\u003C/span>: result.severity.value,\n            \u003Cspan class=\"hljs-string\">&#x27;message&#x27;\u003C/span>: result.message,\n            \u003Cspan class=\"hljs-string\">&#x27;file_path&#x27;\u003C/span>: result.file_path,\n            \u003Cspan class=\"hljs-string\">&#x27;line_number&#x27;\u003C/span>: result.line_number,\n            \u003Cspan class=\"hljs-string\">&#x27;column&#x27;\u003C/span>: result.column,\n            \u003Cspan class=\"hljs-string\">&#x27;context&#x27;\u003C/span>: result.context,\n            \u003Cspan class=\"hljs-string\">&#x27;fix_suggestion&#x27;\u003C/span>: result.fix_suggestion\n        }\n\n\u003Cspan class=\"hljs-comment\"># CLI interface\u003C/span>\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> __name__ == \u003Cspan class=\"hljs-string\">&quot;__main__&quot;\u003C/span>:\n    \u003Cspan class=\"hljs-keyword\">import\u003C/span> argparse\n    \n    parser = argparse.ArgumentParser(description=\u003Cspan class=\"hljs-string\">&#x27;Validate Markdown content&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;files&#x27;\u003C/span>, nargs=\u003Cspan class=\"hljs-string\">&#x27;+&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Files to validate&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--config&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;-c&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Configuration file path&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--output&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;-o&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Output file path&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--format&#x27;\u003C/span>, choices=[\u003Cspan class=\"hljs-string\">&#x27;json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>], default=\u003Cspan class=\"hljs-string\">&#x27;text&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Output format&#x27;\u003C/span>)\n    parser.add_argument(\u003Cspan class=\"hljs-string\">&#x27;--severity&#x27;\u003C/span>, choices=[\u003Cspan class=\"hljs-string\">&#x27;error&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;warning&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;info&#x27;\u003C/span>], default=\u003Cspan class=\"hljs-string\">&#x27;info&#x27;\u003C/span>, \u003Cspan class=\"hljs-built_in\">help\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;Minimum severity to report&#x27;\u003C/span>)\n    \n    args = parser.parse_args()\n    \n    validator = ContentValidator(args.config \u003Cspan class=\"hljs-keyword\">or\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;validation_config.yaml&#x27;\u003C/span>)\n    \n    all_results = []\n    \u003Cspan class=\"hljs-keyword\">for\u003C/span> file_path \u003Cspan class=\"hljs-keyword\">in\u003C/span> args.files:\n        results = validator.validate_file(file_path)\n        all_results.extend(results)\n    \n    \u003Cspan class=\"hljs-comment\"># Filter by severity\u003C/span>\n    severity_order = {\u003Cspan class=\"hljs-string\">&#x27;error&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;warning&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;info&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">2\u003C/span>}\n    min_severity = severity_order[args.severity]\n    \n    filtered_results = [r \u003Cspan class=\"hljs-keyword\">for\u003C/span> r \u003Cspan class=\"hljs-keyword\">in\u003C/span> all_results \u003Cspan class=\"hljs-keyword\">if\u003C/span> severity_order[r.severity.value] &lt;= min_severity]\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> args.\u003Cspan class=\"hljs-built_in\">format\u003C/span> == \u003Cspan class=\"hljs-string\">&#x27;json&#x27;\u003C/span>:\n        validator.results = filtered_results\n        report = validator.generate_report()\n        output = json.dumps(report, indent=\u003Cspan class=\"hljs-number\">2\u003C/span>)\n    \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n        output_lines = []\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> result \u003Cspan class=\"hljs-keyword\">in\u003C/span> filtered_results:\n            line = \u003Cspan class=\"hljs-string\">f&quot;\u003Cspan class=\"hljs-subst\">{result.file_path}\u003C/span>:\u003Cspan class=\"hljs-subst\">{result.line_number \u003Cspan class=\"hljs-keyword\">or\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>}\u003C/span>: \u003Cspan class=\"hljs-subst\">{result.severity.value}\u003C/span>: \u003Cspan class=\"hljs-subst\">{result.message}\u003C/span>&quot;\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> result.context:\n                line += \u003Cspan class=\"hljs-string\">f&quot; (context: \u003Cspan class=\"hljs-subst\">{result.context}\u003C/span>)&quot;\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> result.fix_suggestion:\n                line += \u003Cspan class=\"hljs-string\">f&quot; (fix: \u003Cspan class=\"hljs-subst\">{result.fix_suggestion}\u003C/span>)&quot;\u003C/span>\n            output_lines.append(line)\n        output = \u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>.join(output_lines)\n    \n    \u003Cspan class=\"hljs-keyword\">if\u003C/span> args.output:\n        \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(args.output, \u003Cspan class=\"hljs-string\">&#x27;w&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n            f.write(output)\n    \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n        \u003Cspan class=\"hljs-built_in\">print\u003C/span>(output)\n\u003C/code>\u003C/pre>\u003Ch3 id=\"advanced-validation-rules-engine\">Advanced Validation Rules Engine\u003C/h3>\n\u003Cp>Creating extensible validation systems with custom rule definitions:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-comment\"># validation_config.yaml - Comprehensive validation configuration\u003C/span>\n\u003Cspan class=\"hljs-attr\">rules:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">frontmatter:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">required_fields:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;title&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;description&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;author&#x27;\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">optional_fields:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;keywords&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;category&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;tags&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;image&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;layout&#x27;\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">field_validation:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">title:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">max_length:\u003C/span> \u003Cspan class=\"hljs-number\">100\u003C/span>\n        \u003Cspan class=\"hljs-attr\">min_length:\u003C/span> \u003Cspan class=\"hljs-number\">10\u003C/span>\n        \u003Cspan class=\"hljs-attr\">pattern:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;^[A-Z].*[^.]$&#x27;\u003C/span>  \u003Cspan class=\"hljs-comment\"># Start with capital, no trailing period\u003C/span>\n        \u003Cspan class=\"hljs-attr\">no_generic_words:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;Guide&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Tutorial&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Documentation&#x27;\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">description:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">max_length:\u003C/span> \u003Cspan class=\"hljs-number\">200\u003C/span>\n        \u003Cspan class=\"hljs-attr\">min_length:\u003C/span> \u003Cspan class=\"hljs-number\">50\u003C/span>\n        \u003Cspan class=\"hljs-attr\">unique_across_site:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">date:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">format:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;%Y-%m-%d&#x27;\u003C/span>\n        \u003Cspan class=\"hljs-attr\">not_future:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n        \u003Cspan class=\"hljs-attr\">not_older_than_days:\u003C/span> \u003Cspan class=\"hljs-number\">3650\u003C/span>  \u003Cspan class=\"hljs-comment\"># 10 years\u003C/span>\n      \u003Cspan class=\"hljs-attr\">keywords:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">min_count:\u003C/span> \u003Cspan class=\"hljs-number\">3\u003C/span>\n        \u003Cspan class=\"hljs-attr\">max_count:\u003C/span> \u003Cspan class=\"hljs-number\">12\u003C/span>\n        \u003Cspan class=\"hljs-attr\">lowercase_only:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n        \u003Cspan class=\"hljs-attr\">no_duplicates:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">category:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">allowed_values:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;Tutorial&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Guide&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Reference&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Blog&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;News&#x27;\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">author:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">required_format:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;First Last&#x27;\u003C/span>\n        \u003Cspan class=\"hljs-attr\">validate_against_team_list:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">content_quality:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">readability:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">min_flesch_reading_ease:\u003C/span> \u003Cspan class=\"hljs-number\">30\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_flesch_reading_ease:\u003C/span> \u003Cspan class=\"hljs-number\">90\u003C/span>\n      \u003Cspan class=\"hljs-attr\">warn_complex_sentences:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_sentence_length:\u003C/span> \u003Cspan class=\"hljs-number\">25\u003C/span>\n    \u003Cspan class=\"hljs-attr\">structure:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_paragraph_length:\u003C/span> \u003Cspan class=\"hljs-number\">150\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_introduction_paragraph:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_conclusion_paragraph:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_heading_depth:\u003C/span> \u003Cspan class=\"hljs-number\">6\u003C/span>\n      \u003Cspan class=\"hljs-attr\">balanced_content_distribution:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">terminology:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">consistent_spelling:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">technical_terms_glossary:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;glossary.yaml&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">brand_terms_consistency:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">forbidden_terms:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;obviously&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;simply&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;just&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;easy&#x27;\u003C/span>]\n\n  \u003Cspan class=\"hljs-attr\">links:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">internal_links:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">check_existence:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">allow_fragments:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">validate_anchors:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">prefer_relative_paths:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">warn_external_looking_internal:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">external_links:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">check_accessibility:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">timeout:\u003C/span> \u003Cspan class=\"hljs-number\">15\u003C/span>\n      \u003Cspan class=\"hljs-attr\">retry_count:\u003C/span> \u003Cspan class=\"hljs-number\">3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">check_redirects:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">warn_shortened_urls:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">allowed_domains:\u003C/span> []\n      \u003Cspan class=\"hljs-attr\">blocked_domains:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;bit.ly&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;tinyurl.com&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;t.co&#x27;\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">check_ssl_certificates:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">images:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">accessibility:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_alt_text:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">alt_text_min_length:\u003C/span> \u003Cspan class=\"hljs-number\">5\u003C/span>\n      \u003Cspan class=\"hljs-attr\">alt_text_max_length:\u003C/span> \u003Cspan class=\"hljs-number\">125\u003C/span>\n      \u003Cspan class=\"hljs-attr\">no_filename_alt_text:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">descriptive_alt_text_check:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">technical:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_file_size_mb:\u003C/span> \u003Cspan class=\"hljs-number\">5\u003C/span>\n      \u003Cspan class=\"hljs-attr\">allowed_formats:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;jpg&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;jpeg&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;png&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;gif&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;webp&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;svg&#x27;\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">min_dimensions:\u003C/span> [\u003Cspan class=\"hljs-number\">200\u003C/span>, \u003Cspan class=\"hljs-number\">200\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">max_dimensions:\u003C/span> [\u003Cspan class=\"hljs-number\">2000\u003C/span>, \u003Cspan class=\"hljs-number\">2000\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">check_image_optimization:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_responsive_images:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">organization:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">preferred_directory:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;assets/images&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">naming_convention:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;kebab-case&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_organized_subdirectories:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">code_blocks:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">syntax:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_language_tags:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">validate_syntax_highlighting:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">supported_languages:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;javascript&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;python&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;bash&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;yaml&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;html&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;css&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;sql&#x27;\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">warn_unsupported_languages:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">security:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">no_hardcoded_secrets:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">no_personal_information:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">warn_production_urls:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">scan_for_vulnerabilities:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">style:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_line_length:\u003C/span> \u003Cspan class=\"hljs-number\">120\u003C/span>\n      \u003Cspan class=\"hljs-attr\">consistent_indentation:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">no_trailing_whitespace:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_comments_for_complex_code:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">accessibility:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">headings:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">proper_hierarchy:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">descriptive_text:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">no_generic_headings:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_heading_length:\u003C/span> \u003Cspan class=\"hljs-number\">60\u003C/span>\n    \u003Cspan class=\"hljs-attr\">links:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">descriptive_text:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">no_generic_link_text:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">context_independent:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">keyboard_accessible:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">tables:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_headers:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">require_captions:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">proper_markup:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">responsive_design:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">media:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">alt_text_required:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">captions_for_videos:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">transcripts_for_audio:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">seo_optimization:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">meta_tags:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">title_length:\u003C/span> [\u003Cspan class=\"hljs-number\">30\u003C/span>, \u003Cspan class=\"hljs-number\">60\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">description_length:\u003C/span> [\u003Cspan class=\"hljs-number\">120\u003C/span>, \u003Cspan class=\"hljs-number\">160\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">keywords_relevance_check:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">unique_titles_across_site:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">content:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">keyword_density_check:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">heading_keyword_optimization:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">internal_linking_score:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">content_freshness_warnings:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">technical:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">structured_data_validation:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">canonical_urls:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">og_tags_validation:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">twitter_cards_validation:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n  \u003Cspan class=\"hljs-attr\">performance:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">enabled:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">file_sizes:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">max_markdown_size_kb:\u003C/span> \u003Cspan class=\"hljs-number\">500\u003C/span>\n      \u003Cspan class=\"hljs-attr\">warn_large_files:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">images:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">optimization_check:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">format_recommendations:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">lazy_loading_suggestions:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">external_resources:\u003C/span>\n      \u003Cspan class=\"hljs-attr\">minimize_external_requests:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">cdn_usage_recommendations:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">custom_rules:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">team_specific:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;brand_consistency&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">description:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;Check for consistent brand terminology&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">pattern:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;(?i)(our product|the platform|this tool)&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">suggestion:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;Use specific product names instead of generic terms&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">severity:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;info&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;documentation_templates&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">description:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;Ensure API documentation follows template structure&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">applies_to:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;content/api/**/*.md&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">required_sections:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;Overview&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Parameters&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Response&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Examples&#x27;\u003C/span>]\n      \u003Cspan class=\"hljs-attr\">severity:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;warning&#x27;\u003C/span>\n\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;changelog_format&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">description:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;Validate changelog entry format&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">applies_to:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;CHANGELOG.md&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">entry_pattern:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;^## \\[\\d+\\.\\d+\\.\\d+\\] - \\d{4}-\\d{2}-\\d{2}$&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">severity:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;error&#x27;\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">file_patterns:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">include:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;**/*.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;**/*.markdown&#x27;\u003C/span>]\n  \u003Cspan class=\"hljs-attr\">exclude:\u003C/span> \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;node_modules/**&#x27;\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;.git/**&#x27;\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;_site/**&#x27;\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;vendor/**&#x27;\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;**/README.md&#x27;\u003C/span>  \u003Cspan class=\"hljs-comment\"># Often have different standards\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;docs/archive/**&#x27;\u003C/span>  \u003Cspan class=\"hljs-comment\"># Archived content\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">output:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">formats:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;junit&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;sarif&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;checkstyle&#x27;\u003C/span>]\n  \u003Cspan class=\"hljs-attr\">console_output:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \u003Cspan class=\"hljs-attr\">detailed_reports:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \u003Cspan class=\"hljs-attr\">metrics_tracking:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \u003Cspan class=\"hljs-attr\">historical_comparison:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \n\u003Cspan class=\"hljs-attr\">quality_gates:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">max_errors:\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n  \u003Cspan class=\"hljs-attr\">max_warnings:\u003C/span> \u003Cspan class=\"hljs-number\">10\u003C/span>\n  \u003Cspan class=\"hljs-attr\">min_quality_score:\u003C/span> \u003Cspan class=\"hljs-number\">80\u003C/span>\n  \u003Cspan class=\"hljs-attr\">required_checks:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;frontmatter&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;accessibility&#x27;\u003C/span>]\n\n\u003Cspan class=\"hljs-attr\">integrations:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">github:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">create_issues_for_errors:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">comment_on_pull_requests:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \u003Cspan class=\"hljs-attr\">status_checks:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \u003Cspan class=\"hljs-attr\">slack:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">webhook_url:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;${SLACK_WEBHOOK_URL}&#x27;\u003C/span>\n    \u003Cspan class=\"hljs-attr\">notify_on_quality_regression:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n  \u003Cspan class=\"hljs-attr\">email:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">recipients:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;docs-team@company.com&#x27;\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">daily_summary:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n\u003C/code>\u003C/pre>\u003Ch2 id=\"cicd-integration-and-automation\">CI/CD Integration and Automation\u003C/h2>\n\u003Ch3 id=\"github-actions-workflow\">GitHub Actions Workflow\u003C/h3>\n\u003Cp>Implementing automated validation in continuous integration pipelines:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-yaml\">\u003Cspan class=\"hljs-comment\"># .github/workflows/content-validation.yml - Comprehensive content validation workflow\u003C/span>\n\u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Content\u003C/span> \u003Cspan class=\"hljs-string\">Validation\u003C/span> \u003Cspan class=\"hljs-string\">and\u003C/span> \u003Cspan class=\"hljs-string\">Quality\u003C/span> \u003Cspan class=\"hljs-string\">Assurance\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">on:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">push:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">branches:\u003C/span> [\u003Cspan class=\"hljs-string\">main\u003C/span>, \u003Cspan class=\"hljs-string\">develop\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">paths:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;**/*.md&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;**/*.markdown&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;content/**&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;docs/**&#x27;\u003C/span>\n  \u003Cspan class=\"hljs-attr\">pull_request:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">branches:\u003C/span> [\u003Cspan class=\"hljs-string\">main\u003C/span>, \u003Cspan class=\"hljs-string\">develop\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">paths:\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;**/*.md&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;**/*.markdown&#x27;\u003C/span> \n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;content/**&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;docs/**&#x27;\u003C/span>\n  \u003Cspan class=\"hljs-attr\">schedule:\u003C/span>\n    \u003Cspan class=\"hljs-comment\"># Run comprehensive validation weekly\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">cron:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;0 2 * * 1&#x27;\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">env:\u003C/span>\n  \u003Cspan class=\"hljs-attr\">NODE_VERSION:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;18&#x27;\u003C/span>\n  \u003Cspan class=\"hljs-attr\">PYTHON_VERSION:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;3.9&#x27;\u003C/span>\n\n\u003Cspan class=\"hljs-attr\">jobs:\u003C/span>\n  \u003Cspan class=\"hljs-comment\"># Fast validation for quick feedback\u003C/span>\n  \u003Cspan class=\"hljs-attr\">quick-validation:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.event_name\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;pull_request&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Checkout\u003C/span> \u003Cspan class=\"hljs-string\">repository\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">fetch-depth:\u003C/span> \u003Cspan class=\"hljs-number\">2\u003C/span>  \u003Cspan class=\"hljs-comment\"># Need depth for changed files detection\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Setup\u003C/span> \u003Cspan class=\"hljs-string\">Python\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-python@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">python-version:\u003C/span> \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">env.PYTHON_VERSION\u003C/span> \u003Cspan class=\"hljs-string\">}}\u003C/span>\n        \u003Cspan class=\"hljs-attr\">cache:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;pip&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Install\u003C/span> \u003Cspan class=\"hljs-string\">validation\u003C/span> \u003Cspan class=\"hljs-string\">tools\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        pip install -r requirements-validation.txt\n        npm install -g markdownlint-cli\n        npm install -g markdown-link-check\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Get\u003C/span> \u003Cspan class=\"hljs-string\">changed\u003C/span> \u003Cspan class=\"hljs-string\">files\u003C/span>\n      \u003Cspan class=\"hljs-attr\">id:\u003C/span> \u003Cspan class=\"hljs-string\">changed-files\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">tj-actions/changed-files@v39\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">files:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          **/*.md\n          **/*.markdown\n\u003C/span>        \u003Cspan class=\"hljs-attr\">files_ignore:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          node_modules/**\n          .git/**\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Run\u003C/span> \u003Cspan class=\"hljs-string\">quick\u003C/span> \u003Cspan class=\"hljs-string\">validation\u003C/span> \u003Cspan class=\"hljs-string\">on\u003C/span> \u003Cspan class=\"hljs-string\">changed\u003C/span> \u003Cspan class=\"hljs-string\">files\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">steps.changed-files.outputs.any_changed\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;true&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        echo &quot;Changed files: ${{ steps.changed-files.outputs.all_changed_files }}&quot;\n        python scripts/markdown_validator.py \\\n          --config validation_config.yaml \\\n          --format json \\\n          --output validation_results.json \\\n          --severity warning \\\n          ${{ steps.changed-files.outputs.all_changed_files }}\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Upload\u003C/span> \u003Cspan class=\"hljs-string\">validation\u003C/span> \u003Cspan class=\"hljs-string\">results\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/upload-artifact@v3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">quick-validation-results\u003C/span>\n        \u003Cspan class=\"hljs-attr\">path:\u003C/span> \u003Cspan class=\"hljs-string\">validation_results.json\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Comment\u003C/span> \u003Cspan class=\"hljs-string\">PR\u003C/span> \u003Cspan class=\"hljs-string\">with\u003C/span> \u003Cspan class=\"hljs-string\">results\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.event_name\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;pull_request&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">&amp;&amp;\u003C/span> \u003Cspan class=\"hljs-string\">steps.changed-files.outputs.any_changed\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;true&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/github-script@v6\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">script:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          const fs = require(&#x27;fs&#x27;);\n\u003C/span>          \n          \u003Cspan class=\"hljs-string\">try\u003C/span> {\n            \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">results\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">JSON.parse(fs.readFileSync(&#x27;validation_results.json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;utf8&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">));\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">let\u003C/span> \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;## 📝 Content Validation Results\\n\\n&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n            \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`**Summary:**\\n`;\u003C/span>\n            \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`-\u003C/span> \u003Cspan class=\"hljs-attr\">Errors:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">results.summary.errors\u003C/span>}\u003Cspan class=\"hljs-string\">\\n`;\u003C/span>\n            \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`-\u003C/span> \u003Cspan class=\"hljs-attr\">Warnings:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">results.summary.warnings\u003C/span>}\u003Cspan class=\"hljs-string\">\\n`;\u003C/span>\n            \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`-\u003C/span> \u003Cspan class=\"hljs-attr\">Info:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">results.summary.info\u003C/span>}\u003Cspan class=\"hljs-string\">\\n`;\u003C/span>\n            \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`-\u003C/span> \u003Cspan class=\"hljs-attr\">Files checked:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">results.summary.files_with_issues\u003C/span>}\u003Cspan class=\"hljs-string\">\\n\\n`;\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(results.summary.errors\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span> {\n              \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;❌ **Validation failed** - please fix errors before merging.\\n\\n&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n            } \u003Cspan class=\"hljs-string\">else\u003C/span> \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(results.summary.warnings\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span> {\n              \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;⚠️ **Validation passed with warnings** - consider addressing warnings.\\n\\n&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n            } \u003Cspan class=\"hljs-string\">else\u003C/span> {\n              \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;✅ **All validations passed!**\\n\\n&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n            }\n            \n            \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(results.summary.most_common_issues.length\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span> {\n              \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;**Most common issues:**\\n&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n              \u003Cspan class=\"hljs-string\">results.summary.most_common_issues.forEach((\u003C/span>[\u003Cspan class=\"hljs-string\">rule\u003C/span>, \u003Cspan class=\"hljs-string\">count\u003C/span>]\u003Cspan class=\"hljs-string\">)\u003C/span> \u003Cspan class=\"hljs-string\">=&gt;\u003C/span> {\n                \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`-\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">rule\u003C/span>}\u003Cspan class=\"hljs-string\">:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">count\u003C/span>} \u003Cspan class=\"hljs-string\">occurrences\\n`;\u003C/span>\n              }\u003Cspan class=\"hljs-string\">);\u003C/span>\n            }\n            \n            \u003Cspan class=\"hljs-string\">//\u003C/span> \u003Cspan class=\"hljs-string\">Add\u003C/span> \u003Cspan class=\"hljs-string\">details\u003C/span> \u003Cspan class=\"hljs-string\">for\u003C/span> \u003Cspan class=\"hljs-string\">errors\u003C/span> \u003Cspan class=\"hljs-string\">and\u003C/span> \u003Cspan class=\"hljs-string\">warnings\u003C/span>\n            \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">importantResults\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">results.all_results.filter(r\u003C/span> \u003Cspan class=\"hljs-string\">=&gt;\u003C/span> \n              \u003Cspan class=\"hljs-string\">r.severity\u003C/span> \u003Cspan class=\"hljs-string\">===\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;error&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-string\">r.severity\u003C/span> \u003Cspan class=\"hljs-string\">===\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;warning&#x27;\u003C/span>\n            \u003Cspan class=\"hljs-string\">);\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(importantResults.length\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span> \u003Cspan class=\"hljs-string\">&amp;&amp;\u003C/span> \u003Cspan class=\"hljs-string\">importantResults.length\u003C/span> \u003Cspan class=\"hljs-string\">&lt;=\u003C/span> \u003Cspan class=\"hljs-number\">10\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span> {\n              \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;\\n**Issues found:**\\n&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n              \u003Cspan class=\"hljs-string\">importantResults.forEach(result\u003C/span> \u003Cspan class=\"hljs-string\">=&gt;\u003C/span> {\n                \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">icon\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">result.severity\u003C/span> \u003Cspan class=\"hljs-string\">===\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;error&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">?\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;❌&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;⚠️&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n                \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">location\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">result.line_number\u003C/span> \u003Cspan class=\"hljs-string\">?\u003C/span> \u003Cspan class=\"hljs-string\">`:$\u003C/span>{\u003Cspan class=\"hljs-string\">result.line_number\u003C/span>}\u003Cspan class=\"hljs-string\">`\u003C/span> \u003Cspan class=\"hljs-string\">:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n                \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`$\u003C/span>{\u003Cspan class=\"hljs-string\">icon\u003C/span>} \u003Cspan class=\"hljs-string\">**$\u003C/span>{\u003Cspan class=\"hljs-string\">result.file_path\u003C/span>}\u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">location\u003C/span>}\u003Cspan class=\"hljs-string\">**:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">result.message\u003C/span>}\u003Cspan class=\"hljs-string\">\\n`;\u003C/span>\n                \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(result.fix_suggestion)\u003C/span> {\n                  \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`\u003C/span>   \u003Cspan class=\"hljs-string\">💡\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">result.fix_suggestion\u003C/span>}\u003Cspan class=\"hljs-string\">\\n`;\u003C/span>\n                }\n              }\u003Cspan class=\"hljs-string\">);\u003C/span>\n            } \u003Cspan class=\"hljs-string\">else\u003C/span> \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(importantResults.length\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-number\">10\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span> {\n              \u003Cspan class=\"hljs-string\">comment\u003C/span> \u003Cspan class=\"hljs-string\">+=\u003C/span> \u003Cspan class=\"hljs-string\">`\\n**$\u003C/span>{\u003Cspan class=\"hljs-string\">importantResults.length\u003C/span>} \u003Cspan class=\"hljs-string\">issues\u003C/span> \u003Cspan class=\"hljs-string\">found**\u003C/span> \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">see\u003C/span> \u003Cspan class=\"hljs-string\">full\u003C/span> \u003Cspan class=\"hljs-string\">report\u003C/span> \u003Cspan class=\"hljs-string\">in\u003C/span> \u003Cspan class=\"hljs-string\">workflow\u003C/span> \u003Cspan class=\"hljs-string\">artifacts.\\n`;\u003C/span>\n            }\n            \n            \u003Cspan class=\"hljs-string\">github.rest.issues.createComment(\u003C/span>{\n              \u003Cspan class=\"hljs-attr\">issue_number:\u003C/span> \u003Cspan class=\"hljs-string\">context.issue.number\u003C/span>,\n              \u003Cspan class=\"hljs-attr\">owner:\u003C/span> \u003Cspan class=\"hljs-string\">context.repo.owner\u003C/span>,\n              \u003Cspan class=\"hljs-attr\">repo:\u003C/span> \u003Cspan class=\"hljs-string\">context.repo.repo\u003C/span>,\n              \u003Cspan class=\"hljs-attr\">body:\u003C/span> \u003Cspan class=\"hljs-string\">comment\u003C/span>\n            }\u003Cspan class=\"hljs-string\">);\u003C/span>\n          } \u003Cspan class=\"hljs-string\">catch\u003C/span> \u003Cspan class=\"hljs-string\">(error)\u003C/span> {\n            \u003Cspan class=\"hljs-string\">console.error(&#x27;Failed\u003C/span> \u003Cspan class=\"hljs-string\">to\u003C/span> \u003Cspan class=\"hljs-string\">post\u003C/span> \u003Cspan class=\"hljs-string\">validation\u003C/span> \u003Cspan class=\"hljs-string\">results:&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">error);\u003C/span>\n          }\n\n  \u003Cspan class=\"hljs-comment\"># Comprehensive validation for main branches and scheduled runs\u003C/span>\n  \u003Cspan class=\"hljs-attr\">comprehensive-validation:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.ref\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;refs/heads/main&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-string\">github.ref\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;refs/heads/develop&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-string\">github.event_name\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;schedule&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Checkout\u003C/span> \u003Cspan class=\"hljs-string\">repository\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">fetch-depth:\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Setup\u003C/span> \u003Cspan class=\"hljs-string\">Python\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-python@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">python-version:\u003C/span> \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">env.PYTHON_VERSION\u003C/span> \u003Cspan class=\"hljs-string\">}}\u003C/span>\n        \u003Cspan class=\"hljs-attr\">cache:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;pip&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Setup\u003C/span> \u003Cspan class=\"hljs-string\">Node.js\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-node@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">node-version:\u003C/span> \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">env.NODE_VERSION\u003C/span> \u003Cspan class=\"hljs-string\">}}\u003C/span>\n        \u003Cspan class=\"hljs-attr\">cache:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;npm&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Install\u003C/span> \u003Cspan class=\"hljs-string\">comprehensive\u003C/span> \u003Cspan class=\"hljs-string\">validation\u003C/span> \u003Cspan class=\"hljs-string\">tools\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        # Python tools\n        pip install -r requirements-validation.txt\n        pip install textstat\n        pip install py-readability-metrics\n\u003C/span>        \n        \u003Cspan class=\"hljs-comment\"># Node.js tools\u003C/span>\n        \u003Cspan class=\"hljs-string\">npm\u003C/span> \u003Cspan class=\"hljs-string\">install\u003C/span> \u003Cspan class=\"hljs-string\">-g\u003C/span> \u003Cspan class=\"hljs-string\">markdownlint-cli\u003C/span>\n        \u003Cspan class=\"hljs-string\">npm\u003C/span> \u003Cspan class=\"hljs-string\">install\u003C/span> \u003Cspan class=\"hljs-string\">-g\u003C/span> \u003Cspan class=\"hljs-string\">markdown-link-check\u003C/span>\n        \u003Cspan class=\"hljs-string\">npm\u003C/span> \u003Cspan class=\"hljs-string\">install\u003C/span> \u003Cspan class=\"hljs-string\">-g\u003C/span> \u003Cspan class=\"hljs-string\">alex\u003C/span>\n        \u003Cspan class=\"hljs-string\">npm\u003C/span> \u003Cspan class=\"hljs-string\">install\u003C/span> \u003Cspan class=\"hljs-string\">-g\u003C/span> \u003Cspan class=\"hljs-string\">write-good\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Additional tools\u003C/span>\n        \u003Cspan class=\"hljs-string\">wget\u003C/span> \u003Cspan class=\"hljs-string\">-O\u003C/span> \u003Cspan class=\"hljs-string\">vale.tar.gz\u003C/span> \u003Cspan class=\"hljs-string\">https://github.com/errata-ai/vale/releases/download/v2.25.0/vale_2.25.0_Linux_64-bit.tar.gz\u003C/span>\n        \u003Cspan class=\"hljs-string\">tar\u003C/span> \u003Cspan class=\"hljs-string\">-xzf\u003C/span> \u003Cspan class=\"hljs-string\">vale.tar.gz\u003C/span>\n        \u003Cspan class=\"hljs-string\">sudo\u003C/span> \u003Cspan class=\"hljs-string\">mv\u003C/span> \u003Cspan class=\"hljs-string\">vale\u003C/span> \u003Cspan class=\"hljs-string\">/usr/local/bin/\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Run\u003C/span> \u003Cspan class=\"hljs-string\">comprehensive\u003C/span> \u003Cspan class=\"hljs-string\">validation\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        python scripts/comprehensive_validator.py \\\n          --config validation_config.yaml \\\n          --output-dir validation-reports/ \\\n          --include-metrics \\\n          --generate-trends \\\n          --parallel-processing\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Run\u003C/span> \u003Cspan class=\"hljs-string\">external\u003C/span> \u003Cspan class=\"hljs-string\">tool\u003C/span> \u003Cspan class=\"hljs-string\">validations\u003C/span>\n      \u003Cspan class=\"hljs-attr\">continue-on-error:\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        # Markdown linting\n        markdownlint --config .markdownlint.json &quot;**/*.md&quot; &gt; validation-reports/markdownlint.txt || true\n\u003C/span>        \n        \u003Cspan class=\"hljs-comment\"># Link checking (external links only for comprehensive check)\u003C/span>\n        \u003Cspan class=\"hljs-string\">find\u003C/span> \u003Cspan class=\"hljs-string\">.\u003C/span> \u003Cspan class=\"hljs-string\">-name\u003C/span> \u003Cspan class=\"hljs-string\">&quot;*.md&quot;\u003C/span> \u003Cspan class=\"hljs-string\">-exec\u003C/span> \u003Cspan class=\"hljs-string\">markdown-link-check\u003C/span> {} \u003Cspan class=\"hljs-string\">\\;\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-string\">validation-reports/link-check.txt\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Prose linting\u003C/span>\n        \u003Cspan class=\"hljs-string\">alex\u003C/span> \u003Cspan class=\"hljs-string\">.\u003C/span> \u003Cspan class=\"hljs-string\">--why\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-string\">validation-reports/alex-report.txt\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n        \u003Cspan class=\"hljs-string\">write-good\u003C/span> \u003Cspan class=\"hljs-string\">**/*.md\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-string\">validation-reports/write-good.txt\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Style and grammar checking\u003C/span>\n        \u003Cspan class=\"hljs-string\">vale\u003C/span> \u003Cspan class=\"hljs-string\">--config\u003C/span> \u003Cspan class=\"hljs-string\">vale.ini\u003C/span> \u003Cspan class=\"hljs-string\">.\u003C/span> \u003Cspan class=\"hljs-string\">&gt;\u003C/span> \u003Cspan class=\"hljs-string\">validation-reports/vale-report.txt\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-literal\">true\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Generate\u003C/span> \u003Cspan class=\"hljs-string\">quality\u003C/span> \u003Cspan class=\"hljs-string\">metrics\u003C/span> \u003Cspan class=\"hljs-string\">dashboard\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        python scripts/generate_quality_dashboard.py \\\n          --input validation-reports/ \\\n          --output validation-reports/dashboard.html \\\n          --include-trends \\\n          --compare-with-baseline\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Upload\u003C/span> \u003Cspan class=\"hljs-string\">comprehensive\u003C/span> \u003Cspan class=\"hljs-string\">reports\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/upload-artifact@v3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">comprehensive-validation-reports\u003C/span>\n        \u003Cspan class=\"hljs-attr\">path:\u003C/span> \u003Cspan class=\"hljs-string\">validation-reports/\u003C/span>\n        \u003Cspan class=\"hljs-attr\">retention-days:\u003C/span> \u003Cspan class=\"hljs-number\">30\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Update\u003C/span> \u003Cspan class=\"hljs-string\">quality\u003C/span> \u003Cspan class=\"hljs-string\">metrics\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.ref\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;refs/heads/main&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        python scripts/update_quality_metrics.py \\\n          --results validation-reports/comprehensive-results.json \\\n          --metrics-file docs/quality-metrics.json \\\n          --trend-data docs/quality-trends.json\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Commit\u003C/span> \u003Cspan class=\"hljs-string\">updated\u003C/span> \u003Cspan class=\"hljs-string\">metrics\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.ref\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;refs/heads/main&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        git config --local user.email &quot;action@github.com&quot;\n        git config --local user.name &quot;GitHub Action&quot;\n\u003C/span>        \n        \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">diff\u003C/span> \u003Cspan class=\"hljs-string\">--quiet\u003C/span> \u003Cspan class=\"hljs-string\">docs/quality-metrics.json\u003C/span> \u003Cspan class=\"hljs-string\">docs/quality-trends.json;\u003C/span> \u003Cspan class=\"hljs-string\">then\u003C/span>\n          \u003Cspan class=\"hljs-string\">echo\u003C/span> \u003Cspan class=\"hljs-string\">&quot;No metrics changes to commit&quot;\u003C/span>\n        \u003Cspan class=\"hljs-string\">else\u003C/span>\n          \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">add\u003C/span> \u003Cspan class=\"hljs-string\">docs/quality-metrics.json\u003C/span> \u003Cspan class=\"hljs-string\">docs/quality-trends.json\u003C/span>\n          \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">commit\u003C/span> \u003Cspan class=\"hljs-string\">-m\u003C/span> \u003Cspan class=\"hljs-string\">&quot;Update documentation quality metrics [skip ci]&quot;\u003C/span>\n          \u003Cspan class=\"hljs-string\">git\u003C/span> \u003Cspan class=\"hljs-string\">push\u003C/span>\n        \u003Cspan class=\"hljs-string\">fi\u003C/span>\n\n  \u003Cspan class=\"hljs-comment\"># Security and compliance scanning\u003C/span>\n  \u003Cspan class=\"hljs-attr\">security-validation:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.event_name\u003C/span> \u003Cspan class=\"hljs-type\">!=\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;pull_request&#x27;\u003C/span>  \u003Cspan class=\"hljs-comment\"># Skip for PRs to avoid secrets exposure\u003C/span>\n    \n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Checkout\u003C/span> \u003Cspan class=\"hljs-string\">repository\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v4\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Setup\u003C/span> \u003Cspan class=\"hljs-string\">Python\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-python@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">python-version:\u003C/span> \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">env.PYTHON_VERSION\u003C/span> \u003Cspan class=\"hljs-string\">}}\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Install\u003C/span> \u003Cspan class=\"hljs-string\">security\u003C/span> \u003Cspan class=\"hljs-string\">scanning\u003C/span> \u003Cspan class=\"hljs-string\">tools\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        pip install detect-secrets\n        pip install bandit\n        npm install -g secretlint\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Scan\u003C/span> \u003Cspan class=\"hljs-string\">for\u003C/span> \u003Cspan class=\"hljs-string\">secrets\u003C/span> \u003Cspan class=\"hljs-string\">in\u003C/span> \u003Cspan class=\"hljs-string\">documentation\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        detect-secrets scan --all-files --baseline .secrets.baseline\n        secretlint &quot;**/*.md&quot; --format json --output security-scan.json || true\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Check\u003C/span> \u003Cspan class=\"hljs-string\">for\u003C/span> \u003Cspan class=\"hljs-string\">compliance\u003C/span> \u003Cspan class=\"hljs-string\">violations\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        python scripts/compliance_checker.py \\\n          --config compliance_config.yaml \\\n          --output compliance-report.json\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Upload\u003C/span> \u003Cspan class=\"hljs-string\">security\u003C/span> \u003Cspan class=\"hljs-string\">scan\u003C/span> \u003Cspan class=\"hljs-string\">results\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/upload-artifact@v3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">security-scan-results\u003C/span>\n        \u003Cspan class=\"hljs-attr\">path:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          security-scan.json\n          compliance-report.json\n\u003C/span>\n  \u003Cspan class=\"hljs-comment\"># Performance and optimization analysis\u003C/span>\n  \u003Cspan class=\"hljs-attr\">performance-analysis:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.event_name\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;schedule&#x27;\u003C/span>\n    \n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Checkout\u003C/span> \u003Cspan class=\"hljs-string\">repository\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/checkout@v4\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Setup\u003C/span> \u003Cspan class=\"hljs-string\">Python\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/setup-python@v4\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">python-version:\u003C/span> \u003Cspan class=\"hljs-string\">${{\u003C/span> \u003Cspan class=\"hljs-string\">env.PYTHON_VERSION\u003C/span> \u003Cspan class=\"hljs-string\">}}\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Analyze\u003C/span> \u003Cspan class=\"hljs-string\">content\u003C/span> \u003Cspan class=\"hljs-string\">performance\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        python scripts/performance_analyzer.py \\\n          --input-dir . \\\n          --output performance-analysis.json \\\n          --check-file-sizes \\\n          --analyze-image-optimization \\\n          --check-external-dependencies\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Generate\u003C/span> \u003Cspan class=\"hljs-string\">optimization\u003C/span> \u003Cspan class=\"hljs-string\">recommendations\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        python scripts/optimization_recommender.py \\\n          --analysis performance-analysis.json \\\n          --output optimization-recommendations.md\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Create\u003C/span> \u003Cspan class=\"hljs-string\">optimization\u003C/span> \u003Cspan class=\"hljs-string\">issue\u003C/span>\n      \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">github.event_name\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;schedule&#x27;\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/github-script@v6\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">script:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          const fs = require(&#x27;fs&#x27;);\n\u003C/span>          \n          \u003Cspan class=\"hljs-string\">try\u003C/span> {\n            \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">recommendations\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">fs.readFileSync(&#x27;optimization-recommendations.md&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;utf8&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">);\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(recommendations.trim())\u003C/span> {\n              \u003Cspan class=\"hljs-string\">await\u003C/span> \u003Cspan class=\"hljs-string\">github.rest.issues.create(\u003C/span>{\n                \u003Cspan class=\"hljs-attr\">owner:\u003C/span> \u003Cspan class=\"hljs-string\">context.repo.owner\u003C/span>,\n                \u003Cspan class=\"hljs-attr\">repo:\u003C/span> \u003Cspan class=\"hljs-string\">context.repo.repo\u003C/span>,\n                \u003Cspan class=\"hljs-attr\">title:\u003C/span> \u003Cspan class=\"hljs-string\">`📈\u003C/span> \u003Cspan class=\"hljs-string\">Weekly\u003C/span> \u003Cspan class=\"hljs-string\">Performance\u003C/span> \u003Cspan class=\"hljs-string\">Optimization\u003C/span> \u003Cspan class=\"hljs-string\">Recommendations\u003C/span> \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">new\u003C/span> \u003Cspan class=\"hljs-string\">Date().toISOString().split(&#x27;T&#x27;)\u003C/span>[\u003Cspan class=\"hljs-number\">0\u003C/span>]}\u003Cspan class=\"hljs-string\">`\u003C/span>,\n                \u003Cspan class=\"hljs-attr\">body:\u003C/span> \u003Cspan class=\"hljs-string\">recommendations\u003C/span>,\n                \u003Cspan class=\"hljs-attr\">labels:\u003C/span> [\u003Cspan class=\"hljs-string\">&#x27;documentation&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;performance&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;automated&#x27;\u003C/span>]\n              }\u003Cspan class=\"hljs-string\">);\u003C/span>\n            }\n          } \u003Cspan class=\"hljs-string\">catch\u003C/span> \u003Cspan class=\"hljs-string\">(error)\u003C/span> {\n            \u003Cspan class=\"hljs-string\">console.error(&#x27;Failed\u003C/span> \u003Cspan class=\"hljs-string\">to\u003C/span> \u003Cspan class=\"hljs-string\">create\u003C/span> \u003Cspan class=\"hljs-string\">optimization\u003C/span> \u003Cspan class=\"hljs-string\">issue:&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">error);\u003C/span>\n          }\n\n  \u003Cspan class=\"hljs-comment\"># Quality gates and deployment checks\u003C/span>\n  \u003Cspan class=\"hljs-attr\">quality-gates:\u003C/span>\n    \u003Cspan class=\"hljs-attr\">runs-on:\u003C/span> \u003Cspan class=\"hljs-string\">ubuntu-latest\u003C/span>\n    \u003Cspan class=\"hljs-attr\">needs:\u003C/span> [\u003Cspan class=\"hljs-string\">quick-validation\u003C/span>, \u003Cspan class=\"hljs-string\">comprehensive-validation\u003C/span>]\n    \u003Cspan class=\"hljs-attr\">if:\u003C/span> \u003Cspan class=\"hljs-string\">always()\u003C/span> \u003Cspan class=\"hljs-string\">&amp;&amp;\u003C/span> \u003Cspan class=\"hljs-string\">(needs.quick-validation.result\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;success&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">||\u003C/span> \u003Cspan class=\"hljs-string\">needs.comprehensive-validation.result\u003C/span> \u003Cspan class=\"hljs-string\">==\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;success&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">)\u003C/span>\n    \n    \u003Cspan class=\"hljs-attr\">steps:\u003C/span>\n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Download\u003C/span> \u003Cspan class=\"hljs-string\">validation\u003C/span> \u003Cspan class=\"hljs-string\">results\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/download-artifact@v3\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">path:\u003C/span> \u003Cspan class=\"hljs-string\">validation-results/\u003C/span>\n    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Check\u003C/span> \u003Cspan class=\"hljs-string\">quality\u003C/span> \u003Cspan class=\"hljs-string\">gates\u003C/span>\n      \u003Cspan class=\"hljs-attr\">run:\u003C/span> \u003Cspan class=\"hljs-string\">|\n        python scripts/quality_gates_checker.py \\\n          --results-dir validation-results/ \\\n          --config validation_config.yaml \\\n          --output quality-gates.json\n\u003C/span>    \n    \u003Cspan class=\"hljs-bullet\">-\u003C/span> \u003Cspan class=\"hljs-attr\">name:\u003C/span> \u003Cspan class=\"hljs-string\">Set\u003C/span> \u003Cspan class=\"hljs-string\">deployment\u003C/span> \u003Cspan class=\"hljs-string\">status\u003C/span>\n      \u003Cspan class=\"hljs-attr\">uses:\u003C/span> \u003Cspan class=\"hljs-string\">actions/github-script@v6\u003C/span>\n      \u003Cspan class=\"hljs-attr\">with:\u003C/span>\n        \u003Cspan class=\"hljs-attr\">script:\u003C/span> \u003Cspan class=\"hljs-string\">|\n          const fs = require(&#x27;fs&#x27;);\n\u003C/span>          \n          \u003Cspan class=\"hljs-string\">try\u003C/span> {\n            \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">gates\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">JSON.parse(fs.readFileSync(&#x27;quality-gates.json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;utf8&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">));\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">state\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">gates.passed\u003C/span> \u003Cspan class=\"hljs-string\">?\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;success&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">:\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;failure&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">;\u003C/span>\n            \u003Cspan class=\"hljs-string\">const\u003C/span> \u003Cspan class=\"hljs-string\">description\u003C/span> \u003Cspan class=\"hljs-string\">=\u003C/span> \u003Cspan class=\"hljs-string\">gates.passed\u003C/span> \u003Cspan class=\"hljs-string\">?\u003C/span> \n              \u003Cspan class=\"hljs-string\">&#x27;All quality gates passed&#x27;\u003C/span> \u003Cspan class=\"hljs-string\">:\u003C/span> \n              \u003Cspan class=\"hljs-string\">`Quality\u003C/span> \u003Cspan class=\"hljs-attr\">gates failed:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">gates.failures.join(&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;)}`;\n            \n            await github.rest.repos.createCommitStatus({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              sha: context.sha,\n              state: state,\n              target_url: `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`,\n              description: description,\n              context: &#x27;\u003C/span>\u003Cspan class=\"hljs-string\">Content\u003C/span> \u003Cspan class=\"hljs-string\">Quality\u003C/span> \u003Cspan class=\"hljs-string\">Gates&#x27;\u003C/span>\n            }\u003Cspan class=\"hljs-string\">);\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">core.setOutput(&#x27;quality_gates_passed&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">gates.passed);\u003C/span>\n            \n            \u003Cspan class=\"hljs-string\">if\u003C/span> \u003Cspan class=\"hljs-string\">(!gates.passed)\u003C/span> {\n              \u003Cspan class=\"hljs-string\">core.setFailed(`Quality\u003C/span> \u003Cspan class=\"hljs-attr\">gates failed:\u003C/span> \u003Cspan class=\"hljs-string\">$\u003C/span>{\u003Cspan class=\"hljs-string\">gates.failures.join(&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;)}`);\n            }\n          } catch (error) {\n            console.error(&#x27;\u003C/span>\u003Cspan class=\"hljs-string\">Failed\u003C/span> \u003Cspan class=\"hljs-string\">to\u003C/span> \u003Cspan class=\"hljs-string\">process\u003C/span> \u003Cspan class=\"hljs-string\">quality\u003C/span> \u003Cspan class=\"hljs-string\">gates:&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">error);\u003C/span>\n            \u003Cspan class=\"hljs-string\">core.setFailed(&#x27;Error\u003C/span> \u003Cspan class=\"hljs-string\">processing\u003C/span> \u003Cspan class=\"hljs-string\">quality\u003C/span> \u003Cspan class=\"hljs-string\">gates&#x27;);\u003C/span>\n          }\n\u003C/code>\u003C/pre>\u003Ch2 id=\"integration-with-content-management\">Integration with Content Management\u003C/h2>\n\u003Cp>Content validation systems integrate seamlessly with modern documentation workflows. When combined with \u003Ca href=\"/blog/markdown-version-control-git-integration-complete-guide\">version control and Git integration systems\u003C/a>, automated validation ensures that content quality standards are maintained across collaborative development processes while providing immediate feedback to contributors.\u003C/p>\n\u003Cp>For comprehensive documentation systems, validation complements \u003Ca href=\"/blog/markdown-form-creation-input-validation-complete-guide\">form creation and user interaction features\u003C/a> by ensuring that generated content and user-contributed documentation maintains consistent quality standards and accessibility compliance across all content types.\u003C/p>\n\u003Cp>When building sophisticated content architectures, validation works effectively with \u003Ca href=\"/blog/markdown-auto-linking-url-detection-complete-guide\">automated content linking and cross-referencing systems\u003C/a> to maintain content integrity, validate link relationships, and ensure that automated content generation produces high-quality, maintainable documentation.\u003C/p>\n\u003Ch2 id=\"advanced-quality-metrics-and-reporting\">Advanced Quality Metrics and Reporting\u003C/h2>\n\u003Ch3 id=\"comprehensive-quality-dashboard\">Comprehensive Quality Dashboard\u003C/h3>\n\u003Cp>Building interactive dashboards for content quality monitoring:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\"># quality_dashboard.py - Interactive quality metrics dashboard\u003C/span>\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> json\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> pandas \u003Cspan class=\"hljs-keyword\">as\u003C/span> pd\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> plotly.graph_objects \u003Cspan class=\"hljs-keyword\">as\u003C/span> go\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> plotly.express \u003Cspan class=\"hljs-keyword\">as\u003C/span> px\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> plotly.subplots \u003Cspan class=\"hljs-keyword\">import\u003C/span> make_subplots\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> dash\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> dash \u003Cspan class=\"hljs-keyword\">import\u003C/span> dcc, html, dash_table\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> dash.dependencies \u003Cspan class=\"hljs-keyword\">import\u003C/span> Input, Output, State\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> datetime \u003Cspan class=\"hljs-keyword\">import\u003C/span> datetime, timedelta\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> numpy \u003Cspan class=\"hljs-keyword\">as\u003C/span> np\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> typing \u003Cspan class=\"hljs-keyword\">import\u003C/span> \u003Cspan class=\"hljs-type\">Dict\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>, \u003Cspan class=\"hljs-type\">Any\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">QualityDashboard\u003C/span>:\n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self, metrics_file: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, trends_file: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>):\n        self.app = dash.Dash(__name__)\n        self.metrics_data = self.load_metrics(metrics_file)\n        self.trends_data = self.load_trends(trends_file)\n        self.setup_layout()\n        self.setup_callbacks()\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">load_metrics\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Load current quality metrics&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(file_path, \u003Cspan class=\"hljs-string\">&#x27;r&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> json.load(f)\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> FileNotFoundError:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> self.get_default_metrics()\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">load_trends\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Load historical trend data&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(file_path, \u003Cspan class=\"hljs-string\">&#x27;r&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> json.load(f)\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> FileNotFoundError:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> []\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">get_default_metrics\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Return default metrics structure&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;overall_score&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">85\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;total_files&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>,\n            \u003Cspan class=\"hljs-string\">&#x27;last_updated&#x27;\u003C/span>: datetime.now().isoformat(),\n            \u003Cspan class=\"hljs-string\">&#x27;categories&#x27;\u003C/span>: {\n                \u003Cspan class=\"hljs-string\">&#x27;content_quality&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;score&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">85\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;weight&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0.3\u003C/span>},\n                \u003Cspan class=\"hljs-string\">&#x27;accessibility&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;score&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">90\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;weight&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0.2\u003C/span>},\n                \u003Cspan class=\"hljs-string\">&#x27;seo&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;score&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">80\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;weight&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0.2\u003C/span>},\n                \u003Cspan class=\"hljs-string\">&#x27;technical&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;score&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">88\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;weight&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0.15\u003C/span>},\n                \u003Cspan class=\"hljs-string\">&#x27;security&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;score&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">95\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;weight&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0.15\u003C/span>}\n            },\n            \u003Cspan class=\"hljs-string\">&#x27;rule_performance&#x27;\u003C/span>: {},\n            \u003Cspan class=\"hljs-string\">&#x27;file_quality_distribution&#x27;\u003C/span>: {}\n        }\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">setup_layout\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Setup dashboard layout&quot;&quot;&quot;\u003C/span>\n        self.app.layout = html.Div([\n            \u003Cspan class=\"hljs-comment\"># Header\u003C/span>\n            html.Div([\n                html.H1(\u003Cspan class=\"hljs-string\">&quot;📊 Documentation Quality Dashboard&quot;\u003C/span>, \n                       className=\u003Cspan class=\"hljs-string\">&quot;dashboard-title&quot;\u003C/span>),\n                html.P(\u003Cspan class=\"hljs-string\">f&quot;Last updated: \u003Cspan class=\"hljs-subst\">{self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;last_updated&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Unknown&#x27;\u003C/span>)}\u003C/span>&quot;\u003C/span>, \n                      className=\u003Cspan class=\"hljs-string\">&quot;last-updated&quot;\u003C/span>),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;header-section&quot;\u003C/span>),\n            \n            \u003Cspan class=\"hljs-comment\"># Summary Cards\u003C/span>\n            html.Div([\n                self.create_summary_card(\u003Cspan class=\"hljs-string\">&quot;Overall Quality Score&quot;\u003C/span>, \n                                       \u003Cspan class=\"hljs-string\">f&quot;\u003Cspan class=\"hljs-subst\">{self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;overall_score&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>)}\u003C/span>%&quot;\u003C/span>,\n                                       self.get_score_color(self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;overall_score&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>)),\n                                       \u003Cspan class=\"hljs-string\">&quot;trending-up&quot;\u003C/span>),\n                self.create_summary_card(\u003Cspan class=\"hljs-string\">&quot;Total Files&quot;\u003C/span>, \n                                       \u003Cspan class=\"hljs-built_in\">str\u003C/span>(self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;total_files&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>)),\n                                       \u003Cspan class=\"hljs-string\">&quot;#3498db&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;file-text&quot;\u003C/span>),\n                self.create_summary_card(\u003Cspan class=\"hljs-string\">&quot;Issues Found&quot;\u003C/span>, \n                                       \u003Cspan class=\"hljs-built_in\">str\u003C/span>(self.calculate_total_issues()),\n                                       \u003Cspan class=\"hljs-string\">&quot;#e74c3c&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;alert-triangle&quot;\u003C/span>),\n                self.create_summary_card(\u003Cspan class=\"hljs-string\">&quot;Files Passing&quot;\u003C/span>, \n                                       \u003Cspan class=\"hljs-string\">f&quot;\u003Cspan class=\"hljs-subst\">{self.calculate_passing_percentage()}\u003C/span>%&quot;\u003C/span>,\n                                       \u003Cspan class=\"hljs-string\">&quot;#2ecc71&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;check-circle&quot;\u003C/span>),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;summary-cards&quot;\u003C/span>),\n            \n            \u003Cspan class=\"hljs-comment\"># Quality Score Breakdown\u003C/span>\n            html.Div([\n                html.H2(\u003Cspan class=\"hljs-string\">&quot;Quality Score Breakdown&quot;\u003C/span>),\n                dcc.Graph(\u003Cspan class=\"hljs-built_in\">id\u003C/span>=\u003Cspan class=\"hljs-string\">&quot;quality-breakdown-chart&quot;\u003C/span>),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;chart-section&quot;\u003C/span>),\n            \n            \u003Cspan class=\"hljs-comment\"># Trends Over Time\u003C/span>\n            html.Div([\n                html.H2(\u003Cspan class=\"hljs-string\">&quot;Quality Trends&quot;\u003C/span>),\n                dcc.Graph(\u003Cspan class=\"hljs-built_in\">id\u003C/span>=\u003Cspan class=\"hljs-string\">&quot;trends-chart&quot;\u003C/span>),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;chart-section&quot;\u003C/span>),\n            \n            \u003Cspan class=\"hljs-comment\"># Rule Performance\u003C/span>\n            html.Div([\n                html.H2(\u003Cspan class=\"hljs-string\">&quot;Validation Rule Performance&quot;\u003C/span>),\n                dcc.Graph(\u003Cspan class=\"hljs-built_in\">id\u003C/span>=\u003Cspan class=\"hljs-string\">&quot;rule-performance-chart&quot;\u003C/span>),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;chart-section&quot;\u003C/span>),\n            \n            \u003Cspan class=\"hljs-comment\"># File Quality Distribution\u003C/span>\n            html.Div([\n                html.H2(\u003Cspan class=\"hljs-string\">&quot;File Quality Distribution&quot;\u003C/span>),\n                dcc.Graph(\u003Cspan class=\"hljs-built_in\">id\u003C/span>=\u003Cspan class=\"hljs-string\">&quot;file-quality-chart&quot;\u003C/span>),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;chart-section&quot;\u003C/span>),\n            \n            \u003Cspan class=\"hljs-comment\"># Detailed Issues Table\u003C/span>\n            html.Div([\n                html.H2(\u003Cspan class=\"hljs-string\">&quot;Recent Issues&quot;\u003C/span>),\n                dash_table.DataTable(\n                    \u003Cspan class=\"hljs-built_in\">id\u003C/span>=\u003Cspan class=\"hljs-string\">&#x27;issues-table&#x27;\u003C/span>,\n                    columns=[\n                        {\u003Cspan class=\"hljs-string\">&quot;name&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;File&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;id&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;file_path&quot;\u003C/span>},\n                        {\u003Cspan class=\"hljs-string\">&quot;name&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Rule&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;id&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;rule_id&quot;\u003C/span>},\n                        {\u003Cspan class=\"hljs-string\">&quot;name&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Severity&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;id&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;severity&quot;\u003C/span>},\n                        {\u003Cspan class=\"hljs-string\">&quot;name&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Message&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;id&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;message&quot;\u003C/span>},\n                        {\u003Cspan class=\"hljs-string\">&quot;name&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Fix Suggestion&quot;\u003C/span>, \u003Cspan class=\"hljs-string\">&quot;id&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;fix_suggestion&quot;\u003C/span>}\n                    ],\n                    data=self.get_recent_issues(),\n                    style_cell={\u003Cspan class=\"hljs-string\">&#x27;textAlign&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;left&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;overflow&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;hidden&#x27;\u003C/span>, \n                              \u003Cspan class=\"hljs-string\">&#x27;textOverflow&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;ellipsis&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;maxWidth&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>},\n                    style_data_conditional=[\n                        {\n                            \u003Cspan class=\"hljs-string\">&#x27;if&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;filter_query&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;{severity} = error&#x27;\u003C/span>},\n                            \u003Cspan class=\"hljs-string\">&#x27;backgroundColor&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;#ffebee&#x27;\u003C/span>,\n                            \u003Cspan class=\"hljs-string\">&#x27;color&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;black&#x27;\u003C/span>,\n                        },\n                        {\n                            \u003Cspan class=\"hljs-string\">&#x27;if&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;filter_query&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;{severity} = warning&#x27;\u003C/span>},\n                            \u003Cspan class=\"hljs-string\">&#x27;backgroundColor&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;#fff3e0&#x27;\u003C/span>,\n                            \u003Cspan class=\"hljs-string\">&#x27;color&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;black&#x27;\u003C/span>,\n                        }\n                    ],\n                    page_size=\u003Cspan class=\"hljs-number\">20\u003C/span>,\n                    sort_action=\u003Cspan class=\"hljs-string\">&quot;native&quot;\u003C/span>,\n                    filter_action=\u003Cspan class=\"hljs-string\">&quot;native&quot;\u003C/span>\n                ),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;table-section&quot;\u003C/span>),\n            \n        ], className=\u003Cspan class=\"hljs-string\">&quot;dashboard-container&quot;\u003C/span>)\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">create_summary_card\u003C/span>(\u003Cspan class=\"hljs-params\">self, title: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, value: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, color: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, icon: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; html.Div:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Create a summary card component&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> html.Div([\n            html.Div([\n                html.I(className=\u003Cspan class=\"hljs-string\">f&quot;fas fa-\u003Cspan class=\"hljs-subst\">{icon}\u003C/span>&quot;\u003C/span>, style={\u003Cspan class=\"hljs-string\">&quot;color&quot;\u003C/span>: color, \u003Cspan class=\"hljs-string\">&quot;fontSize&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;2rem&quot;\u003C/span>}),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;card-icon&quot;\u003C/span>),\n            html.Div([\n                html.H3(title, className=\u003Cspan class=\"hljs-string\">&quot;card-title&quot;\u003C/span>),\n                html.P(value, className=\u003Cspan class=\"hljs-string\">&quot;card-value&quot;\u003C/span>, style={\u003Cspan class=\"hljs-string\">&quot;color&quot;\u003C/span>: color}),\n            ], className=\u003Cspan class=\"hljs-string\">&quot;card-content&quot;\u003C/span>),\n        ], className=\u003Cspan class=\"hljs-string\">&quot;summary-card&quot;\u003C/span>)\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">get_score_color\u003C/span>(\u003Cspan class=\"hljs-params\">self, score: \u003Cspan class=\"hljs-built_in\">int\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">str\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Get color based on quality score&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> score &gt;= \u003Cspan class=\"hljs-number\">90\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-string\">&quot;#2ecc71&quot;\u003C/span>  \u003Cspan class=\"hljs-comment\"># Green\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">elif\u003C/span> score &gt;= \u003Cspan class=\"hljs-number\">75\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-string\">&quot;#f39c12&quot;\u003C/span>  \u003Cspan class=\"hljs-comment\"># Orange\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">else\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-string\">&quot;#e74c3c&quot;\u003C/span>  \u003Cspan class=\"hljs-comment\"># Red\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">calculate_total_issues\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">int\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Calculate total issues across all categories&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-built_in\">sum\u003C/span>(cat.get(\u003Cspan class=\"hljs-string\">&#x27;issues&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>) \u003Cspan class=\"hljs-keyword\">for\u003C/span> cat \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;categories&#x27;\u003C/span>, {}).values())\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">calculate_passing_percentage\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">int\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Calculate percentage of files passing all checks&quot;&quot;&quot;\u003C/span>\n        file_dist = self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;file_quality_distribution&#x27;\u003C/span>, {})\n        total_files = \u003Cspan class=\"hljs-built_in\">sum\u003C/span>(file_dist.values()) \u003Cspan class=\"hljs-keyword\">if\u003C/span> file_dist \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-number\">1\u003C/span>\n        passing_files = file_dist.get(\u003Cspan class=\"hljs-string\">&#x27;excellent&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>) + file_dist.get(\u003Cspan class=\"hljs-string\">&#x27;good&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>)\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-built_in\">int\u003C/span>((passing_files / total_files) * \u003Cspan class=\"hljs-number\">100\u003C/span>) \u003Cspan class=\"hljs-keyword\">if\u003C/span> total_files &gt; \u003Cspan class=\"hljs-number\">0\u003C/span> \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-number\">0\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">get_recent_issues\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Get recent issues for the table&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-comment\"># This would typically come from a more detailed validation results file\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> [\n            {\n                \u003Cspan class=\"hljs-string\">&quot;file_path&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;docs/api/authentication.md&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;rule_id&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;heading_too_long&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;severity&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;warning&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;message&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Heading too long (85 chars, max 80)&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;fix_suggestion&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Shorten heading text&quot;\u003C/span>\n            },\n            {\n                \u003Cspan class=\"hljs-string\">&quot;file_path&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;content/guides/getting-started.md&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;rule_id&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;link_broken_external&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;severity&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;error&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;message&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Broken external link: https://example.com/api&quot;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&quot;fix_suggestion&quot;\u003C/span>: \u003Cspan class=\"hljs-string\">&quot;Update or remove broken link&quot;\u003C/span>\n            }\n        ]\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">setup_callbacks\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Setup interactive callbacks&quot;&quot;&quot;\u003C/span>\n        \n\u003Cspan class=\"hljs-meta\">        @self.app.callback(\u003Cspan class=\"hljs-params\">\n            Output(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;quality-breakdown-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;figure&#x27;\u003C/span>\u003C/span>),\n            Input(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;quality-breakdown-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;id&#x27;\u003C/span>\u003C/span>)\n        \u003C/span>)\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">update_quality_breakdown\u003C/span>(\u003Cspan class=\"hljs-params\">chart_id\u003C/span>):\n            categories = self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;categories&#x27;\u003C/span>, {})\n            \n            fig = go.Figure()\n            \n            \u003Cspan class=\"hljs-comment\"># Create radar chart for quality breakdown\u003C/span>\n            categories_list = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(categories.keys())\n            scores = [categories[cat].get(\u003Cspan class=\"hljs-string\">&#x27;score&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>) \u003Cspan class=\"hljs-keyword\">for\u003C/span> cat \u003Cspan class=\"hljs-keyword\">in\u003C/span> categories_list]\n            \n            fig.add_trace(go.Scatterpolar(\n                r=scores,\n                theta=categories_list,\n                fill=\u003Cspan class=\"hljs-string\">&#x27;toself&#x27;\u003C/span>,\n                name=\u003Cspan class=\"hljs-string\">&#x27;Quality Scores&#x27;\u003C/span>,\n                line_color=\u003Cspan class=\"hljs-string\">&#x27;rgb(106, 81, 163)&#x27;\u003C/span>\n            ))\n            \n            fig.update_layout(\n                polar=\u003Cspan class=\"hljs-built_in\">dict\u003C/span>(\n                    radialaxis=\u003Cspan class=\"hljs-built_in\">dict\u003C/span>(\n                        visible=\u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                        \u003Cspan class=\"hljs-built_in\">range\u003C/span>=[\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-number\">100\u003C/span>]\n                    )),\n                showlegend=\u003Cspan class=\"hljs-literal\">True\u003C/span>,\n                title=\u003Cspan class=\"hljs-string\">&quot;Quality Score by Category&quot;\u003C/span>\n            )\n            \n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> fig\n        \n\u003Cspan class=\"hljs-meta\">        @self.app.callback(\u003Cspan class=\"hljs-params\">\n            Output(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;trends-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;figure&#x27;\u003C/span>\u003C/span>),\n            Input(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;trends-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;id&#x27;\u003C/span>\u003C/span>)\n        \u003C/span>)\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">update_trends_chart\u003C/span>(\u003Cspan class=\"hljs-params\">chart_id\u003C/span>):\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.trends_data:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> go.Figure().add_annotation(\n                    text=\u003Cspan class=\"hljs-string\">&quot;No trend data available&quot;\u003C/span>, \n                    xref=\u003Cspan class=\"hljs-string\">&quot;paper&quot;\u003C/span>, yref=\u003Cspan class=\"hljs-string\">&quot;paper&quot;\u003C/span>,\n                    x=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, y=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, showarrow=\u003Cspan class=\"hljs-literal\">False\u003C/span>\n                )\n            \n            df = pd.DataFrame(self.trends_data)\n            df[\u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>] = pd.to_datetime(df[\u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>])\n            \n            fig = make_subplots(\n                rows=\u003Cspan class=\"hljs-number\">2\u003C/span>, cols=\u003Cspan class=\"hljs-number\">1\u003C/span>,\n                subplot_titles=(\u003Cspan class=\"hljs-string\">&#x27;Overall Quality Score&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;Issues Count&#x27;\u003C/span>),\n                vertical_spacing=\u003Cspan class=\"hljs-number\">0.1\u003C/span>\n            )\n            \n            \u003Cspan class=\"hljs-comment\"># Overall score trend\u003C/span>\n            fig.add_trace(\n                go.Scatter(\n                    x=df[\u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>], \n                    y=df[\u003Cspan class=\"hljs-string\">&#x27;overall_score&#x27;\u003C/span>],\n                    mode=\u003Cspan class=\"hljs-string\">&#x27;lines+markers&#x27;\u003C/span>,\n                    name=\u003Cspan class=\"hljs-string\">&#x27;Quality Score&#x27;\u003C/span>,\n                    line=\u003Cspan class=\"hljs-built_in\">dict\u003C/span>(color=\u003Cspan class=\"hljs-string\">&#x27;#3498db&#x27;\u003C/span>, width=\u003Cspan class=\"hljs-number\">3\u003C/span>)\n                ),\n                row=\u003Cspan class=\"hljs-number\">1\u003C/span>, col=\u003Cspan class=\"hljs-number\">1\u003C/span>\n            )\n            \n            \u003Cspan class=\"hljs-comment\"># Issues count trend\u003C/span>\n            fig.add_trace(\n                go.Scatter(\n                    x=df[\u003Cspan class=\"hljs-string\">&#x27;date&#x27;\u003C/span>], \n                    y=df[\u003Cspan class=\"hljs-string\">&#x27;total_issues&#x27;\u003C/span>],\n                    mode=\u003Cspan class=\"hljs-string\">&#x27;lines+markers&#x27;\u003C/span>,\n                    name=\u003Cspan class=\"hljs-string\">&#x27;Total Issues&#x27;\u003C/span>,\n                    line=\u003Cspan class=\"hljs-built_in\">dict\u003C/span>(color=\u003Cspan class=\"hljs-string\">&#x27;#e74c3c&#x27;\u003C/span>, width=\u003Cspan class=\"hljs-number\">3\u003C/span>)\n                ),\n                row=\u003Cspan class=\"hljs-number\">2\u003C/span>, col=\u003Cspan class=\"hljs-number\">1\u003C/span>\n            )\n            \n            fig.update_layout(height=\u003Cspan class=\"hljs-number\">600\u003C/span>, showlegend=\u003Cspan class=\"hljs-literal\">True\u003C/span>)\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> fig\n        \n\u003Cspan class=\"hljs-meta\">        @self.app.callback(\u003Cspan class=\"hljs-params\">\n            Output(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;rule-performance-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;figure&#x27;\u003C/span>\u003C/span>),\n            Input(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;rule-performance-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;id&#x27;\u003C/span>\u003C/span>)\n        \u003C/span>)\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">update_rule_performance\u003C/span>(\u003Cspan class=\"hljs-params\">chart_id\u003C/span>):\n            rule_perf = self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;rule_performance&#x27;\u003C/span>, {})\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> rule_perf:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> go.Figure().add_annotation(\n                    text=\u003Cspan class=\"hljs-string\">&quot;No rule performance data available&quot;\u003C/span>, \n                    xref=\u003Cspan class=\"hljs-string\">&quot;paper&quot;\u003C/span>, yref=\u003Cspan class=\"hljs-string\">&quot;paper&quot;\u003C/span>,\n                    x=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, y=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, showarrow=\u003Cspan class=\"hljs-literal\">False\u003C/span>\n                )\n            \n            rules = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(rule_perf.keys())\n            issue_counts = [rule_perf[rule].get(\u003Cspan class=\"hljs-string\">&#x27;issues&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>) \u003Cspan class=\"hljs-keyword\">for\u003C/span> rule \u003Cspan class=\"hljs-keyword\">in\u003C/span> rules]\n            \n            fig = go.Figure(data=[\n                go.Bar(\n                    x=issue_counts,\n                    y=rules,\n                    orientation=\u003Cspan class=\"hljs-string\">&#x27;h&#x27;\u003C/span>,\n                    marker_color=[\u003Cspan class=\"hljs-string\">&#x27;#e74c3c&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">if\u003C/span> count &gt; \u003Cspan class=\"hljs-number\">10\u003C/span> \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;#f39c12&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">if\u003C/span> count &gt; \u003Cspan class=\"hljs-number\">5\u003C/span> \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-string\">&#x27;#2ecc71&#x27;\u003C/span> \n                                 \u003Cspan class=\"hljs-keyword\">for\u003C/span> count \u003Cspan class=\"hljs-keyword\">in\u003C/span> issue_counts]\n                )\n            ])\n            \n            fig.update_layout(\n                title=\u003Cspan class=\"hljs-string\">&quot;Issues by Validation Rule&quot;\u003C/span>,\n                xaxis_title=\u003Cspan class=\"hljs-string\">&quot;Number of Issues&quot;\u003C/span>,\n                yaxis_title=\u003Cspan class=\"hljs-string\">&quot;Validation Rule&quot;\u003C/span>,\n                height=\u003Cspan class=\"hljs-built_in\">max\u003C/span>(\u003Cspan class=\"hljs-number\">400\u003C/span>, \u003Cspan class=\"hljs-built_in\">len\u003C/span>(rules) * \u003Cspan class=\"hljs-number\">30\u003C/span>)\n            )\n            \n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> fig\n        \n\u003Cspan class=\"hljs-meta\">        @self.app.callback(\u003Cspan class=\"hljs-params\">\n            Output(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;file-quality-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;figure&#x27;\u003C/span>\u003C/span>),\n            Input(\u003Cspan class=\"hljs-params\">\u003Cspan class=\"hljs-string\">&#x27;file-quality-chart&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;id&#x27;\u003C/span>\u003C/span>)\n        \u003C/span>)\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">update_file_quality_chart\u003C/span>(\u003Cspan class=\"hljs-params\">chart_id\u003C/span>):\n            file_dist = self.metrics_data.get(\u003Cspan class=\"hljs-string\">&#x27;file_quality_distribution&#x27;\u003C/span>, {})\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> file_dist:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> go.Figure().add_annotation(\n                    text=\u003Cspan class=\"hljs-string\">&quot;No file quality distribution data available&quot;\u003C/span>, \n                    xref=\u003Cspan class=\"hljs-string\">&quot;paper&quot;\u003C/span>, yref=\u003Cspan class=\"hljs-string\">&quot;paper&quot;\u003C/span>,\n                    x=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, y=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, showarrow=\u003Cspan class=\"hljs-literal\">False\u003C/span>\n                )\n            \n            labels = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(file_dist.keys())\n            values = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(file_dist.values())\n            colors = {\n                \u003Cspan class=\"hljs-string\">&#x27;excellent&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;#2ecc71&#x27;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;good&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;#3498db&#x27;\u003C/span>, \n                \u003Cspan class=\"hljs-string\">&#x27;fair&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;#f39c12&#x27;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;poor&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;#e74c3c&#x27;\u003C/span>,\n                \u003Cspan class=\"hljs-string\">&#x27;critical&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;#8e44ad&#x27;\u003C/span>\n            }\n            \n            fig = go.Figure(data=[\n                go.Pie(\n                    labels=labels, \n                    values=values,\n                    marker_colors=[colors.get(label, \u003Cspan class=\"hljs-string\">&#x27;#95a5a6&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">for\u003C/span> label \u003Cspan class=\"hljs-keyword\">in\u003C/span> labels],\n                    hole=\u003Cspan class=\"hljs-number\">0.3\u003C/span>\n                )\n            ])\n            \n            fig.update_layout(\n                title=\u003Cspan class=\"hljs-string\">&quot;File Quality Distribution&quot;\u003C/span>,\n                annotations=[\u003Cspan class=\"hljs-built_in\">dict\u003C/span>(text=\u003Cspan class=\"hljs-string\">&#x27;Files&#x27;\u003C/span>, x=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, y=\u003Cspan class=\"hljs-number\">0.5\u003C/span>, font_size=\u003Cspan class=\"hljs-number\">20\u003C/span>, showarrow=\u003Cspan class=\"hljs-literal\">False\u003C/span>)]\n            )\n            \n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> fig\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">run\u003C/span>(\u003Cspan class=\"hljs-params\">self, debug: \u003Cspan class=\"hljs-built_in\">bool\u003C/span> = \u003Cspan class=\"hljs-literal\">True\u003C/span>, port: \u003Cspan class=\"hljs-built_in\">int\u003C/span> = \u003Cspan class=\"hljs-number\">8050\u003C/span>\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Run the dashboard&quot;&quot;&quot;\u003C/span>\n        self.app.run_server(debug=debug, port=port)\n\n\u003Cspan class=\"hljs-comment\"># Usage\u003C/span>\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> __name__ == \u003Cspan class=\"hljs-string\">&quot;__main__&quot;\u003C/span>:\n    dashboard = QualityDashboard(\u003Cspan class=\"hljs-string\">&#x27;docs/quality-metrics.json&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;docs/quality-trends.json&#x27;\u003C/span>)\n    dashboard.run()\n\u003C/code>\u003C/pre>\u003Ch2 id=\"troubleshooting-common-validation-issues\">Troubleshooting Common Validation Issues\u003C/h2>\n\u003Ch3 id=\"performance-optimization-for-large-repositories\">Performance Optimization for Large Repositories\u003C/h3>\n\u003Cp>\u003Cstrong>Problem\u003C/strong>: Validation takes too long on large documentation repositories\u003C/p>\n\u003Cp>\u003Cstrong>Solutions\u003C/strong>:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\"># performance_optimizer.py - Optimize validation for large repositories\u003C/span>\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> multiprocessing \u003Cspan class=\"hljs-keyword\">as\u003C/span> mp\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> concurrent.futures \u003Cspan class=\"hljs-keyword\">import\u003C/span> ProcessPoolExecutor, ThreadPoolExecutor\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> asyncio\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> aiohttp\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> time\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> functools \u003Cspan class=\"hljs-keyword\">import\u003C/span> lru_cache\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> pickle\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> typing \u003Cspan class=\"hljs-keyword\">import\u003C/span> \u003Cspan class=\"hljs-type\">List\u003C/span>, \u003Cspan class=\"hljs-type\">Dict\u003C/span>, \u003Cspan class=\"hljs-type\">Any\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">OptimizedValidator\u003C/span>:\n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self, config: \u003Cspan class=\"hljs-type\">Dict\u003C/span>\u003C/span>):\n        self.config = config\n        self.cache = {}\n        self.session = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n        \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">setup_caching\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>):\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Setup validation result caching&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-comment\"># File hash-based caching\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">import\u003C/span> hashlib\n        \n        \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">get_file_hash\u003C/span>(\u003Cspan class=\"hljs-params\">file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">str\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(file_path, \u003Cspan class=\"hljs-string\">&#x27;rb&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> hashlib.md5(f.read()).hexdigest()\n        \n        self.get_file_hash = get_file_hash\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_files_parallel\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_paths: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate files using parallel processing&quot;&quot;&quot;\u003C/span>\n        cpu_count = mp.cpu_count()\n        chunk_size = \u003Cspan class=\"hljs-built_in\">max\u003C/span>(\u003Cspan class=\"hljs-number\">1\u003C/span>, \u003Cspan class=\"hljs-built_in\">len\u003C/span>(file_paths) // cpu_count)\n        \n        \u003Cspan class=\"hljs-keyword\">with\u003C/span> ProcessPoolExecutor(max_workers=cpu_count) \u003Cspan class=\"hljs-keyword\">as\u003C/span> executor:\n            \u003Cspan class=\"hljs-comment\"># Split files into chunks for parallel processing\u003C/span>\n            file_chunks = [file_paths[i:i + chunk_size] \n                          \u003Cspan class=\"hljs-keyword\">for\u003C/span> i \u003Cspan class=\"hljs-keyword\">in\u003C/span> \u003Cspan class=\"hljs-built_in\">range\u003C/span>(\u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-built_in\">len\u003C/span>(file_paths), chunk_size)]\n            \n            \u003Cspan class=\"hljs-comment\"># Submit validation tasks\u003C/span>\n            futures = [executor.submit(self.validate_chunk, chunk) \n                      \u003Cspan class=\"hljs-keyword\">for\u003C/span> chunk \u003Cspan class=\"hljs-keyword\">in\u003C/span> file_chunks]\n            \n            \u003Cspan class=\"hljs-comment\"># Collect results\u003C/span>\n            all_results = []\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> future \u003Cspan class=\"hljs-keyword\">in\u003C/span> futures:\n                all_results.extend(future.result())\n            \n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> all_results\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_chunk\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_paths: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate a chunk of files&quot;&quot;&quot;\u003C/span>\n        validator = ContentValidator(self.config)\n        results = []\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> file_path \u003Cspan class=\"hljs-keyword\">in\u003C/span> file_paths:\n            \u003Cspan class=\"hljs-comment\"># Check cache first\u003C/span>\n            file_hash = self.get_file_hash(file_path)\n            cache_key = \u003Cspan class=\"hljs-string\">f&quot;\u003Cspan class=\"hljs-subst\">{file_path}\u003C/span>:\u003Cspan class=\"hljs-subst\">{file_hash}\u003C/span>&quot;\u003C/span>\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> cache_key \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.cache:\n                results.extend(self.cache[cache_key])\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Validate file\u003C/span>\n            file_results = validator.validate_file(file_path)\n            self.cache[cache_key] = file_results\n            results.extend(file_results)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> results\n    \n    \u003Cspan class=\"hljs-keyword\">async\u003C/span> \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">validate_external_links_async\u003C/span>(\u003Cspan class=\"hljs-params\">self, links: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-built_in\">bool\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Validate external links asynchronously&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.session:\n            timeout = aiohttp.ClientTimeout(total=\u003Cspan class=\"hljs-number\">10\u003C/span>)\n            self.session = aiohttp.ClientSession(timeout=timeout)\n        \n        \u003Cspan class=\"hljs-keyword\">async\u003C/span> \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">check_link\u003C/span>(\u003Cspan class=\"hljs-params\">session: aiohttp.ClientSession, url: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">tuple\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-built_in\">bool\u003C/span>]:\n            \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">async\u003C/span> \u003Cspan class=\"hljs-keyword\">with\u003C/span> session.head(url, allow_redirects=\u003Cspan class=\"hljs-literal\">True\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> response:\n                    \u003Cspan class=\"hljs-keyword\">return\u003C/span> url, response.status &lt; \u003Cspan class=\"hljs-number\">400\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">except\u003C/span>:\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> url, \u003Cspan class=\"hljs-literal\">False\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Batch process links\u003C/span>\n        tasks = [check_link(self.session, url) \u003Cspan class=\"hljs-keyword\">for\u003C/span> url \u003Cspan class=\"hljs-keyword\">in\u003C/span> links]\n        results = \u003Cspan class=\"hljs-keyword\">await\u003C/span> asyncio.gather(*tasks, return_exceptions=\u003Cspan class=\"hljs-literal\">True\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {url: result \u003Cspan class=\"hljs-keyword\">for\u003C/span> url, result \u003Cspan class=\"hljs-keyword\">in\u003C/span> results \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-built_in\">isinstance\u003C/span>(result, Exception)}\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">incremental_validation\u003C/span>(\u003Cspan class=\"hljs-params\">self, base_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, changed_files: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Run incremental validation on changed files only&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> changed_files \u003Cspan class=\"hljs-keyword\">is\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>:\n            \u003Cspan class=\"hljs-comment\"># Get changed files from Git\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">import\u003C/span> subprocess\n            result = subprocess.run([\u003Cspan class=\"hljs-string\">&#x27;git&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;diff&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;--name-only&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;HEAD~1&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;HEAD&#x27;\u003C/span>], \n                                 capture_output=\u003Cspan class=\"hljs-literal\">True\u003C/span>, text=\u003Cspan class=\"hljs-literal\">True\u003C/span>, cwd=base_path)\n            changed_files = result.stdout.strip().split(\u003Cspan class=\"hljs-string\">&#x27;\\n&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">if\u003C/span> result.stdout \u003Cspan class=\"hljs-keyword\">else\u003C/span> []\n            changed_files = [f \u003Cspan class=\"hljs-keyword\">for\u003C/span> f \u003Cspan class=\"hljs-keyword\">in\u003C/span> changed_files \u003Cspan class=\"hljs-keyword\">if\u003C/span> f.endswith(\u003Cspan class=\"hljs-string\">&#x27;.md&#x27;\u003C/span>)]\n        \n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> changed_files:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\u003Cspan class=\"hljs-string\">&#x27;message&#x27;\u003C/span>: \u003Cspan class=\"hljs-string\">&#x27;No markdown files changed&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;results&#x27;\u003C/span>: []}\n        \n        \u003Cspan class=\"hljs-comment\"># Validate only changed files\u003C/span>\n        results = self.validate_files_parallel(changed_files)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;changed_files&#x27;\u003C/span>: changed_files,\n            \u003Cspan class=\"hljs-string\">&#x27;results&#x27;\u003C/span>: results,\n            \u003Cspan class=\"hljs-string\">&#x27;summary&#x27;\u003C/span>: self.generate_summary(results)\n        }\n    \n\u003Cspan class=\"hljs-meta\">    @lru_cache(\u003Cspan class=\"hljs-params\">maxsize=\u003Cspan class=\"hljs-number\">1000\u003C/span>\u003C/span>)\u003C/span>\n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">cached_rule_check\u003C/span>(\u003Cspan class=\"hljs-params\">self, rule_id: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, content_hash: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, rule_params: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Cache expensive rule checks&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-comment\"># This would implement the actual rule logic\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">pass\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">smart_link_checking\u003C/span>(\u003Cspan class=\"hljs-params\">self, links: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-built_in\">bool\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Smart link checking with caching and batching&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-comment\"># Group links by domain for efficient checking\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">from\u003C/span> urllib.parse \u003Cspan class=\"hljs-keyword\">import\u003C/span> urlparse\n        domain_groups = {}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> link \u003Cspan class=\"hljs-keyword\">in\u003C/span> links:\n            domain = urlparse(link).netloc\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> domain \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> domain_groups:\n                domain_groups[domain] = []\n            domain_groups[domain].append(link)\n        \n        \u003Cspan class=\"hljs-comment\"># Check each domain group with appropriate delays\u003C/span>\n        results = {}\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> domain, domain_links \u003Cspan class=\"hljs-keyword\">in\u003C/span> domain_groups.items():\n            domain_results = asyncio.run(\n                self.validate_external_links_async(domain_links)\n            )\n            results.update(domain_results)\n            \n            \u003Cspan class=\"hljs-comment\"># Add delay between domains to be respectful\u003C/span>\n            time.sleep(\u003Cspan class=\"hljs-number\">1\u003C/span>)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> results\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">generate_summary\u003C/span>(\u003Cspan class=\"hljs-params\">self, results: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Generate validation summary&quot;&quot;&quot;\u003C/span>\n        severity_counts = {\u003Cspan class=\"hljs-string\">&#x27;error&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;warning&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;info&#x27;\u003C/span>: \u003Cspan class=\"hljs-number\">0\u003C/span>}\n        rule_counts = {}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> result \u003Cspan class=\"hljs-keyword\">in\u003C/span> results:\n            severity_counts[result.get(\u003Cspan class=\"hljs-string\">&#x27;severity&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;info&#x27;\u003C/span>)] += \u003Cspan class=\"hljs-number\">1\u003C/span>\n            rule_id = result.get(\u003Cspan class=\"hljs-string\">&#x27;rule_id&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;unknown&#x27;\u003C/span>)\n            rule_counts[rule_id] = rule_counts.get(rule_id, \u003Cspan class=\"hljs-number\">0\u003C/span>) + \u003Cspan class=\"hljs-number\">1\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;total_issues&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">len\u003C/span>(results),\n            \u003Cspan class=\"hljs-string\">&#x27;by_severity&#x27;\u003C/span>: severity_counts,\n            \u003Cspan class=\"hljs-string\">&#x27;top_rules&#x27;\u003C/span>: \u003Cspan class=\"hljs-built_in\">sorted\u003C/span>(rule_counts.items(), key=\u003Cspan class=\"hljs-keyword\">lambda\u003C/span> x: x[\u003Cspan class=\"hljs-number\">1\u003C/span>], reverse=\u003Cspan class=\"hljs-literal\">True\u003C/span>)[:\u003Cspan class=\"hljs-number\">5\u003C/span>],\n            \u003Cspan class=\"hljs-string\">&#x27;validation_time&#x27;\u003C/span>: time.time()\n        }\n\n\u003Cspan class=\"hljs-comment\"># Usage example\u003C/span>\n\u003Cspan class=\"hljs-keyword\">if\u003C/span> __name__ == \u003Cspan class=\"hljs-string\">&quot;__main__&quot;\u003C/span>:\n    config = {\u003Cspan class=\"hljs-string\">&#x27;rules&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;links&#x27;\u003C/span>: {\u003Cspan class=\"hljs-string\">&#x27;enabled&#x27;\u003C/span>: \u003Cspan class=\"hljs-literal\">True\u003C/span>}}}  \u003Cspan class=\"hljs-comment\"># Simplified config\u003C/span>\n    \n    optimizer = OptimizedValidator(config)\n    optimizer.setup_caching()\n    \n    \u003Cspan class=\"hljs-comment\"># Run incremental validation\u003C/span>\n    results = optimizer.incremental_validation(\u003Cspan class=\"hljs-string\">&#x27;.&#x27;\u003C/span>)\n    \u003Cspan class=\"hljs-built_in\">print\u003C/span>(json.dumps(results, indent=\u003Cspan class=\"hljs-number\">2\u003C/span>))\n\u003C/code>\u003C/pre>\u003Ch3 id=\"false-positive-management\">False Positive Management\u003C/h3>\n\u003Cp>\u003Cstrong>Problem\u003C/strong>: Validation rules generating too many false positives\u003C/p>\n\u003Cp>\u003Cstrong>Solutions\u003C/strong>:\u003C/p>\n\u003Cpre>\u003Ccode class=\"hljs language-python\">\u003Cspan class=\"hljs-comment\"># false_positive_manager.py - Manage and reduce false positives\u003C/span>\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> re\n\u003Cspan class=\"hljs-keyword\">import\u003C/span> yaml\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> typing \u003Cspan class=\"hljs-keyword\">import\u003C/span> \u003Cspan class=\"hljs-type\">Dict\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>, \u003Cspan class=\"hljs-type\">Set\u003C/span>, \u003Cspan class=\"hljs-type\">Optional\u003C/span>\n\u003Cspan class=\"hljs-keyword\">from\u003C/span> dataclasses \u003Cspan class=\"hljs-keyword\">import\u003C/span> dataclass\n\n\u003Cspan class=\"hljs-meta\">@dataclass\u003C/span>\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">Suppression\u003C/span>:\n    rule_id: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\n    file_pattern: \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    line_pattern: \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    reason: \u003Cspan class=\"hljs-built_in\">str\u003C/span> = \u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>\n    expires: \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>] = \u003Cspan class=\"hljs-literal\">None\u003C/span>\n\n\u003Cspan class=\"hljs-keyword\">class\u003C/span> \u003Cspan class=\"hljs-title class_\">FalsePositiveManager\u003C/span>:\n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">__init__\u003C/span>(\u003Cspan class=\"hljs-params\">self, suppressions_file: \u003Cspan class=\"hljs-built_in\">str\u003C/span> = \u003Cspan class=\"hljs-string\">&quot;validation_suppressions.yaml&quot;\u003C/span>\u003C/span>):\n        self.suppressions = self.load_suppressions(suppressions_file)\n        self.whitelist_patterns = self.load_whitelist_patterns()\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">load_suppressions\u003C/span>(\u003Cspan class=\"hljs-params\">self, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[Suppression]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Load validation suppressions from YAML file&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">try\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">with\u003C/span> \u003Cspan class=\"hljs-built_in\">open\u003C/span>(file_path, \u003Cspan class=\"hljs-string\">&#x27;r&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">as\u003C/span> f:\n                data = yaml.safe_load(f)\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> [Suppression(**item) \u003Cspan class=\"hljs-keyword\">for\u003C/span> item \u003Cspan class=\"hljs-keyword\">in\u003C/span> data.get(\u003Cspan class=\"hljs-string\">&#x27;suppressions&#x27;\u003C/span>, [])]\n        \u003Cspan class=\"hljs-keyword\">except\u003C/span> FileNotFoundError:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> []\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">load_whitelist_patterns\u003C/span>(\u003Cspan class=\"hljs-params\">self\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Dict\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>, \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Load rule-specific whitelist patterns&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> {\n            \u003Cspan class=\"hljs-string\">&#x27;link_broken_external&#x27;\u003C/span>: [\n                \u003Cspan class=\"hljs-string\">r&#x27;https://example\\.com.*&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># Example URLs\u003C/span>\n                \u003Cspan class=\"hljs-string\">r&#x27;https://placeholder\\..*&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># Placeholder URLs\u003C/span>\n                \u003Cspan class=\"hljs-string\">r&#x27;https://.*\\.localhost.*&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># Local development URLs\u003C/span>\n            ],\n            \u003Cspan class=\"hljs-string\">&#x27;image_missing_alt&#x27;\u003C/span>: [\n                \u003Cspan class=\"hljs-string\">r&#x27;!\\[.*\\]\\(.*spacer\\.gif\\)&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># Spacer images\u003C/span>\n                \u003Cspan class=\"hljs-string\">r&#x27;!\\[.*\\]\\(.*pixel\\.png\\)&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># Tracking pixels\u003C/span>\n            ],\n            \u003Cspan class=\"hljs-string\">&#x27;heading_generic&#x27;\u003C/span>: [\n                \u003Cspan class=\"hljs-string\">r&#x27;^(Overview|Introduction|Getting Started)$&#x27;\u003C/span>,  \u003Cspan class=\"hljs-comment\"># Allow common generic headings\u003C/span>\n            ]\n        }\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">should_suppress\u003C/span>(\u003Cspan class=\"hljs-params\">self, result: \u003Cspan class=\"hljs-type\">Dict\u003C/span>, file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, line_content: \u003Cspan class=\"hljs-built_in\">str\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-built_in\">bool\u003C/span>:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Check if a validation result should be suppressed&quot;&quot;&quot;\u003C/span>\n        rule_id = result.get(\u003Cspan class=\"hljs-string\">&#x27;rule_id&#x27;\u003C/span>)\n        \n        \u003Cspan class=\"hljs-comment\"># Check suppressions\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> suppression \u003Cspan class=\"hljs-keyword\">in\u003C/span> self.suppressions:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> suppression.rule_id != rule_id:\n                \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Check file pattern\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> suppression.file_pattern:\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> re.search(suppression.file_pattern, file_path):\n                    \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Check line pattern\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> suppression.line_pattern:\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> re.search(suppression.line_pattern, line_content):\n                    \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            \u003Cspan class=\"hljs-comment\"># Check expiration\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> suppression.expires:\n                \u003Cspan class=\"hljs-keyword\">from\u003C/span> datetime \u003Cspan class=\"hljs-keyword\">import\u003C/span> datetime\n                expire_date = datetime.fromisoformat(suppression.expires)\n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> datetime.now() &gt; expire_date:\n                    \u003Cspan class=\"hljs-keyword\">continue\u003C/span>\n            \n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">True\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Check whitelist patterns\u003C/span>\n        patterns = self.whitelist_patterns.get(rule_id, [])\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> pattern \u003Cspan class=\"hljs-keyword\">in\u003C/span> patterns:\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> re.search(pattern, result.get(\u003Cspan class=\"hljs-string\">&#x27;context&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C/span>) \u003Cspan class=\"hljs-keyword\">or\u003C/span> line_content):\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">True\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">False\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">create_smart_suppressions\u003C/span>(\u003Cspan class=\"hljs-params\">self, results: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>], threshold: \u003Cspan class=\"hljs-built_in\">int\u003C/span> = \u003Cspan class=\"hljs-number\">5\u003C/span>\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[Suppression]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Automatically suggest suppressions for frequently occurring issues&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-comment\"># Count rule occurrences\u003C/span>\n        rule_counts = {}\n        rule_contexts = {}\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> result \u003Cspan class=\"hljs-keyword\">in\u003C/span> results:\n            rule_id = result.get(\u003Cspan class=\"hljs-string\">&#x27;rule_id&#x27;\u003C/span>)\n            context = result.get(\u003Cspan class=\"hljs-string\">&#x27;context&#x27;\u003C/span>, \u003Cspan class=\"hljs-string\">&#x27;&#x27;\u003C/span>)\n            \n            rule_counts[rule_id] = rule_counts.get(rule_id, \u003Cspan class=\"hljs-number\">0\u003C/span>) + \u003Cspan class=\"hljs-number\">1\u003C/span>\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> rule_id \u003Cspan class=\"hljs-keyword\">not\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> rule_contexts:\n                rule_contexts[rule_id] = []\n            rule_contexts[rule_id].append(context)\n        \n        \u003Cspan class=\"hljs-comment\"># Suggest suppressions for high-frequency rules\u003C/span>\n        suggestions = []\n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> rule_id, count \u003Cspan class=\"hljs-keyword\">in\u003C/span> rule_counts.items():\n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> count &gt;= threshold:\n                \u003Cspan class=\"hljs-comment\"># Analyze contexts to find common patterns\u003C/span>\n                contexts = rule_contexts[rule_id]\n                common_pattern = self.find_common_pattern(contexts)\n                \n                \u003Cspan class=\"hljs-keyword\">if\u003C/span> common_pattern:\n                    suggestions.append(Suppression(\n                        rule_id=rule_id,\n                        line_pattern=common_pattern,\n                        reason=\u003Cspan class=\"hljs-string\">f&quot;Auto-suggested: \u003Cspan class=\"hljs-subst\">{count}\u003C/span> occurrences with common pattern&quot;\u003C/span>\n                    ))\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> suggestions\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">find_common_pattern\u003C/span>(\u003Cspan class=\"hljs-params\">self, contexts: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">Optional\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Find common pattern in validation contexts&quot;&quot;&quot;\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(contexts) &lt; \u003Cspan class=\"hljs-number\">2\u003C/span>:\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>\n        \n        \u003Cspan class=\"hljs-comment\"># Simple pattern detection - find common prefixes/suffixes\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">len\u003C/span>(\u003Cspan class=\"hljs-built_in\">set\u003C/span>(contexts)) == \u003Cspan class=\"hljs-number\">1\u003C/span>:\n            \u003Cspan class=\"hljs-comment\"># All contexts are identical\u003C/span>\n            \u003Cspan class=\"hljs-keyword\">return\u003C/span> re.escape(contexts[\u003Cspan class=\"hljs-number\">0\u003C/span>])\n        \n        \u003Cspan class=\"hljs-comment\"># Check for common URL patterns\u003C/span>\n        \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-built_in\">all\u003C/span>(\u003Cspan class=\"hljs-string\">&#x27;http&#x27;\u003C/span> \u003Cspan class=\"hljs-keyword\">in\u003C/span> ctx \u003Cspan class=\"hljs-keyword\">for\u003C/span> ctx \u003Cspan class=\"hljs-keyword\">in\u003C/span> contexts):\n            domains = [re.findall(\u003Cspan class=\"hljs-string\">r&#x27;https?://([^/]+)&#x27;\u003C/span>, ctx) \u003Cspan class=\"hljs-keyword\">for\u003C/span> ctx \u003Cspan class=\"hljs-keyword\">in\u003C/span> contexts]\n            common_domains = \u003Cspan class=\"hljs-built_in\">set\u003C/span>(domains[\u003Cspan class=\"hljs-number\">0\u003C/span>])\n            \u003Cspan class=\"hljs-keyword\">for\u003C/span> domain_list \u003Cspan class=\"hljs-keyword\">in\u003C/span> domains[\u003Cspan class=\"hljs-number\">1\u003C/span>:]:\n                common_domains &amp;= \u003Cspan class=\"hljs-built_in\">set\u003C/span>(domain_list)\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> common_domains:\n                domain = \u003Cspan class=\"hljs-built_in\">list\u003C/span>(common_domains)[\u003Cspan class=\"hljs-number\">0\u003C/span>]\n                \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-string\">f&#x27;https?://\u003Cspan class=\"hljs-subst\">{re.escape(domain)}\u003C/span>.*&#x27;\u003C/span>\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> \u003Cspan class=\"hljs-literal\">None\u003C/span>\n    \n    \u003Cspan class=\"hljs-keyword\">def\u003C/span> \u003Cspan class=\"hljs-title function_\">filter_results\u003C/span>(\u003Cspan class=\"hljs-params\">self, results: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>], file_path: \u003Cspan class=\"hljs-built_in\">str\u003C/span>, file_lines: \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-built_in\">str\u003C/span>]\u003C/span>) -&gt; \u003Cspan class=\"hljs-type\">List\u003C/span>[\u003Cspan class=\"hljs-type\">Dict\u003C/span>]:\n        \u003Cspan class=\"hljs-string\">&quot;&quot;&quot;Filter validation results to remove suppressed issues&quot;&quot;&quot;\u003C/span>\n        filtered_results = []\n        \n        \u003Cspan class=\"hljs-keyword\">for\u003C/span> result \u003Cspan class=\"hljs-keyword\">in\u003C/span> results:\n            line_num = result.get(\u003Cspan class=\"hljs-string\">&#x27;line_number&#x27;\u003C/span>, \u003Cspan class=\"hljs-number\">0\u003C/span>)\n            line_content = file_lines[line_num - \u003Cspan class=\"hljs-number\">1\u003C/span>] \u003Cspan class=\"hljs-keyword\">if\u003C/span> line_num &gt; \u003Cspan class=\"hljs-number\">0\u003C/span> \u003Cspan class=\"hljs-keyword\">and\u003C/span> line_num &lt;= \u003Cspan class=\"hljs-built_in\">len\u003C/span>(file_lines) \u003Cspan class=\"hljs-keyword\">else\u003C/span> \u003Cspan class=\"hljs-string\">&quot;&quot;\u003C/span>\n            \n            \u003Cspan class=\"hljs-keyword\">if\u003C/span> \u003Cspan class=\"hljs-keyword\">not\u003C/span> self.should_suppress(result, file_path, line_content):\n                filtered_results.append(result)\n        \n        \u003Cspan class=\"hljs-keyword\">return\u003C/span> filtered_results\n\u003C/code>\u003C/pre>\u003Ch2 id=\"conclusion\">Conclusion\u003C/h2>\n\u003Cp>Automated Markdown content validation and quality assurance systems provide the foundation for maintaining professional documentation standards while enabling teams to scale their content creation processes efficiently. By implementing comprehensive validation frameworks, establishing quality metrics dashboards, and integrating automated checks into development workflows, organizations can ensure consistent, accessible, and high-quality documentation that serves users effectively while reducing manual oversight burden.\u003C/p>\n\u003Cp>The key to successful validation implementation lies in balancing comprehensive coverage with practical usability, ensuring that validation rules enhance rather than hinder the content creation process. Whether you&#39;re building internal documentation systems, open-source project documentation, or comprehensive knowledge bases, the techniques covered in this guide provide the tools necessary for creating robust, automated quality assurance systems that support both content creators and content consumers.\u003C/p>\n\u003Cp>Remember to continuously refine your validation rules based on team feedback and real-world usage patterns, implement performance optimizations for large repositories, and maintain clear documentation of validation standards to enable effective collaboration. With proper implementation of automated content validation, your documentation can achieve and maintain professional standards while supporting rapid content development and team scalability.\u003C/p>\n",[15,19,22,25,28,31,34],{"id":16,"text":17,"level":18},"why-master-automated-content-validation","Why Master Automated Content Validation?",2,{"id":20,"text":21,"level":18},"foundation-validation-systems","Foundation Validation Systems",{"id":23,"text":24,"level":18},"cicd-integration-and-automation","CI/CD Integration and Automation",{"id":26,"text":27,"level":18},"integration-with-content-management","Integration with Content Management",{"id":29,"text":30,"level":18},"advanced-quality-metrics-and-reporting","Advanced Quality Metrics and Reporting",{"id":32,"text":33,"level":18},"troubleshooting-common-validation-issues","Troubleshooting Common Validation Issues",{"id":35,"text":36,"level":18},"conclusion","Conclusion",[],[39,46,54],{"slug":40,"title":41,"description":42,"excerpt":43,"date":44,"category":9,"author":10,"keywords":45,"readingMinutes":12},"markdown-content-validation-automated-quality-assurance-complete-guide","Markdown Content Validation and Automated Quality Assurance: Complete Guide for Robust Documentation Workflows","Master comprehensive Markdown content validation techniques including syntax checking, link verification, accessibility testing, and automated quality assurance systems. Learn to build reliable documentation workflows with error prevention and content integrity checks.","Advanced Markdown content validation and automated quality assurance systems ensure documentation integrity, prevent content errors, and maintain consistent formatting standards across large-scale…","2025-10-09","markdown validation, markdown quality assurance, markdown syntax checking, link validation markdown, markdown testing automation, content validation tools, markdown linting, documentation qa",{"slug":47,"title":48,"description":49,"excerpt":50,"date":51,"category":9,"author":10,"keywords":52,"readingMinutes":53},"markdown-error-handling-validation-complete-guide","Markdown Error Handling and Validation: Complete Guide for Content Quality Assurance and Automated Checking","Master Markdown error handling, validation techniques, and automated quality assurance. Learn syntax checking, link validation, content linting, and comprehensive testing strategies for robust Markdown workflows.","Markdown error handling and validation techniques enable content teams to maintain high-quality documentation through automated quality assurance processes that catch syntax errors, validate…","2025-12-04","markdown validation, markdown error handling, markdown linting, content quality assurance, markdown syntax checking, automated markdown testing, markdown workflow validation",28,{"slug":55,"title":56,"description":57,"excerpt":58,"date":59,"category":9,"author":10,"keywords":60,"readingMinutes":61},"markdown-table-data-validation-quality-assurance-complete-guide","Markdown Table Data Validation and Quality Assurance: Complete Guide for Automated Table Content Verification","Master comprehensive table data validation techniques in Markdown for automated quality assurance, content verification, and structural integrity checking. Learn advanced validation patterns and automated testing workflows.","Markdown table data validation and quality assurance ensure accurate, consistent, and reliable table content across documentation systems through automated verification, structural integrity…","2025-11-09","markdown table validation, data quality assurance, table content verification, automated markdown testing, table structure validation, data integrity checking, markdown quality control, table validation tools",22,1792184943087]