#
tokens: 36736/50000 2/274 files (page 18/20)
lines: off (toggle) GitHub
raw markdown copy
This is page 18 of 20. Use http://codebase.md/tosin2013/documcp?page={x} to view the full context.

# Directory Structure

```
├── .dockerignore
├── .eslintignore
├── .eslintrc.json
├── .github
│   ├── agents
│   │   ├── documcp-ast.md
│   │   ├── documcp-deploy.md
│   │   ├── documcp-memory.md
│   │   ├── documcp-test.md
│   │   └── documcp-tool.md
│   ├── copilot-instructions.md
│   ├── dependabot.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── automated-changelog.md
│   │   ├── bug_report.md
│   │   ├── bug_report.yml
│   │   ├── documentation_issue.md
│   │   ├── feature_request.md
│   │   ├── feature_request.yml
│   │   ├── npm-publishing-fix.md
│   │   └── release_improvements.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── release-drafter.yml
│   └── workflows
│       ├── auto-merge.yml
│       ├── ci.yml
│       ├── codeql.yml
│       ├── dependency-review.yml
│       ├── deploy-docs.yml
│       ├── README.md
│       ├── release-drafter.yml
│       └── release.yml
├── .gitignore
├── .husky
│   ├── commit-msg
│   └── pre-commit
├── .linkcheck.config.json
├── .markdown-link-check.json
├── .nvmrc
├── .pre-commit-config.yaml
├── .versionrc.json
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── commitlint.config.js
├── CONTRIBUTING.md
├── docker-compose.docs.yml
├── Dockerfile.docs
├── docs
│   ├── .docusaurus
│   │   ├── docusaurus-plugin-content-docs
│   │   │   └── default
│   │   │       └── __mdx-loader-dependency.json
│   │   └── docusaurus-plugin-content-pages
│   │       └── default
│   │           └── __plugin.json
│   ├── adrs
│   │   ├── 001-mcp-server-architecture.md
│   │   ├── 002-repository-analysis-engine.md
│   │   ├── 003-static-site-generator-recommendation-engine.md
│   │   ├── 004-diataxis-framework-integration.md
│   │   ├── 005-github-pages-deployment-automation.md
│   │   ├── 006-mcp-tools-api-design.md
│   │   ├── 007-mcp-prompts-and-resources-integration.md
│   │   ├── 008-intelligent-content-population-engine.md
│   │   ├── 009-content-accuracy-validation-framework.md
│   │   ├── 010-mcp-resource-pattern-redesign.md
│   │   └── README.md
│   ├── api
│   │   ├── .nojekyll
│   │   ├── assets
│   │   │   ├── hierarchy.js
│   │   │   ├── highlight.css
│   │   │   ├── icons.js
│   │   │   ├── icons.svg
│   │   │   ├── main.js
│   │   │   ├── navigation.js
│   │   │   ├── search.js
│   │   │   └── style.css
│   │   ├── hierarchy.html
│   │   ├── index.html
│   │   ├── modules.html
│   │   └── variables
│   │       └── TOOLS.html
│   ├── assets
│   │   └── logo.svg
│   ├── development
│   │   └── MCP_INSPECTOR_TESTING.md
│   ├── docusaurus.config.js
│   ├── explanation
│   │   ├── architecture.md
│   │   └── index.md
│   ├── guides
│   │   ├── link-validation.md
│   │   ├── playwright-integration.md
│   │   └── playwright-testing-workflow.md
│   ├── how-to
│   │   ├── analytics-setup.md
│   │   ├── custom-domains.md
│   │   ├── documentation-freshness-tracking.md
│   │   ├── github-pages-deployment.md
│   │   ├── index.md
│   │   ├── local-testing.md
│   │   ├── performance-optimization.md
│   │   ├── prompting-guide.md
│   │   ├── repository-analysis.md
│   │   ├── seo-optimization.md
│   │   ├── site-monitoring.md
│   │   ├── troubleshooting.md
│   │   └── usage-examples.md
│   ├── index.md
│   ├── knowledge-graph.md
│   ├── package-lock.json
│   ├── package.json
│   ├── phase-2-intelligence.md
│   ├── reference
│   │   ├── api-overview.md
│   │   ├── cli.md
│   │   ├── configuration.md
│   │   ├── deploy-pages.md
│   │   ├── index.md
│   │   ├── mcp-tools.md
│   │   └── prompt-templates.md
│   ├── research
│   │   ├── cross-domain-integration
│   │   │   └── README.md
│   │   ├── domain-1-mcp-architecture
│   │   │   ├── index.md
│   │   │   └── mcp-performance-research.md
│   │   ├── domain-2-repository-analysis
│   │   │   └── README.md
│   │   ├── domain-3-ssg-recommendation
│   │   │   ├── index.md
│   │   │   └── ssg-performance-analysis.md
│   │   ├── domain-4-diataxis-integration
│   │   │   └── README.md
│   │   ├── domain-5-github-deployment
│   │   │   ├── github-pages-security-analysis.md
│   │   │   └── index.md
│   │   ├── domain-6-api-design
│   │   │   └── README.md
│   │   ├── README.md
│   │   ├── research-integration-summary-2025-01-14.md
│   │   ├── research-progress-template.md
│   │   └── research-questions-2025-01-14.md
│   ├── robots.txt
│   ├── sidebars.js
│   ├── sitemap.xml
│   ├── src
│   │   └── css
│   │       └── custom.css
│   └── tutorials
│       ├── development-setup.md
│       ├── environment-setup.md
│       ├── first-deployment.md
│       ├── getting-started.md
│       ├── index.md
│       ├── memory-workflows.md
│       └── user-onboarding.md
├── jest.config.js
├── LICENSE
├── Makefile
├── MCP_PHASE2_IMPLEMENTATION.md
├── mcp-config-example.json
├── mcp.json
├── package-lock.json
├── package.json
├── README.md
├── release.sh
├── scripts
│   └── check-package-structure.cjs
├── SECURITY.md
├── setup-precommit.sh
├── src
│   ├── benchmarks
│   │   └── performance.ts
│   ├── index.ts
│   ├── memory
│   │   ├── contextual-retrieval.ts
│   │   ├── deployment-analytics.ts
│   │   ├── enhanced-manager.ts
│   │   ├── export-import.ts
│   │   ├── freshness-kg-integration.ts
│   │   ├── index.ts
│   │   ├── integration.ts
│   │   ├── kg-code-integration.ts
│   │   ├── kg-health.ts
│   │   ├── kg-integration.ts
│   │   ├── kg-link-validator.ts
│   │   ├── kg-storage.ts
│   │   ├── knowledge-graph.ts
│   │   ├── learning.ts
│   │   ├── manager.ts
│   │   ├── multi-agent-sharing.ts
│   │   ├── pruning.ts
│   │   ├── schemas.ts
│   │   ├── storage.ts
│   │   ├── temporal-analysis.ts
│   │   ├── user-preferences.ts
│   │   └── visualization.ts
│   ├── prompts
│   │   └── technical-writer-prompts.ts
│   ├── scripts
│   │   └── benchmark.ts
│   ├── templates
│   │   └── playwright
│   │       ├── accessibility.spec.template.ts
│   │       ├── Dockerfile.template
│   │       ├── docs-e2e.workflow.template.yml
│   │       ├── link-validation.spec.template.ts
│   │       └── playwright.config.template.ts
│   ├── tools
│   │   ├── analyze-deployments.ts
│   │   ├── analyze-readme.ts
│   │   ├── analyze-repository.ts
│   │   ├── check-documentation-links.ts
│   │   ├── deploy-pages.ts
│   │   ├── detect-gaps.ts
│   │   ├── evaluate-readme-health.ts
│   │   ├── generate-config.ts
│   │   ├── generate-contextual-content.ts
│   │   ├── generate-llm-context.ts
│   │   ├── generate-readme-template.ts
│   │   ├── generate-technical-writer-prompts.ts
│   │   ├── kg-health-check.ts
│   │   ├── manage-preferences.ts
│   │   ├── manage-sitemap.ts
│   │   ├── optimize-readme.ts
│   │   ├── populate-content.ts
│   │   ├── readme-best-practices.ts
│   │   ├── recommend-ssg.ts
│   │   ├── setup-playwright-tests.ts
│   │   ├── setup-structure.ts
│   │   ├── sync-code-to-docs.ts
│   │   ├── test-local-deployment.ts
│   │   ├── track-documentation-freshness.ts
│   │   ├── update-existing-documentation.ts
│   │   ├── validate-content.ts
│   │   ├── validate-documentation-freshness.ts
│   │   ├── validate-readme-checklist.ts
│   │   └── verify-deployment.ts
│   ├── types
│   │   └── api.ts
│   ├── utils
│   │   ├── ast-analyzer.ts
│   │   ├── code-scanner.ts
│   │   ├── content-extractor.ts
│   │   ├── drift-detector.ts
│   │   ├── freshness-tracker.ts
│   │   ├── language-parsers-simple.ts
│   │   ├── permission-checker.ts
│   │   └── sitemap-generator.ts
│   └── workflows
│       └── documentation-workflow.ts
├── test-docs-local.sh
├── tests
│   ├── api
│   │   └── mcp-responses.test.ts
│   ├── benchmarks
│   │   └── performance.test.ts
│   ├── edge-cases
│   │   └── error-handling.test.ts
│   ├── functional
│   │   └── tools.test.ts
│   ├── integration
│   │   ├── kg-documentation-workflow.test.ts
│   │   ├── knowledge-graph-workflow.test.ts
│   │   ├── mcp-readme-tools.test.ts
│   │   ├── memory-mcp-tools.test.ts
│   │   ├── readme-technical-writer.test.ts
│   │   └── workflow.test.ts
│   ├── memory
│   │   ├── contextual-retrieval.test.ts
│   │   ├── enhanced-manager.test.ts
│   │   ├── export-import.test.ts
│   │   ├── freshness-kg-integration.test.ts
│   │   ├── kg-code-integration.test.ts
│   │   ├── kg-health.test.ts
│   │   ├── kg-link-validator.test.ts
│   │   ├── kg-storage-validation.test.ts
│   │   ├── kg-storage.test.ts
│   │   ├── knowledge-graph-enhanced.test.ts
│   │   ├── knowledge-graph.test.ts
│   │   ├── learning.test.ts
│   │   ├── manager-advanced.test.ts
│   │   ├── manager.test.ts
│   │   ├── mcp-resource-integration.test.ts
│   │   ├── mcp-tool-persistence.test.ts
│   │   ├── schemas.test.ts
│   │   ├── storage.test.ts
│   │   ├── temporal-analysis.test.ts
│   │   └── user-preferences.test.ts
│   ├── performance
│   │   ├── memory-load-testing.test.ts
│   │   └── memory-stress-testing.test.ts
│   ├── prompts
│   │   ├── guided-workflow-prompts.test.ts
│   │   └── technical-writer-prompts.test.ts
│   ├── server.test.ts
│   ├── setup.ts
│   ├── tools
│   │   ├── all-tools.test.ts
│   │   ├── analyze-coverage.test.ts
│   │   ├── analyze-deployments.test.ts
│   │   ├── analyze-readme.test.ts
│   │   ├── analyze-repository.test.ts
│   │   ├── check-documentation-links.test.ts
│   │   ├── deploy-pages-kg-retrieval.test.ts
│   │   ├── deploy-pages-tracking.test.ts
│   │   ├── deploy-pages.test.ts
│   │   ├── detect-gaps.test.ts
│   │   ├── evaluate-readme-health.test.ts
│   │   ├── generate-contextual-content.test.ts
│   │   ├── generate-llm-context.test.ts
│   │   ├── generate-readme-template.test.ts
│   │   ├── generate-technical-writer-prompts.test.ts
│   │   ├── kg-health-check.test.ts
│   │   ├── manage-sitemap.test.ts
│   │   ├── optimize-readme.test.ts
│   │   ├── readme-best-practices.test.ts
│   │   ├── recommend-ssg-historical.test.ts
│   │   ├── recommend-ssg-preferences.test.ts
│   │   ├── recommend-ssg.test.ts
│   │   ├── simple-coverage.test.ts
│   │   ├── sync-code-to-docs.test.ts
│   │   ├── test-local-deployment.test.ts
│   │   ├── tool-error-handling.test.ts
│   │   ├── track-documentation-freshness.test.ts
│   │   ├── validate-content.test.ts
│   │   ├── validate-documentation-freshness.test.ts
│   │   └── validate-readme-checklist.test.ts
│   ├── types
│   │   └── type-safety.test.ts
│   └── utils
│       ├── ast-analyzer.test.ts
│       ├── content-extractor.test.ts
│       ├── drift-detector.test.ts
│       ├── freshness-tracker.test.ts
│       └── sitemap-generator.test.ts
├── tsconfig.json
└── typedoc.json
```

# Files

--------------------------------------------------------------------------------
/src/tools/validate-content.ts:
--------------------------------------------------------------------------------

```typescript
import { Tool } from "@modelcontextprotocol/sdk/types.js";
import * as fs from "fs/promises";
import * as path from "path";
import { exec } from "child_process";
import { promisify } from "util";
import { handleMemoryRecall } from "../memory/index.js";
// ESM-compatible dirname replacement - fallback for test environments
function getDirname(): string {
  // Use process.cwd() as fallback for all environments to avoid import.meta issues
  return process.cwd();
}

const currentDir = getDirname();

const execAsync = promisify(exec);

interface ValidationOptions {
  contentPath: string;
  analysisId?: string;
  validationType: "accuracy" | "completeness" | "compliance" | "all";
  includeCodeValidation: boolean;
  confidence: "strict" | "moderate" | "permissive";
}

interface ConfidenceMetrics {
  overall: number;
  breakdown: {
    technologyDetection: number;
    frameworkVersionAccuracy: number;
    codeExampleRelevance: number;
    architecturalAssumptions: number;
    businessContextAlignment: number;
  };
  riskFactors: RiskFactor[];
}

interface RiskFactor {
  type: "high" | "medium" | "low";
  category: string;
  description: string;
  impact: string;
  mitigation: string;
}

interface UncertaintyFlag {
  area: string;
  severity: "low" | "medium" | "high" | "critical";
  description: string;
  potentialImpact: string;
  clarificationNeeded: string;
  fallbackStrategy: string;
}

interface ValidationIssue {
  type: "error" | "warning" | "info";
  category: "accuracy" | "completeness" | "compliance" | "performance";
  location: {
    file: string;
    line?: number;
    section?: string;
  };
  description: string;
  evidence: string[];
  suggestedFix: string;
  confidence: number;
}

interface CodeValidationResult {
  overallSuccess: boolean;
  exampleResults: ExampleValidation[];
  confidence: number;
}

interface ExampleValidation {
  example: string;
  compilationSuccess: boolean;
  executionSuccess: boolean;
  issues: ValidationIssue[];
  confidence: number;
}

export interface ValidationResult {
  success: boolean;
  confidence: ConfidenceMetrics;
  issues: ValidationIssue[];
  uncertainties: UncertaintyFlag[];
  codeValidation?: CodeValidationResult;
  recommendations: string[];
  nextSteps: string[];
}

class ContentAccuracyValidator {
  private projectContext: any;
  private tempDir: string;

  constructor() {
    this.tempDir = path.join(currentDir, ".tmp");
  }

  async validateContent(
    options: ValidationOptions,
    context?: any,
  ): Promise<ValidationResult> {
    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 0, total: 100 });
    }

    const result: ValidationResult = {
      success: false,
      confidence: this.initializeConfidenceMetrics(),
      issues: [],
      uncertainties: [],
      recommendations: [],
      nextSteps: [],
    };

    // Load project context if analysis ID provided
    if (options.analysisId) {
      await context?.info?.("📊 Loading project context...");
      this.projectContext = await this.loadProjectContext(options.analysisId);
    }

    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 20, total: 100 });
    }

    // Determine if we should analyze application code vs documentation
    await context?.info?.("🔎 Analyzing content type...");
    const isApplicationValidation = await this.shouldAnalyzeApplicationCode(
      options.contentPath,
    );

    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 40, total: 100 });
    }

    // Perform different types of validation based on request
    if (
      options.validationType === "all" ||
      options.validationType === "accuracy"
    ) {
      await this.validateAccuracy(options.contentPath, result);
    }

    if (
      options.validationType === "all" ||
      options.validationType === "completeness"
    ) {
      await this.validateCompleteness(options.contentPath, result);
    }

    if (
      options.validationType === "all" ||
      options.validationType === "compliance"
    ) {
      if (isApplicationValidation) {
        await this.validateApplicationStructureCompliance(
          options.contentPath,
          result,
        );
      } else {
        await this.validateDiataxisCompliance(options.contentPath, result);
      }
    }

    // Code validation if requested
    if (options.includeCodeValidation) {
      result.codeValidation = await this.validateCodeExamples(
        options.contentPath,
      );
      // Set code example relevance confidence based on code validation results
      if (result.codeValidation) {
        const successRate =
          result.codeValidation.exampleResults.length > 0
            ? result.codeValidation.exampleResults.filter(
                (e) => e.compilationSuccess,
              ).length / result.codeValidation.exampleResults.length
            : 1;
        result.confidence.breakdown.codeExampleRelevance = Math.round(
          successRate * 100,
        );
      }
    } else {
      // If code validation is skipped, assume reasonable confidence
      result.confidence.breakdown.codeExampleRelevance = 75;
    }

    // Set framework version accuracy based on technology detection confidence
    result.confidence.breakdown.frameworkVersionAccuracy = Math.min(
      90,
      result.confidence.breakdown.technologyDetection + 10,
    );

    // Set architectural assumptions confidence based on file structure and content analysis
    const filesAnalyzed = await this.getMarkdownFiles(options.contentPath);
    const hasStructuredContent = filesAnalyzed.length > 3; // Basic heuristic
    result.confidence.breakdown.architecturalAssumptions = hasStructuredContent
      ? 80
      : 60;

    // Calculate overall confidence and success
    this.calculateOverallMetrics(result);

    // Generate recommendations and next steps
    this.generateRecommendations(result, options);

    if (context?.meta?.progressToken) {
      await context.meta.reportProgress?.({ progress: 100, total: 100 });
    }

    const status = result.success ? "PASSED" : "ISSUES FOUND";
    await context?.info?.(
      `✅ Validation complete! Status: ${status} (${result.confidence.overall}% confidence, ${result.issues.length} issue(s))`,
    );

    return result;
  }

  private initializeConfidenceMetrics(): ConfidenceMetrics {
    return {
      overall: 0,
      breakdown: {
        technologyDetection: 0,
        frameworkVersionAccuracy: 0,
        codeExampleRelevance: 0,
        architecturalAssumptions: 0,
        businessContextAlignment: 0,
      },
      riskFactors: [],
    };
  }

  private async loadProjectContext(analysisId: string): Promise<any> {
    // Try to get analysis from memory system first
    try {
      const memoryRecall = await handleMemoryRecall({
        query: analysisId,
        type: "analysis",
        limit: 1,
      });

      // Handle the memory recall result structure
      if (
        memoryRecall &&
        memoryRecall.memories &&
        memoryRecall.memories.length > 0
      ) {
        const memory = memoryRecall.memories[0];

        // Handle wrapped content structure
        if (
          memory.data &&
          memory.data.content &&
          Array.isArray(memory.data.content)
        ) {
          // Extract the JSON from the first text content
          const firstContent = memory.data.content[0];
          if (
            firstContent &&
            firstContent.type === "text" &&
            firstContent.text
          ) {
            try {
              return JSON.parse(firstContent.text);
            } catch (parseError) {
              console.warn(
                "Failed to parse analysis content from memory:",
                parseError,
              );
            }
          }
        }

        // Try direct content or data access
        if (memory.content) {
          return memory.content;
        }
        if (memory.data) {
          return memory.data;
        }
      }
    } catch (error) {
      console.warn("Failed to retrieve from memory system:", error);
    }

    // Fallback to reading from cached analysis file
    try {
      const analysisPath = path.join(
        ".documcp",
        "analyses",
        `${analysisId}.json`,
      );
      const content = await fs.readFile(analysisPath, "utf-8");
      return JSON.parse(content);
    } catch {
      // Return default context if no analysis found
      return {
        metadata: { projectName: "unknown", primaryLanguage: "JavaScript" },
        technologies: {},
        dependencies: { packages: [] },
      };
    }
  }

  private async validateAccuracy(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const files = await this.getMarkdownFiles(contentPath);

    for (const file of files) {
      const content = await fs.readFile(file, "utf-8");

      // Check for common accuracy issues
      await this.checkTechnicalAccuracy(file, content, result);
      await this.checkFrameworkVersionCompatibility(file, content, result);
      await this.checkCommandAccuracy(file, content, result);
      await this.checkLinkValidity(file, content, result);
    }

    // Update confidence based on findings
    this.updateAccuracyConfidence(result);
  }

  private async checkTechnicalAccuracy(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    // Check for deprecated patterns
    const deprecatedPatterns = [
      {
        pattern: /npm install -g/,
        suggestion: "Use npx instead of global installs",
      },
      { pattern: /var\s+\w+/, suggestion: "Use const or let instead of var" },
      { pattern: /function\(\)/, suggestion: "Consider using arrow functions" },
      { pattern: /http:\/\//, suggestion: "Use HTTPS URLs for security" },
    ];

    for (const { pattern, suggestion } of deprecatedPatterns) {
      if (pattern.test(content)) {
        result.issues.push({
          type: "warning",
          category: "accuracy",
          location: { file: path.basename(filePath) },
          description: `Potentially outdated pattern detected: ${pattern.source}`,
          evidence: [content.match(pattern)?.[0] || ""],
          suggestedFix: suggestion,
          confidence: 80,
        });
      }
    }

    // Check for missing error handling in code examples
    const codeBlocks = this.extractCodeBlocks(content);
    for (const block of codeBlocks) {
      if (block.language === "javascript" || block.language === "typescript") {
        if (
          block.code.includes("await") &&
          !block.code.includes("try") &&
          !block.code.includes("catch")
        ) {
          result.issues.push({
            type: "warning",
            category: "accuracy",
            location: { file: path.basename(filePath) },
            description: "Async code without error handling",
            evidence: [block.code.substring(0, 100)],
            suggestedFix: "Add try-catch blocks for async operations",
            confidence: 90,
          });
        }
      }
    }
  }

  private async checkFrameworkVersionCompatibility(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    if (!this.projectContext) return;

    // Check if mentioned versions align with project dependencies
    const versionPattern = /@(\d+\.\d+\.\d+)/g;
    const matches = content.match(versionPattern);

    if (matches) {
      for (const match of matches) {
        const version = match.replace("@", "");

        result.uncertainties.push({
          area: "version-compatibility",
          severity: "medium",
          description: `Version ${version} mentioned in documentation`,
          potentialImpact: "May not match actual project dependencies",
          clarificationNeeded: "Verify version compatibility with project",
          fallbackStrategy: "Use generic version-agnostic examples",
        });
      }
    }
  }

  private async checkCommandAccuracy(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    const codeBlocks = this.extractCodeBlocks(content);

    for (const block of codeBlocks) {
      if (block.language === "bash" || block.language === "sh") {
        // Check for common command issues
        const commands = block.code
          .split("\n")
          .filter((line) => line.trim() && !line.startsWith("#"));

        for (const command of commands) {
          // Check for potentially dangerous commands
          const dangerousPatterns = [
            /rm -rf \//,
            /sudo rm/,
            /chmod 777/,
            /> \/dev\/null 2>&1/,
          ];

          for (const pattern of dangerousPatterns) {
            if (pattern.test(command)) {
              result.issues.push({
                type: "error",
                category: "accuracy",
                location: { file: path.basename(filePath) },
                description: "Potentially dangerous command in documentation",
                evidence: [command],
                suggestedFix: "Review and provide safer alternative",
                confidence: 95,
              });
            }
          }

          // Check for non-portable commands (Windows vs Unix)
          if (command.includes("\\") && command.includes("/")) {
            result.issues.push({
              type: "warning",
              category: "accuracy",
              location: { file: path.basename(filePath) },
              description: "Mixed path separators in command",
              evidence: [command],
              suggestedFix:
                "Use consistent path separators or provide OS-specific examples",
              confidence: 85,
            });
          }
        }
      }
    }
  }

  private async checkLinkValidity(
    filePath: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    const linkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
    const links: Array<{ text: string; url: string }> = [];
    let match;

    while ((match = linkPattern.exec(content)) !== null) {
      links.push({ text: match[1], url: match[2] });
    }

    for (const link of links) {
      // Check internal links
      if (!link.url.startsWith("http")) {
        const targetPath = path.resolve(path.dirname(filePath), link.url);
        try {
          await fs.access(targetPath);
        } catch {
          result.issues.push({
            type: "error",
            category: "accuracy",
            location: { file: path.basename(filePath) },
            description: `Broken internal link: ${link.url}`,
            evidence: [link.text],
            suggestedFix: "Fix the link path or create the missing file",
            confidence: 100,
          });
        }
      }

      // Flag external links for manual verification
      if (link.url.startsWith("http")) {
        result.uncertainties.push({
          area: "external-links",
          severity: "low",
          description: `External link: ${link.url}`,
          potentialImpact: "Link may become outdated or broken",
          clarificationNeeded: "Verify link is still valid",
          fallbackStrategy: "Archive important external content locally",
        });
      }
    }
  }

  private async validateCompleteness(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const files = await this.getMarkdownFiles(contentPath);
    const structure = await this.analyzeDiataxisStructure(contentPath);

    // Check for missing essential sections
    const requiredSections = [
      "tutorials",
      "how-to",
      "reference",
      "explanation",
    ];
    const missingSections = requiredSections.filter(
      (section) => !structure.sections.includes(section),
    );

    if (missingSections.length > 0) {
      result.issues.push({
        type: "warning",
        category: "completeness",
        location: { file: "documentation structure" },
        description: `Missing Diataxis sections: ${missingSections.join(", ")}`,
        evidence: structure.sections,
        suggestedFix:
          "Add missing Diataxis sections for complete documentation",
        confidence: 100,
      });
    }

    // Check content depth in each section
    for (const section of structure.sections) {
      const sectionFiles = files.filter((f) => f.includes(`/${section}/`));
      if (sectionFiles.length < 2) {
        result.issues.push({
          type: "info",
          category: "completeness",
          location: { file: section },
          description: `Limited content in ${section} section`,
          evidence: [`Only ${sectionFiles.length} files`],
          suggestedFix: "Consider adding more comprehensive coverage",
          confidence: 75,
        });
      }
    }

    // Update completeness confidence
    result.confidence.breakdown.businessContextAlignment = Math.max(
      0,
      100 - missingSections.length * 25,
    );
  }

  private async validateDiataxisCompliance(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const files = await this.getMarkdownFiles(contentPath);

    for (const file of files) {
      const content = await fs.readFile(file, "utf-8");
      const section = this.identifyDiataxisSection(file);

      if (section) {
        await this.checkSectionCompliance(file, content, section, result);
      }
    }
  }

  private async validateApplicationStructureCompliance(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    // Analyze application source code for Diataxis compliance
    await this.validateSourceCodeDocumentation(contentPath, result);
    await this.validateApplicationArchitecture(contentPath, result);
    await this.validateInlineDocumentationPatterns(contentPath, result);
  }

  private async validateSourceCodeDocumentation(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const sourceFiles = await this.getSourceFiles(contentPath);

    for (const file of sourceFiles) {
      const content = await fs.readFile(file, "utf-8");

      // Check for proper JSDoc/TSDoc documentation
      await this.checkInlineDocumentationQuality(file, content, result);

      // Check for README files and their structure
      if (file.endsWith("README.md")) {
        await this.validateReadmeStructure(file, content, result);
      }

      // Check for proper module/class documentation
      await this.checkModuleDocumentation(file, content, result);
    }
  }

  private async validateApplicationArchitecture(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    // Check if the application structure supports different types of documentation
    const hasToolsDir = await this.pathExists(path.join(contentPath, "tools"));
    const hasTypesDir = await this.pathExists(path.join(contentPath, "types"));
    // Check for workflows directory (currently not used but may be useful for future validation)
    // const hasWorkflowsDir = await this.pathExists(path.join(contentPath, 'workflows'));

    if (!hasToolsDir) {
      result.issues.push({
        type: "warning",
        category: "compliance",
        location: { file: "application structure" },
        description:
          "No dedicated tools directory found - may impact reference documentation organization",
        evidence: ["Missing /tools directory"],
        suggestedFix:
          "Organize tools into dedicated directory for better reference documentation",
        confidence: 80,
      });
    }

    if (!hasTypesDir) {
      result.issues.push({
        type: "info",
        category: "compliance",
        location: { file: "application structure" },
        description:
          "No types directory found - may impact API reference documentation",
        evidence: ["Missing /types directory"],
        suggestedFix: "Consider organizing types for better API documentation",
        confidence: 70,
      });
    }
  }

  private async validateInlineDocumentationPatterns(
    contentPath: string,
    result: ValidationResult,
  ): Promise<void> {
    const sourceFiles = await this.getSourceFiles(contentPath);

    for (const file of sourceFiles) {
      const content = await fs.readFile(file, "utf-8");

      // Check for proper function documentation that could support tutorials
      const functions = this.extractFunctions(content);
      for (const func of functions) {
        if (func.isExported && !func.hasDocumentation) {
          result.issues.push({
            type: "warning",
            category: "compliance",
            location: { file: path.basename(file), line: func.line },
            description: `Exported function '${func.name}' lacks documentation`,
            evidence: [func.signature],
            suggestedFix:
              "Add JSDoc/TSDoc documentation to support tutorial and reference content",
            confidence: 85,
          });
        }
      }

      // Check for proper error handling documentation
      const errorPatterns = content.match(/throw new \w*Error/g);
      if (errorPatterns && errorPatterns.length > 0) {
        const hasErrorDocs =
          content.includes("@throws") || content.includes("@error");
        if (!hasErrorDocs) {
          result.issues.push({
            type: "info",
            category: "compliance",
            location: { file: path.basename(file) },
            description:
              "Error throwing code found without error documentation",
            evidence: errorPatterns,
            suggestedFix:
              "Document error conditions to support troubleshooting guides",
            confidence: 75,
          });
        }
      }
    }
  }

  private identifyDiataxisSection(filePath: string): string | null {
    const sections = ["tutorials", "how-to", "reference", "explanation"];

    for (const section of sections) {
      if (filePath.includes(`/${section}/`)) {
        return section;
      }
    }

    return null;
  }

  private async checkSectionCompliance(
    filePath: string,
    content: string,
    section: string,
    result: ValidationResult,
  ): Promise<void> {
    const complianceRules = this.getDiataxisComplianceRules(section);

    for (const rule of complianceRules) {
      if (!rule.check(content)) {
        result.issues.push({
          type: "warning",
          category: "compliance",
          location: { file: path.basename(filePath), section },
          description: rule.message,
          evidence: [rule.evidence?.(content) || ""],
          suggestedFix: rule.fix,
          confidence: rule.confidence,
        });
      }
    }
  }

  private getDiataxisComplianceRules(section: string) {
    const rules: any = {
      tutorials: [
        {
          check: (content: string) =>
            content.includes("## Prerequisites") ||
            content.includes("## Requirements"),
          message: "Tutorial should include prerequisites section",
          fix: "Add a prerequisites or requirements section",
          confidence: 90,
        },
        {
          check: (content: string) => /step|Step|STEP/.test(content),
          message: "Tutorial should be organized in clear steps",
          fix: "Structure content with numbered steps or clear progression",
          confidence: 85,
        },
        {
          check: (content: string) => content.includes("```"),
          message: "Tutorial should include practical code examples",
          fix: "Add code blocks with working examples",
          confidence: 80,
        },
      ],
      "how-to": [
        {
          check: (content: string) => /how to|How to|HOW TO/.test(content),
          message: "How-to guide should focus on specific tasks",
          fix: "Frame content around achieving specific goals",
          confidence: 75,
        },
        {
          check: (content: string) => content.length > 500,
          message: "How-to guide should provide detailed guidance",
          fix: "Expand with more detailed instructions",
          confidence: 70,
        },
      ],
      reference: [
        {
          check: (content: string) => /##|###/.test(content),
          message: "Reference should be well-structured with clear sections",
          fix: "Add proper headings and organization",
          confidence: 95,
        },
        {
          check: (content: string) => /\|.*\|/.test(content),
          message: "Reference should include tables for structured information",
          fix: "Consider using tables for parameters, options, etc.",
          confidence: 60,
        },
      ],
      explanation: [
        {
          check: (content: string) =>
            content.includes("why") || content.includes("Why"),
          message: 'Explanation should address the "why" behind concepts',
          fix: "Include rationale and context for decisions/concepts",
          confidence: 80,
        },
        {
          check: (content: string) => content.length > 800,
          message: "Explanation should provide in-depth coverage",
          fix: "Expand with more comprehensive explanation",
          confidence: 70,
        },
      ],
    };

    return rules[section] || [];
  }

  private async validateCodeExamples(
    contentPath: string,
  ): Promise<CodeValidationResult> {
    const files = await this.getMarkdownFiles(contentPath);
    const allExamples: ExampleValidation[] = [];

    for (const file of files) {
      const content = await fs.readFile(file, "utf-8");
      const codeBlocks = this.extractCodeBlocks(content);

      for (const block of codeBlocks) {
        if (this.isValidatableLanguage(block.language)) {
          const validation = await this.validateCodeBlock(block, file);
          allExamples.push(validation);
        }
      }
    }

    return {
      overallSuccess: allExamples.every((e) => e.compilationSuccess),
      exampleResults: allExamples,
      confidence: this.calculateCodeValidationConfidence(allExamples),
    };
  }

  private extractCodeBlocks(
    content: string,
  ): Array<{ language: string; code: string; id: string }> {
    const codeBlockPattern = /```(\w+)?\n([\s\S]*?)```/g;
    const blocks: Array<{ language: string; code: string; id: string }> = [];
    let match;
    let index = 0;

    while ((match = codeBlockPattern.exec(content)) !== null) {
      blocks.push({
        language: match[1] || "text",
        code: match[2].trim(),
        id: `block-${index++}`,
      });
    }

    return blocks;
  }

  private isValidatableLanguage(language: string): boolean {
    const validatable = [
      "javascript",
      "typescript",
      "js",
      "ts",
      "json",
      "bash",
      "sh",
    ];
    return validatable.includes(language.toLowerCase());
  }

  private async validateCodeBlock(
    block: { language: string; code: string; id: string },
    filePath: string,
  ): Promise<ExampleValidation> {
    const validation: ExampleValidation = {
      example: block.id,
      compilationSuccess: false,
      executionSuccess: false,
      issues: [],
      confidence: 0,
    };

    try {
      if (block.language === "typescript" || block.language === "ts") {
        await this.validateTypeScriptCode(block.code, validation);
      } else if (block.language === "javascript" || block.language === "js") {
        await this.validateJavaScriptCode(block.code, validation);
      } else if (block.language === "json") {
        await this.validateJSONCode(block.code, validation);
      } else if (block.language === "bash" || block.language === "sh") {
        await this.validateBashCode(block.code, validation);
      }
    } catch (error: any) {
      validation.issues.push({
        type: "error",
        category: "accuracy",
        location: { file: path.basename(filePath) },
        description: `Code validation failed: ${error.message}`,
        evidence: [block.code.substring(0, 100)],
        suggestedFix: "Review and fix syntax errors",
        confidence: 95,
      });
    }

    return validation;
  }

  private async validateTypeScriptCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    // Ensure temp directory exists
    await fs.mkdir(this.tempDir, { recursive: true });

    const tempFile = path.join(this.tempDir, `temp-${Date.now()}.ts`);

    try {
      // Write code to temporary file
      await fs.writeFile(tempFile, code, "utf-8");

      // Try to compile with TypeScript
      const { stderr } = await execAsync(
        `npx tsc --noEmit --skipLibCheck ${tempFile}`,
      );

      if (stderr && stderr.includes("error")) {
        validation.issues.push({
          type: "error",
          category: "accuracy",
          location: { file: "code-example" },
          description: "TypeScript compilation error",
          evidence: [stderr],
          suggestedFix: "Fix TypeScript syntax and type errors",
          confidence: 90,
        });
      } else {
        validation.compilationSuccess = true;
        validation.confidence = 85;
      }
    } catch (error: any) {
      if (error.stderr && error.stderr.includes("error")) {
        validation.issues.push({
          type: "error",
          category: "accuracy",
          location: { file: "code-example" },
          description: "TypeScript compilation failed",
          evidence: [error.stderr],
          suggestedFix: "Fix compilation errors",
          confidence: 95,
        });
      }
    } finally {
      // Clean up temp file
      try {
        await fs.unlink(tempFile);
      } catch {
        // Ignore cleanup errors
      }
    }
  }

  private async validateJavaScriptCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    try {
      // Basic syntax check using Node.js
      new Function(code);
      validation.compilationSuccess = true;
      validation.confidence = 75;
    } catch (error: any) {
      validation.issues.push({
        type: "error",
        category: "accuracy",
        location: { file: "code-example" },
        description: `JavaScript syntax error: ${error.message}`,
        evidence: [code.substring(0, 100)],
        suggestedFix: "Fix JavaScript syntax errors",
        confidence: 90,
      });
    }
  }

  private async validateJSONCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    try {
      JSON.parse(code);
      validation.compilationSuccess = true;
      validation.confidence = 95;
    } catch (error: any) {
      validation.issues.push({
        type: "error",
        category: "accuracy",
        location: { file: "code-example" },
        description: `Invalid JSON: ${error.message}`,
        evidence: [code.substring(0, 100)],
        suggestedFix: "Fix JSON syntax errors",
        confidence: 100,
      });
    }
  }

  private async validateBashCode(
    code: string,
    validation: ExampleValidation,
  ): Promise<void> {
    // Basic bash syntax validation
    const lines = code
      .split("\n")
      .filter((line) => line.trim() && !line.startsWith("#"));

    for (const line of lines) {
      // Check for basic syntax issues
      if (line.includes("&&") && line.includes("||")) {
        validation.issues.push({
          type: "warning",
          category: "accuracy",
          location: { file: "code-example" },
          description: "Complex command chaining may be confusing",
          evidence: [line],
          suggestedFix:
            "Consider breaking into separate commands or adding explanation",
          confidence: 60,
        });
      }

      // Check for unquoted variables in dangerous contexts
      if (line.includes("rm") && /\$\w+/.test(line) && !/'.*\$.*'/.test(line)) {
        validation.issues.push({
          type: "warning",
          category: "accuracy",
          location: { file: "code-example" },
          description: "Unquoted variable in potentially dangerous command",
          evidence: [line],
          suggestedFix: "Quote variables to prevent word splitting",
          confidence: 80,
        });
      }
    }

    validation.compilationSuccess =
      validation.issues.filter((i) => i.type === "error").length === 0;
    validation.confidence = validation.compilationSuccess ? 70 : 20;
  }

  private calculateCodeValidationConfidence(
    examples: ExampleValidation[],
  ): number {
    if (examples.length === 0) return 0;

    const totalConfidence = examples.reduce(
      (sum, ex) => sum + ex.confidence,
      0,
    );
    return Math.round(totalConfidence / examples.length);
  }

  public async getMarkdownFiles(
    contentPath: string,
    maxDepth: number = 5,
  ): Promise<string[]> {
    const files: string[] = [];
    const excludedDirs = new Set([
      "node_modules",
      ".git",
      "dist",
      "build",
      ".next",
      ".nuxt",
      "coverage",
      ".tmp",
      "tmp",
      ".cache",
      ".vscode",
      ".idea",
      "logs",
      ".logs",
      ".npm",
      ".yarn",
    ]);

    const scan = async (
      dir: string,
      currentDepth: number = 0,
    ): Promise<void> => {
      if (currentDepth > maxDepth) return;

      try {
        const entries = await fs.readdir(dir, { withFileTypes: true });

        for (const entry of entries) {
          const fullPath = path.join(dir, entry.name);

          if (entry.isDirectory()) {
            // Skip excluded directories
            if (excludedDirs.has(entry.name) || entry.name.startsWith(".")) {
              continue;
            }

            // Prevent symlink loops
            try {
              const stats = await fs.lstat(fullPath);
              if (stats.isSymbolicLink()) {
                continue;
              }
            } catch {
              continue;
            }

            await scan(fullPath, currentDepth + 1);
          } else if (entry.name.endsWith(".md")) {
            files.push(fullPath);

            // Limit total files to prevent memory issues
            if (files.length > 500) {
              console.warn("Markdown file limit reached (500), stopping scan");
              return;
            }
          }
        }
      } catch (error) {
        // Skip directories that can't be read
        console.warn(`Warning: Could not read directory ${dir}:`, error);
      }
    };

    try {
      await scan(contentPath);
    } catch (error) {
      console.warn("Error scanning directory:", error);
    }

    return files;
  }

  private async getSourceFiles(
    contentPath: string,
    maxDepth: number = 5,
  ): Promise<string[]> {
    const files: string[] = [];
    const excludedDirs = new Set([
      "node_modules",
      ".git",
      "dist",
      "build",
      ".next",
      ".nuxt",
      "coverage",
      ".tmp",
      "tmp",
      ".cache",
      ".vscode",
      ".idea",
      "logs",
      ".logs",
      ".npm",
      ".yarn",
    ]);

    const scan = async (
      dir: string,
      currentDepth: number = 0,
    ): Promise<void> => {
      if (currentDepth > maxDepth) return;

      try {
        const entries = await fs.readdir(dir, { withFileTypes: true });

        for (const entry of entries) {
          const fullPath = path.join(dir, entry.name);

          if (entry.isDirectory()) {
            // Skip excluded directories
            if (excludedDirs.has(entry.name) || entry.name.startsWith(".")) {
              continue;
            }

            // Prevent symlink loops
            try {
              const stats = await fs.lstat(fullPath);
              if (stats.isSymbolicLink()) {
                continue;
              }
            } catch {
              continue;
            }

            await scan(fullPath, currentDepth + 1);
          } else if (
            entry.name.endsWith(".ts") ||
            entry.name.endsWith(".js") ||
            entry.name.endsWith(".md")
          ) {
            files.push(fullPath);

            // Limit total files to prevent memory issues
            if (files.length > 1000) {
              console.warn("File limit reached (1000), stopping scan");
              return;
            }
          }
        }
      } catch (error) {
        // Skip directories that can't be read
        console.warn(`Warning: Could not read directory ${dir}:`, error);
      }
    };

    try {
      await scan(contentPath);
    } catch (error) {
      console.warn("Error scanning directory:", error);
    }

    return files;
  }

  private async pathExists(filePath: string): Promise<boolean> {
    try {
      await fs.access(filePath);
      return true;
    } catch {
      return false;
    }
  }

  private extractFunctions(content: string): Array<{
    name: string;
    line: number;
    signature: string;
    isExported: boolean;
    hasDocumentation: boolean;
  }> {
    const functions: Array<{
      name: string;
      line: number;
      signature: string;
      isExported: boolean;
      hasDocumentation: boolean;
    }> = [];
    const lines = content.split("\n");

    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];

      // Match function declarations and exports
      const functionMatch = line.match(
        /^(export\s+)?(async\s+)?function\s+(\w+)/,
      );
      const arrowMatch = line.match(
        /^(export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(async\s+)?\(/,
      );

      if (functionMatch) {
        const name = functionMatch[3];
        const isExported = !!functionMatch[1];
        const hasDocumentation = this.checkForDocumentation(lines, i);

        functions.push({
          name,
          line: i + 1,
          signature: line.trim(),
          isExported,
          hasDocumentation,
        });
      } else if (arrowMatch) {
        const name = arrowMatch[2];
        const isExported = !!arrowMatch[1];
        const hasDocumentation = this.checkForDocumentation(lines, i);

        functions.push({
          name,
          line: i + 1,
          signature: line.trim(),
          isExported,
          hasDocumentation,
        });
      }
    }

    return functions;
  }

  private async checkInlineDocumentationQuality(
    _file: string,
    _content: string,
    _result: ValidationResult,
  ): Promise<void> {
    // Implementation for checking JSDoc/TSDoc quality
    // This could check for proper parameter documentation, return types, etc.
  }

  private async validateReadmeStructure(
    _file: string,
    content: string,
    result: ValidationResult,
  ): Promise<void> {
    // Check if README follows good structure
    const hasTitle = /^#\s+/.test(content);
    const hasDescription =
      content.includes("## Description") || content.includes("## Overview");
    const hasInstallation =
      content.includes("## Installation") || content.includes("## Setup");
    const hasUsage =
      content.includes("## Usage") || content.includes("## Getting Started");

    if (!hasTitle) {
      result.issues.push({
        type: "warning",
        category: "compliance",
        location: { file: "README.md" },
        description: "README missing clear title",
        evidence: ["No H1 heading found"],
        suggestedFix: "Add clear title with # heading",
        confidence: 90,
      });
    }

    if (!hasDescription && !hasInstallation && !hasUsage) {
      result.issues.push({
        type: "warning",
        category: "compliance",
        location: { file: "README.md" },
        description:
          "README lacks essential sections (description, installation, usage)",
        evidence: ["Missing standard README sections"],
        suggestedFix:
          "Add sections for description, installation, and usage following Diataxis principles",
        confidence: 85,
      });
    }
  }

  private async checkModuleDocumentation(
    _file: string,
    _content: string,
    _result: ValidationResult,
  ): Promise<void> {
    // Implementation for checking module-level documentation
    // This could check for file-level JSDoc, proper exports documentation, etc.
  }

  private checkForDocumentation(
    lines: string[],
    functionLineIndex: number,
  ): boolean {
    // Look backwards from the function line to find documentation
    let checkIndex = functionLineIndex - 1;

    // Skip empty lines
    while (checkIndex >= 0 && lines[checkIndex].trim() === "") {
      checkIndex--;
    }

    // Check if we found the end of a JSDoc comment
    if (checkIndex >= 0 && lines[checkIndex].trim() === "*/") {
      // Look backwards to find the start of the JSDoc block
      let jsDocStart = checkIndex;
      while (jsDocStart >= 0) {
        const line = lines[jsDocStart].trim();
        if (line.startsWith("/**")) {
          return true; // Found complete JSDoc block
        }
        if (!line.startsWith("*") && line !== "*/") {
          break; // Not part of JSDoc block
        }
        jsDocStart--;
      }
    }

    // Also check for single-line JSDoc comments
    if (
      checkIndex >= 0 &&
      lines[checkIndex].trim().startsWith("/**") &&
      lines[checkIndex].includes("*/")
    ) {
      return true;
    }

    return false;
  }

  private async shouldAnalyzeApplicationCode(
    contentPath: string,
  ): Promise<boolean> {
    // Check if the path contains application source code vs documentation
    const hasSrcDir = await this.pathExists(path.join(contentPath, "src"));
    const hasPackageJson = await this.pathExists(
      path.join(contentPath, "package.json"),
    );
    const hasTypescriptFiles = (await this.getSourceFiles(contentPath)).some(
      (file) => file.endsWith(".ts"),
    );

    // If path ends with 'src' or is a project root with src/, analyze as application code
    if (
      contentPath.endsWith("/src") ||
      contentPath.endsWith("\\src") ||
      (hasSrcDir && hasPackageJson)
    ) {
      return true;
    }

    // If path contains TypeScript/JavaScript files and package.json, treat as application code
    if (hasTypescriptFiles && hasPackageJson) {
      return true;
    }

    // If path is specifically a documentation directory, analyze as documentation
    if (contentPath.includes("/docs") || contentPath.includes("\\docs")) {
      return false;
    }

    return false;
  }

  private async analyzeDiataxisStructure(
    contentPath: string,
  ): Promise<{ sections: string[] }> {
    const sections: string[] = [];

    try {
      const entries = await fs.readdir(contentPath, { withFileTypes: true });

      for (const entry of entries) {
        if (entry.isDirectory()) {
          const dirName = entry.name;
          if (
            ["tutorials", "how-to", "reference", "explanation"].includes(
              dirName,
            )
          ) {
            sections.push(dirName);
          }
        }
      }
    } catch {
      // Directory doesn't exist
    }

    return { sections };
  }

  private updateAccuracyConfidence(result: ValidationResult): void {
    const errorCount = result.issues.filter((i) => i.type === "error").length;
    const warningCount = result.issues.filter(
      (i) => i.type === "warning",
    ).length;

    // Base confidence starts high and decreases with issues
    let confidence = 95;
    confidence -= errorCount * 20;
    confidence -= warningCount * 5;
    confidence = Math.max(0, confidence);

    result.confidence.breakdown.technologyDetection = confidence;
  }

  private calculateOverallMetrics(result: ValidationResult): void {
    const breakdown = result.confidence.breakdown;
    const values = Object.values(breakdown).filter((v) => v > 0);

    if (values.length > 0) {
      result.confidence.overall = Math.round(
        values.reduce((a, b) => a + b, 0) / values.length,
      );
    }

    // Determine overall success
    const criticalIssues = result.issues.filter(
      (i) => i.type === "error",
    ).length;
    result.success = criticalIssues === 0;

    // Add risk factors based on issues
    if (criticalIssues > 0) {
      result.confidence.riskFactors.push({
        type: "high",
        category: "accuracy",
        description: `${criticalIssues} critical accuracy issues found`,
        impact: "Users may encounter broken examples or incorrect information",
        mitigation: "Fix all critical issues before publication",
      });
    }

    const uncertaintyCount = result.uncertainties.length;
    if (uncertaintyCount > 5) {
      result.confidence.riskFactors.push({
        type: "medium",
        category: "completeness",
        description: `${uncertaintyCount} areas requiring clarification`,
        impact: "Documentation may lack specificity for user context",
        mitigation: "Address high-priority uncertainties with user input",
      });
    }
  }

  private generateRecommendations(
    result: ValidationResult,
    _options: ValidationOptions,
  ): void {
    const recommendations: string[] = [];
    const nextSteps: string[] = [];

    // Generate recommendations based on issues found
    const errorCount = result.issues.filter((i) => i.type === "error").length;
    if (errorCount > 0) {
      recommendations.push(
        `Fix ${errorCount} critical accuracy issues before publication`,
      );
      nextSteps.push("Review and resolve all error-level validation issues");
    }

    const warningCount = result.issues.filter(
      (i) => i.type === "warning",
    ).length;
    if (warningCount > 0) {
      recommendations.push(
        `Address ${warningCount} potential accuracy concerns`,
      );
      nextSteps.push(
        "Review warning-level issues and apply fixes where appropriate",
      );
    }

    const uncertaintyCount = result.uncertainties.filter(
      (u) => u.severity === "high" || u.severity === "critical",
    ).length;
    if (uncertaintyCount > 0) {
      recommendations.push(
        `Clarify ${uncertaintyCount} high-uncertainty areas`,
      );
      nextSteps.push("Gather user input on areas flagged for clarification");
    }

    // Code validation recommendations
    if (result.codeValidation && !result.codeValidation.overallSuccess) {
      recommendations.push(
        "Fix code examples that fail compilation or execution tests",
      );
      nextSteps.push(
        "Test all code examples in appropriate development environment",
      );
    }

    // Completeness recommendations
    const missingCompliance = result.issues.filter(
      (i) => i.category === "compliance",
    ).length;
    if (missingCompliance > 0) {
      recommendations.push(
        "Improve Diataxis framework compliance for better user experience",
      );
      nextSteps.push(
        "Restructure content to better align with Diataxis principles",
      );
    }

    // General recommendations based on confidence level
    if (result.confidence.overall < 70) {
      recommendations.push(
        "Overall confidence is below recommended threshold - consider comprehensive review",
      );
      nextSteps.push(
        "Conduct manual review of generated content before publication",
      );
    }

    if (recommendations.length === 0) {
      recommendations.push("Content validation passed - ready for publication");
      nextSteps.push("Deploy documentation and monitor for user feedback");
    }

    result.recommendations = recommendations;
    result.nextSteps = nextSteps;
  }
}

export const validateDiataxisContent: Tool = {
  name: "validate_diataxis_content",
  description:
    "Validate the accuracy, completeness, and compliance of generated Diataxis documentation",
  inputSchema: {
    type: "object",
    properties: {
      contentPath: {
        type: "string",
        description: "Path to the documentation directory to validate",
      },
      analysisId: {
        type: "string",
        description:
          "Optional repository analysis ID for context-aware validation",
      },
      validationType: {
        type: "string",
        enum: ["accuracy", "completeness", "compliance", "all"],
        default: "all",
        description: "Type of validation to perform",
      },
      includeCodeValidation: {
        type: "boolean",
        default: true,
        description: "Whether to validate code examples for correctness",
      },
      confidence: {
        type: "string",
        enum: ["strict", "moderate", "permissive"],
        default: "moderate",
        description:
          "Validation confidence level - stricter levels catch more issues",
      },
    },
    required: ["contentPath"],
  },
};

/**
 * Validates Diataxis-compliant documentation content for accuracy, completeness, and compliance.
 *
 * Performs comprehensive validation of documentation content including accuracy verification,
 * completeness assessment, compliance checking, and code example validation. Uses advanced
 * confidence scoring and risk assessment to provide detailed validation results with
 * actionable recommendations.
 *
 * @param args - The validation parameters
 * @param args.contentPath - Path to the documentation content directory
 * @param args.analysisId - Optional repository analysis ID for context-aware validation
 * @param args.validationType - Type of validation to perform: "accuracy", "completeness", "compliance", or "all"
 * @param args.includeCodeValidation - Whether to validate code examples and syntax
 * @param args.confidence - Validation confidence level: "strict", "moderate", or "permissive"
 *
 * @returns Promise resolving to comprehensive validation results
 * @returns success - Whether validation passed overall
 * @returns confidence - Confidence metrics and risk assessment
 * @returns issues - Array of validation issues found
 * @returns uncertainties - Areas requiring clarification
 * @returns codeValidation - Code example validation results
 * @returns recommendations - Suggested improvements
 * @returns nextSteps - Recommended next actions
 *
 * @throws {Error} When content path is inaccessible
 * @throws {Error} When validation processing fails
 *
 * @example
 * ```typescript
 * // Comprehensive validation
 * const result = await handleValidateDiataxisContent({
 *   contentPath: "./docs",
 *   validationType: "all",
 *   includeCodeValidation: true,
 *   confidence: "moderate"
 * });
 *
 * console.log(`Validation success: ${result.success}`);
 * console.log(`Overall confidence: ${result.confidence.overall}%`);
 * console.log(`Issues found: ${result.issues.length}`);
 *
 * // Strict accuracy validation
 * const accuracy = await handleValidateDiataxisContent({
 *   contentPath: "./docs",
 *   validationType: "accuracy",
 *   confidence: "strict"
 * });
 * ```
 *
 * @since 1.0.0
 */
export async function handleValidateDiataxisContent(
  args: any,
  context?: any,
): Promise<ValidationResult> {
  await context?.info?.("🔍 Starting Diataxis content validation...");

  const validator = new ContentAccuracyValidator();

  // Add timeout protection to prevent infinite hangs
  const timeoutMs = 120000; // 2 minutes
  let timeoutHandle: NodeJS.Timeout;
  const timeoutPromise = new Promise<ValidationResult>((_, reject) => {
    timeoutHandle = setTimeout(() => {
      reject(
        new Error(
          `Validation timed out after ${
            timeoutMs / 1000
          } seconds. This may be due to a large directory structure. Try validating a smaller subset or specific directory.`,
        ),
      );
    }, timeoutMs);
  });

  const validationPromise = validator.validateContent(args, context);

  try {
    const result = await Promise.race([validationPromise, timeoutPromise]);
    clearTimeout(timeoutHandle!);
    return result;
  } catch (error: any) {
    clearTimeout(timeoutHandle!);
    // Return a partial result with error information
    return {
      success: false,
      confidence: {
        overall: 0,
        breakdown: {
          technologyDetection: 0,
          frameworkVersionAccuracy: 0,
          codeExampleRelevance: 0,
          architecturalAssumptions: 0,
          businessContextAlignment: 0,
        },
        riskFactors: [
          {
            type: "high",
            category: "validation",
            description: "Validation process failed or timed out",
            impact: "Unable to complete content validation",
            mitigation:
              "Try validating a smaller directory or specific subset of files",
          },
        ],
      },
      issues: [],
      uncertainties: [],
      recommendations: [
        "Validation failed or timed out",
        "Consider validating smaller directory subsets",
        "Check for very large files or deep directory structures",
        `Error: ${error.message}`,
      ],
      nextSteps: [
        "Verify the content path is correct and accessible",
        "Try validating specific subdirectories instead of the entire project",
        "Check for circular symlinks or very deep directory structures",
      ],
    };
  }
}

interface GeneralValidationResult {
  success: boolean;
  linksChecked: number;
  brokenLinks: string[];
  codeBlocksValidated: number;
  codeErrors: string[];
  recommendations: string[];
  summary: string;
}

export async function validateGeneralContent(
  args: any,
): Promise<GeneralValidationResult> {
  const {
    contentPath,
    validationType = "all",
    includeCodeValidation = true,
    followExternalLinks = false,
  } = args;

  const result: GeneralValidationResult = {
    success: true,
    linksChecked: 0,
    brokenLinks: [],
    codeBlocksValidated: 0,
    codeErrors: [],
    recommendations: [],
    summary: "",
  };

  try {
    // Get all markdown files
    const validator = new ContentAccuracyValidator();
    const files = await validator.getMarkdownFiles(contentPath);

    // Check links if requested
    if (validationType === "all" || validationType === "links") {
      for (const file of files) {
        const content = await fs.readFile(file, "utf-8");
        const links = extractLinksFromMarkdown(content);

        for (const link of links) {
          result.linksChecked++;

          // Skip external links unless explicitly requested
          if (link.startsWith("http") && !followExternalLinks) continue;

          // Check internal links
          if (!link.startsWith("http")) {
            const fullPath = path.resolve(path.dirname(file), link);
            try {
              await fs.access(fullPath);
            } catch {
              result.brokenLinks.push(`${path.basename(file)}: ${link}`);
              result.success = false;
            }
          }
        }
      }
    }

    // Validate code blocks if requested
    if (
      includeCodeValidation &&
      (validationType === "all" || validationType === "code")
    ) {
      for (const file of files) {
        const content = await fs.readFile(file, "utf-8");
        const codeBlocks = extractCodeBlocks(content);

        for (const block of codeBlocks) {
          result.codeBlocksValidated++;

          // Basic syntax validation
          if (block.language && block.code.trim()) {
            if (block.language === "javascript" || block.language === "js") {
              try {
                // Basic JS syntax check - look for common issues
                if (
                  block.code.includes("console.log") &&
                  !block.code.includes(";")
                ) {
                  result.codeErrors.push(
                    `${path.basename(file)}: Missing semicolon in JS code`,
                  );
                }
              } catch (error) {
                result.codeErrors.push(
                  `${path.basename(file)}: JS syntax error - ${error}`,
                );
                result.success = false;
              }
            }
          }
        }
      }
    }

    // Generate recommendations
    if (result.brokenLinks.length > 0) {
      result.recommendations.push(
        `Fix ${result.brokenLinks.length} broken internal links`,
      );
      result.recommendations.push(
        "Run documentation build to catch additional link issues",
      );
    }

    if (result.codeErrors.length > 0) {
      result.recommendations.push(
        `Review and fix ${result.codeErrors.length} code syntax issues`,
      );
    }

    if (result.success) {
      result.recommendations.push(
        "Content validation passed - no critical issues found",
      );
    }

    // Create summary
    result.summary = `Validated ${files.length} files, ${
      result.linksChecked
    } links, ${result.codeBlocksValidated} code blocks. ${
      result.success
        ? "PASSED"
        : `ISSUES FOUND: ${
            result.brokenLinks.length + result.codeErrors.length
          }`
    }`;

    return result;
  } catch (error) {
    result.success = false;
    result.recommendations.push(`Validation failed: ${error}`);
    result.summary = `Validation error: ${error}`;
    return result;
  }
}

// Helper function to extract links from markdown
function extractLinksFromMarkdown(content: string): string[] {
  const linkRegex = /\[([^\]]*)\]\(([^)]+)\)/g;
  const links: string[] = [];
  let match;

  while ((match = linkRegex.exec(content)) !== null) {
    links.push(match[2]); // The URL part
  }

  return links;
}

// Helper function to extract code blocks from markdown
function extractCodeBlocks(
  content: string,
): { language: string; code: string }[] {
  const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
  const blocks: { language: string; code: string }[] = [];
  let match;

  while ((match = codeBlockRegex.exec(content)) !== null) {
    blocks.push({
      language: match[1] || "text",
      code: match[2],
    });
  }

  return blocks;
}

```

--------------------------------------------------------------------------------
/docs/api/assets/main.js:
--------------------------------------------------------------------------------

```javascript
"use strict";
window.translations = {
  copy: "Copy",
  copied: "Copied!",
  normally_hidden:
    "This member is normally hidden due to your filter settings.",
  hierarchy_expand: "Expand",
  hierarchy_collapse: "Collapse",
  folder: "Folder",
  search_index_not_available: "The search index is not available",
  search_no_results_found_for_0: "No results found for {0}",
  kind_1: "Project",
  kind_2: "Module",
  kind_4: "Namespace",
  kind_8: "Enumeration",
  kind_16: "Enumeration Member",
  kind_32: "Variable",
  kind_64: "Function",
  kind_128: "Class",
  kind_256: "Interface",
  kind_512: "Constructor",
  kind_1024: "Property",
  kind_2048: "Method",
  kind_4096: "Call Signature",
  kind_8192: "Index Signature",
  kind_16384: "Constructor Signature",
  kind_32768: "Parameter",
  kind_65536: "Type Literal",
  kind_131072: "Type Parameter",
  kind_262144: "Accessor",
  kind_524288: "Get Signature",
  kind_1048576: "Set Signature",
  kind_2097152: "Type Alias",
  kind_4194304: "Reference",
  kind_8388608: "Document",
};
("use strict");
(() => {
  var Ke = Object.create;
  var he = Object.defineProperty;
  var Ge = Object.getOwnPropertyDescriptor;
  var Ze = Object.getOwnPropertyNames;
  var Xe = Object.getPrototypeOf,
    Ye = Object.prototype.hasOwnProperty;
  var et = (t, e) => () => (
    e || t((e = { exports: {} }).exports, e), e.exports
  );
  var tt = (t, e, n, r) => {
    if ((e && typeof e == "object") || typeof e == "function")
      for (let i of Ze(e))
        !Ye.call(t, i) &&
          i !== n &&
          he(t, i, {
            get: () => e[i],
            enumerable: !(r = Ge(e, i)) || r.enumerable,
          });
    return t;
  };
  var nt = (t, e, n) => (
    (n = t != null ? Ke(Xe(t)) : {}),
    tt(
      e || !t || !t.__esModule
        ? he(n, "default", { value: t, enumerable: !0 })
        : n,
      t,
    )
  );
  var ye = et((me, ge) => {
    (function () {
      var t = function (e) {
        var n = new t.Builder();
        return (
          n.pipeline.add(t.trimmer, t.stopWordFilter, t.stemmer),
          n.searchPipeline.add(t.stemmer),
          e.call(n, n),
          n.build()
        );
      };
      t.version = "2.3.9";
      (t.utils = {}),
        (t.utils.warn = (function (e) {
          return function (n) {
            e.console && console.warn && console.warn(n);
          };
        })(this)),
        (t.utils.asString = function (e) {
          return e == null ? "" : e.toString();
        }),
        (t.utils.clone = function (e) {
          if (e == null) return e;
          for (
            var n = Object.create(null), r = Object.keys(e), i = 0;
            i < r.length;
            i++
          ) {
            var s = r[i],
              o = e[s];
            if (Array.isArray(o)) {
              n[s] = o.slice();
              continue;
            }
            if (
              typeof o == "string" ||
              typeof o == "number" ||
              typeof o == "boolean"
            ) {
              n[s] = o;
              continue;
            }
            throw new TypeError(
              "clone is not deep and does not support nested objects",
            );
          }
          return n;
        }),
        (t.FieldRef = function (e, n, r) {
          (this.docRef = e), (this.fieldName = n), (this._stringValue = r);
        }),
        (t.FieldRef.joiner = "/"),
        (t.FieldRef.fromString = function (e) {
          var n = e.indexOf(t.FieldRef.joiner);
          if (n === -1) throw "malformed field ref string";
          var r = e.slice(0, n),
            i = e.slice(n + 1);
          return new t.FieldRef(i, r, e);
        }),
        (t.FieldRef.prototype.toString = function () {
          return (
            this._stringValue == null &&
              (this._stringValue =
                this.fieldName + t.FieldRef.joiner + this.docRef),
            this._stringValue
          );
        });
      (t.Set = function (e) {
        if (((this.elements = Object.create(null)), e)) {
          this.length = e.length;
          for (var n = 0; n < this.length; n++) this.elements[e[n]] = !0;
        } else this.length = 0;
      }),
        (t.Set.complete = {
          intersect: function (e) {
            return e;
          },
          union: function () {
            return this;
          },
          contains: function () {
            return !0;
          },
        }),
        (t.Set.empty = {
          intersect: function () {
            return this;
          },
          union: function (e) {
            return e;
          },
          contains: function () {
            return !1;
          },
        }),
        (t.Set.prototype.contains = function (e) {
          return !!this.elements[e];
        }),
        (t.Set.prototype.intersect = function (e) {
          var n,
            r,
            i,
            s = [];
          if (e === t.Set.complete) return this;
          if (e === t.Set.empty) return e;
          this.length < e.length
            ? ((n = this), (r = e))
            : ((n = e), (r = this)),
            (i = Object.keys(n.elements));
          for (var o = 0; o < i.length; o++) {
            var a = i[o];
            a in r.elements && s.push(a);
          }
          return new t.Set(s);
        }),
        (t.Set.prototype.union = function (e) {
          return e === t.Set.complete
            ? t.Set.complete
            : e === t.Set.empty
              ? this
              : new t.Set(
                  Object.keys(this.elements).concat(Object.keys(e.elements)),
                );
        }),
        (t.idf = function (e, n) {
          var r = 0;
          for (var i in e) i != "_index" && (r += Object.keys(e[i]).length);
          var s = (n - r + 0.5) / (r + 0.5);
          return Math.log(1 + Math.abs(s));
        }),
        (t.Token = function (e, n) {
          (this.str = e || ""), (this.metadata = n || {});
        }),
        (t.Token.prototype.toString = function () {
          return this.str;
        }),
        (t.Token.prototype.update = function (e) {
          return (this.str = e(this.str, this.metadata)), this;
        }),
        (t.Token.prototype.clone = function (e) {
          return (
            (e =
              e ||
              function (n) {
                return n;
              }),
            new t.Token(e(this.str, this.metadata), this.metadata)
          );
        });
      (t.tokenizer = function (e, n) {
        if (e == null || e == null) return [];
        if (Array.isArray(e))
          return e.map(function (f) {
            return new t.Token(
              t.utils.asString(f).toLowerCase(),
              t.utils.clone(n),
            );
          });
        for (
          var r = e.toString().toLowerCase(),
            i = r.length,
            s = [],
            o = 0,
            a = 0;
          o <= i;
          o++
        ) {
          var c = r.charAt(o),
            l = o - a;
          if (c.match(t.tokenizer.separator) || o == i) {
            if (l > 0) {
              var d = t.utils.clone(n) || {};
              (d.position = [a, l]),
                (d.index = s.length),
                s.push(new t.Token(r.slice(a, o), d));
            }
            a = o + 1;
          }
        }
        return s;
      }),
        (t.tokenizer.separator = /[\s\-]+/);
      (t.Pipeline = function () {
        this._stack = [];
      }),
        (t.Pipeline.registeredFunctions = Object.create(null)),
        (t.Pipeline.registerFunction = function (e, n) {
          n in this.registeredFunctions &&
            t.utils.warn("Overwriting existing registered function: " + n),
            (e.label = n),
            (t.Pipeline.registeredFunctions[e.label] = e);
        }),
        (t.Pipeline.warnIfFunctionNotRegistered = function (e) {
          var n = e.label && e.label in this.registeredFunctions;
          n ||
            t.utils.warn(
              `Function is not registered with pipeline. This may cause problems when serialising the index.
`,
              e,
            );
        }),
        (t.Pipeline.load = function (e) {
          var n = new t.Pipeline();
          return (
            e.forEach(function (r) {
              var i = t.Pipeline.registeredFunctions[r];
              if (i) n.add(i);
              else throw new Error("Cannot load unregistered function: " + r);
            }),
            n
          );
        }),
        (t.Pipeline.prototype.add = function () {
          var e = Array.prototype.slice.call(arguments);
          e.forEach(function (n) {
            t.Pipeline.warnIfFunctionNotRegistered(n), this._stack.push(n);
          }, this);
        }),
        (t.Pipeline.prototype.after = function (e, n) {
          t.Pipeline.warnIfFunctionNotRegistered(n);
          var r = this._stack.indexOf(e);
          if (r == -1) throw new Error("Cannot find existingFn");
          (r = r + 1), this._stack.splice(r, 0, n);
        }),
        (t.Pipeline.prototype.before = function (e, n) {
          t.Pipeline.warnIfFunctionNotRegistered(n);
          var r = this._stack.indexOf(e);
          if (r == -1) throw new Error("Cannot find existingFn");
          this._stack.splice(r, 0, n);
        }),
        (t.Pipeline.prototype.remove = function (e) {
          var n = this._stack.indexOf(e);
          n != -1 && this._stack.splice(n, 1);
        }),
        (t.Pipeline.prototype.run = function (e) {
          for (var n = this._stack.length, r = 0; r < n; r++) {
            for (var i = this._stack[r], s = [], o = 0; o < e.length; o++) {
              var a = i(e[o], o, e);
              if (!(a == null || a === ""))
                if (Array.isArray(a))
                  for (var c = 0; c < a.length; c++) s.push(a[c]);
                else s.push(a);
            }
            e = s;
          }
          return e;
        }),
        (t.Pipeline.prototype.runString = function (e, n) {
          var r = new t.Token(e, n);
          return this.run([r]).map(function (i) {
            return i.toString();
          });
        }),
        (t.Pipeline.prototype.reset = function () {
          this._stack = [];
        }),
        (t.Pipeline.prototype.toJSON = function () {
          return this._stack.map(function (e) {
            return t.Pipeline.warnIfFunctionNotRegistered(e), e.label;
          });
        });
      (t.Vector = function (e) {
        (this._magnitude = 0), (this.elements = e || []);
      }),
        (t.Vector.prototype.positionForIndex = function (e) {
          if (this.elements.length == 0) return 0;
          for (
            var n = 0,
              r = this.elements.length / 2,
              i = r - n,
              s = Math.floor(i / 2),
              o = this.elements[s * 2];
            i > 1 && (o < e && (n = s), o > e && (r = s), o != e);

          )
            (i = r - n),
              (s = n + Math.floor(i / 2)),
              (o = this.elements[s * 2]);
          if (o == e || o > e) return s * 2;
          if (o < e) return (s + 1) * 2;
        }),
        (t.Vector.prototype.insert = function (e, n) {
          this.upsert(e, n, function () {
            throw "duplicate index";
          });
        }),
        (t.Vector.prototype.upsert = function (e, n, r) {
          this._magnitude = 0;
          var i = this.positionForIndex(e);
          this.elements[i] == e
            ? (this.elements[i + 1] = r(this.elements[i + 1], n))
            : this.elements.splice(i, 0, e, n);
        }),
        (t.Vector.prototype.magnitude = function () {
          if (this._magnitude) return this._magnitude;
          for (var e = 0, n = this.elements.length, r = 1; r < n; r += 2) {
            var i = this.elements[r];
            e += i * i;
          }
          return (this._magnitude = Math.sqrt(e));
        }),
        (t.Vector.prototype.dot = function (e) {
          for (
            var n = 0,
              r = this.elements,
              i = e.elements,
              s = r.length,
              o = i.length,
              a = 0,
              c = 0,
              l = 0,
              d = 0;
            l < s && d < o;

          )
            (a = r[l]),
              (c = i[d]),
              a < c
                ? (l += 2)
                : a > c
                  ? (d += 2)
                  : a == c && ((n += r[l + 1] * i[d + 1]), (l += 2), (d += 2));
          return n;
        }),
        (t.Vector.prototype.similarity = function (e) {
          return this.dot(e) / this.magnitude() || 0;
        }),
        (t.Vector.prototype.toArray = function () {
          for (
            var e = new Array(this.elements.length / 2), n = 1, r = 0;
            n < this.elements.length;
            n += 2, r++
          )
            e[r] = this.elements[n];
          return e;
        }),
        (t.Vector.prototype.toJSON = function () {
          return this.elements;
        });
      (t.stemmer = (function () {
        var e = {
            ational: "ate",
            tional: "tion",
            enci: "ence",
            anci: "ance",
            izer: "ize",
            bli: "ble",
            alli: "al",
            entli: "ent",
            eli: "e",
            ousli: "ous",
            ization: "ize",
            ation: "ate",
            ator: "ate",
            alism: "al",
            iveness: "ive",
            fulness: "ful",
            ousness: "ous",
            aliti: "al",
            iviti: "ive",
            biliti: "ble",
            logi: "log",
          },
          n = {
            icate: "ic",
            ative: "",
            alize: "al",
            iciti: "ic",
            ical: "ic",
            ful: "",
            ness: "",
          },
          r = "[^aeiou]",
          i = "[aeiouy]",
          s = r + "[^aeiouy]*",
          o = i + "[aeiou]*",
          a = "^(" + s + ")?" + o + s,
          c = "^(" + s + ")?" + o + s + "(" + o + ")?$",
          l = "^(" + s + ")?" + o + s + o + s,
          d = "^(" + s + ")?" + i,
          f = new RegExp(a),
          p = new RegExp(l),
          v = new RegExp(c),
          x = new RegExp(d),
          w = /^(.+?)(ss|i)es$/,
          m = /^(.+?)([^s])s$/,
          g = /^(.+?)eed$/,
          T = /^(.+?)(ed|ing)$/,
          L = /.$/,
          C = /(at|bl|iz)$/,
          O = new RegExp("([^aeiouylsz])\\1$"),
          j = new RegExp("^" + s + i + "[^aeiouwxy]$"),
          N = /^(.+?[^aeiou])y$/,
          q =
            /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,
          W = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,
          B =
            /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,
          z = /^(.+?)(s|t)(ion)$/,
          _ = /^(.+?)e$/,
          U = /ll$/,
          J = new RegExp("^" + s + i + "[^aeiouwxy]$"),
          V = function (u) {
            var y, P, k, h, E, Q, H;
            if (u.length < 3) return u;
            if (
              ((k = u.substr(0, 1)),
              k == "y" && (u = k.toUpperCase() + u.substr(1)),
              (h = w),
              (E = m),
              h.test(u)
                ? (u = u.replace(h, "$1$2"))
                : E.test(u) && (u = u.replace(E, "$1$2")),
              (h = g),
              (E = T),
              h.test(u))
            ) {
              var b = h.exec(u);
              (h = f), h.test(b[1]) && ((h = L), (u = u.replace(h, "")));
            } else if (E.test(u)) {
              var b = E.exec(u);
              (y = b[1]),
                (E = x),
                E.test(y) &&
                  ((u = y),
                  (E = C),
                  (Q = O),
                  (H = j),
                  E.test(u)
                    ? (u = u + "e")
                    : Q.test(u)
                      ? ((h = L), (u = u.replace(h, "")))
                      : H.test(u) && (u = u + "e"));
            }
            if (((h = N), h.test(u))) {
              var b = h.exec(u);
              (y = b[1]), (u = y + "i");
            }
            if (((h = q), h.test(u))) {
              var b = h.exec(u);
              (y = b[1]), (P = b[2]), (h = f), h.test(y) && (u = y + e[P]);
            }
            if (((h = W), h.test(u))) {
              var b = h.exec(u);
              (y = b[1]), (P = b[2]), (h = f), h.test(y) && (u = y + n[P]);
            }
            if (((h = B), (E = z), h.test(u))) {
              var b = h.exec(u);
              (y = b[1]), (h = p), h.test(y) && (u = y);
            } else if (E.test(u)) {
              var b = E.exec(u);
              (y = b[1] + b[2]), (E = p), E.test(y) && (u = y);
            }
            if (((h = _), h.test(u))) {
              var b = h.exec(u);
              (y = b[1]),
                (h = p),
                (E = v),
                (Q = J),
                (h.test(y) || (E.test(y) && !Q.test(y))) && (u = y);
            }
            return (
              (h = U),
              (E = p),
              h.test(u) && E.test(u) && ((h = L), (u = u.replace(h, ""))),
              k == "y" && (u = k.toLowerCase() + u.substr(1)),
              u
            );
          };
        return function (A) {
          return A.update(V);
        };
      })()),
        t.Pipeline.registerFunction(t.stemmer, "stemmer");
      (t.generateStopWordFilter = function (e) {
        var n = e.reduce(function (r, i) {
          return (r[i] = i), r;
        }, {});
        return function (r) {
          if (r && n[r.toString()] !== r.toString()) return r;
        };
      }),
        (t.stopWordFilter = t.generateStopWordFilter([
          "a",
          "able",
          "about",
          "across",
          "after",
          "all",
          "almost",
          "also",
          "am",
          "among",
          "an",
          "and",
          "any",
          "are",
          "as",
          "at",
          "be",
          "because",
          "been",
          "but",
          "by",
          "can",
          "cannot",
          "could",
          "dear",
          "did",
          "do",
          "does",
          "either",
          "else",
          "ever",
          "every",
          "for",
          "from",
          "get",
          "got",
          "had",
          "has",
          "have",
          "he",
          "her",
          "hers",
          "him",
          "his",
          "how",
          "however",
          "i",
          "if",
          "in",
          "into",
          "is",
          "it",
          "its",
          "just",
          "least",
          "let",
          "like",
          "likely",
          "may",
          "me",
          "might",
          "most",
          "must",
          "my",
          "neither",
          "no",
          "nor",
          "not",
          "of",
          "off",
          "often",
          "on",
          "only",
          "or",
          "other",
          "our",
          "own",
          "rather",
          "said",
          "say",
          "says",
          "she",
          "should",
          "since",
          "so",
          "some",
          "than",
          "that",
          "the",
          "their",
          "them",
          "then",
          "there",
          "these",
          "they",
          "this",
          "tis",
          "to",
          "too",
          "twas",
          "us",
          "wants",
          "was",
          "we",
          "were",
          "what",
          "when",
          "where",
          "which",
          "while",
          "who",
          "whom",
          "why",
          "will",
          "with",
          "would",
          "yet",
          "you",
          "your",
        ])),
        t.Pipeline.registerFunction(t.stopWordFilter, "stopWordFilter");
      (t.trimmer = function (e) {
        return e.update(function (n) {
          return n.replace(/^\W+/, "").replace(/\W+$/, "");
        });
      }),
        t.Pipeline.registerFunction(t.trimmer, "trimmer");
      (t.TokenSet = function () {
        (this.final = !1),
          (this.edges = {}),
          (this.id = t.TokenSet._nextId),
          (t.TokenSet._nextId += 1);
      }),
        (t.TokenSet._nextId = 1),
        (t.TokenSet.fromArray = function (e) {
          for (
            var n = new t.TokenSet.Builder(), r = 0, i = e.length;
            r < i;
            r++
          )
            n.insert(e[r]);
          return n.finish(), n.root;
        }),
        (t.TokenSet.fromClause = function (e) {
          return "editDistance" in e
            ? t.TokenSet.fromFuzzyString(e.term, e.editDistance)
            : t.TokenSet.fromString(e.term);
        }),
        (t.TokenSet.fromFuzzyString = function (e, n) {
          for (
            var r = new t.TokenSet(),
              i = [{ node: r, editsRemaining: n, str: e }];
            i.length;

          ) {
            var s = i.pop();
            if (s.str.length > 0) {
              var o = s.str.charAt(0),
                a;
              o in s.node.edges
                ? (a = s.node.edges[o])
                : ((a = new t.TokenSet()), (s.node.edges[o] = a)),
                s.str.length == 1 && (a.final = !0),
                i.push({
                  node: a,
                  editsRemaining: s.editsRemaining,
                  str: s.str.slice(1),
                });
            }
            if (s.editsRemaining != 0) {
              if ("*" in s.node.edges) var c = s.node.edges["*"];
              else {
                var c = new t.TokenSet();
                s.node.edges["*"] = c;
              }
              if (
                (s.str.length == 0 && (c.final = !0),
                i.push({
                  node: c,
                  editsRemaining: s.editsRemaining - 1,
                  str: s.str,
                }),
                s.str.length > 1 &&
                  i.push({
                    node: s.node,
                    editsRemaining: s.editsRemaining - 1,
                    str: s.str.slice(1),
                  }),
                s.str.length == 1 && (s.node.final = !0),
                s.str.length >= 1)
              ) {
                if ("*" in s.node.edges) var l = s.node.edges["*"];
                else {
                  var l = new t.TokenSet();
                  s.node.edges["*"] = l;
                }
                s.str.length == 1 && (l.final = !0),
                  i.push({
                    node: l,
                    editsRemaining: s.editsRemaining - 1,
                    str: s.str.slice(1),
                  });
              }
              if (s.str.length > 1) {
                var d = s.str.charAt(0),
                  f = s.str.charAt(1),
                  p;
                f in s.node.edges
                  ? (p = s.node.edges[f])
                  : ((p = new t.TokenSet()), (s.node.edges[f] = p)),
                  s.str.length == 1 && (p.final = !0),
                  i.push({
                    node: p,
                    editsRemaining: s.editsRemaining - 1,
                    str: d + s.str.slice(2),
                  });
              }
            }
          }
          return r;
        }),
        (t.TokenSet.fromString = function (e) {
          for (
            var n = new t.TokenSet(), r = n, i = 0, s = e.length;
            i < s;
            i++
          ) {
            var o = e[i],
              a = i == s - 1;
            if (o == "*") (n.edges[o] = n), (n.final = a);
            else {
              var c = new t.TokenSet();
              (c.final = a), (n.edges[o] = c), (n = c);
            }
          }
          return r;
        }),
        (t.TokenSet.prototype.toArray = function () {
          for (var e = [], n = [{ prefix: "", node: this }]; n.length; ) {
            var r = n.pop(),
              i = Object.keys(r.node.edges),
              s = i.length;
            r.node.final && (r.prefix.charAt(0), e.push(r.prefix));
            for (var o = 0; o < s; o++) {
              var a = i[o];
              n.push({ prefix: r.prefix.concat(a), node: r.node.edges[a] });
            }
          }
          return e;
        }),
        (t.TokenSet.prototype.toString = function () {
          if (this._str) return this._str;
          for (
            var e = this.final ? "1" : "0",
              n = Object.keys(this.edges).sort(),
              r = n.length,
              i = 0;
            i < r;
            i++
          ) {
            var s = n[i],
              o = this.edges[s];
            e = e + s + o.id;
          }
          return e;
        }),
        (t.TokenSet.prototype.intersect = function (e) {
          for (
            var n = new t.TokenSet(),
              r = void 0,
              i = [{ qNode: e, output: n, node: this }];
            i.length;

          ) {
            r = i.pop();
            for (
              var s = Object.keys(r.qNode.edges),
                o = s.length,
                a = Object.keys(r.node.edges),
                c = a.length,
                l = 0;
              l < o;
              l++
            )
              for (var d = s[l], f = 0; f < c; f++) {
                var p = a[f];
                if (p == d || d == "*") {
                  var v = r.node.edges[p],
                    x = r.qNode.edges[d],
                    w = v.final && x.final,
                    m = void 0;
                  p in r.output.edges
                    ? ((m = r.output.edges[p]), (m.final = m.final || w))
                    : ((m = new t.TokenSet()),
                      (m.final = w),
                      (r.output.edges[p] = m)),
                    i.push({ qNode: x, output: m, node: v });
                }
              }
          }
          return n;
        }),
        (t.TokenSet.Builder = function () {
          (this.previousWord = ""),
            (this.root = new t.TokenSet()),
            (this.uncheckedNodes = []),
            (this.minimizedNodes = {});
        }),
        (t.TokenSet.Builder.prototype.insert = function (e) {
          var n,
            r = 0;
          if (e < this.previousWord)
            throw new Error("Out of order word insertion");
          for (
            var i = 0;
            i < e.length &&
            i < this.previousWord.length &&
            e[i] == this.previousWord[i];
            i++
          )
            r++;
          this.minimize(r),
            this.uncheckedNodes.length == 0
              ? (n = this.root)
              : (n = this.uncheckedNodes[this.uncheckedNodes.length - 1].child);
          for (var i = r; i < e.length; i++) {
            var s = new t.TokenSet(),
              o = e[i];
            (n.edges[o] = s),
              this.uncheckedNodes.push({ parent: n, char: o, child: s }),
              (n = s);
          }
          (n.final = !0), (this.previousWord = e);
        }),
        (t.TokenSet.Builder.prototype.finish = function () {
          this.minimize(0);
        }),
        (t.TokenSet.Builder.prototype.minimize = function (e) {
          for (var n = this.uncheckedNodes.length - 1; n >= e; n--) {
            var r = this.uncheckedNodes[n],
              i = r.child.toString();
            i in this.minimizedNodes
              ? (r.parent.edges[r.char] = this.minimizedNodes[i])
              : ((r.child._str = i), (this.minimizedNodes[i] = r.child)),
              this.uncheckedNodes.pop();
          }
        });
      (t.Index = function (e) {
        (this.invertedIndex = e.invertedIndex),
          (this.fieldVectors = e.fieldVectors),
          (this.tokenSet = e.tokenSet),
          (this.fields = e.fields),
          (this.pipeline = e.pipeline);
      }),
        (t.Index.prototype.search = function (e) {
          return this.query(function (n) {
            var r = new t.QueryParser(e, n);
            r.parse();
          });
        }),
        (t.Index.prototype.query = function (e) {
          for (
            var n = new t.Query(this.fields),
              r = Object.create(null),
              i = Object.create(null),
              s = Object.create(null),
              o = Object.create(null),
              a = Object.create(null),
              c = 0;
            c < this.fields.length;
            c++
          )
            i[this.fields[c]] = new t.Vector();
          e.call(n, n);
          for (var c = 0; c < n.clauses.length; c++) {
            var l = n.clauses[c],
              d = null,
              f = t.Set.empty;
            l.usePipeline
              ? (d = this.pipeline.runString(l.term, { fields: l.fields }))
              : (d = [l.term]);
            for (var p = 0; p < d.length; p++) {
              var v = d[p];
              l.term = v;
              var x = t.TokenSet.fromClause(l),
                w = this.tokenSet.intersect(x).toArray();
              if (w.length === 0 && l.presence === t.Query.presence.REQUIRED) {
                for (var m = 0; m < l.fields.length; m++) {
                  var g = l.fields[m];
                  o[g] = t.Set.empty;
                }
                break;
              }
              for (var T = 0; T < w.length; T++)
                for (
                  var L = w[T], C = this.invertedIndex[L], O = C._index, m = 0;
                  m < l.fields.length;
                  m++
                ) {
                  var g = l.fields[m],
                    j = C[g],
                    N = Object.keys(j),
                    q = L + "/" + g,
                    W = new t.Set(N);
                  if (
                    (l.presence == t.Query.presence.REQUIRED &&
                      ((f = f.union(W)),
                      o[g] === void 0 && (o[g] = t.Set.complete)),
                    l.presence == t.Query.presence.PROHIBITED)
                  ) {
                    a[g] === void 0 && (a[g] = t.Set.empty),
                      (a[g] = a[g].union(W));
                    continue;
                  }
                  if (
                    (i[g].upsert(O, l.boost, function (Ue, Je) {
                      return Ue + Je;
                    }),
                    !s[q])
                  ) {
                    for (var B = 0; B < N.length; B++) {
                      var z = N[B],
                        _ = new t.FieldRef(z, g),
                        U = j[z],
                        J;
                      (J = r[_]) === void 0
                        ? (r[_] = new t.MatchData(L, g, U))
                        : J.add(L, g, U);
                    }
                    s[q] = !0;
                  }
                }
            }
            if (l.presence === t.Query.presence.REQUIRED)
              for (var m = 0; m < l.fields.length; m++) {
                var g = l.fields[m];
                o[g] = o[g].intersect(f);
              }
          }
          for (
            var V = t.Set.complete, A = t.Set.empty, c = 0;
            c < this.fields.length;
            c++
          ) {
            var g = this.fields[c];
            o[g] && (V = V.intersect(o[g])), a[g] && (A = A.union(a[g]));
          }
          var u = Object.keys(r),
            y = [],
            P = Object.create(null);
          if (n.isNegated()) {
            u = Object.keys(this.fieldVectors);
            for (var c = 0; c < u.length; c++) {
              var _ = u[c],
                k = t.FieldRef.fromString(_);
              r[_] = new t.MatchData();
            }
          }
          for (var c = 0; c < u.length; c++) {
            var k = t.FieldRef.fromString(u[c]),
              h = k.docRef;
            if (V.contains(h) && !A.contains(h)) {
              var E = this.fieldVectors[k],
                Q = i[k.fieldName].similarity(E),
                H;
              if ((H = P[h]) !== void 0)
                (H.score += Q), H.matchData.combine(r[k]);
              else {
                var b = { ref: h, score: Q, matchData: r[k] };
                (P[h] = b), y.push(b);
              }
            }
          }
          return y.sort(function (We, ze) {
            return ze.score - We.score;
          });
        }),
        (t.Index.prototype.toJSON = function () {
          var e = Object.keys(this.invertedIndex)
              .sort()
              .map(function (r) {
                return [r, this.invertedIndex[r]];
              }, this),
            n = Object.keys(this.fieldVectors).map(function (r) {
              return [r, this.fieldVectors[r].toJSON()];
            }, this);
          return {
            version: t.version,
            fields: this.fields,
            fieldVectors: n,
            invertedIndex: e,
            pipeline: this.pipeline.toJSON(),
          };
        }),
        (t.Index.load = function (e) {
          var n = {},
            r = {},
            i = e.fieldVectors,
            s = Object.create(null),
            o = e.invertedIndex,
            a = new t.TokenSet.Builder(),
            c = t.Pipeline.load(e.pipeline);
          e.version != t.version &&
            t.utils.warn(
              "Version mismatch when loading serialised index. Current version of lunr '" +
                t.version +
                "' does not match serialized index '" +
                e.version +
                "'",
            );
          for (var l = 0; l < i.length; l++) {
            var d = i[l],
              f = d[0],
              p = d[1];
            r[f] = new t.Vector(p);
          }
          for (var l = 0; l < o.length; l++) {
            var d = o[l],
              v = d[0],
              x = d[1];
            a.insert(v), (s[v] = x);
          }
          return (
            a.finish(),
            (n.fields = e.fields),
            (n.fieldVectors = r),
            (n.invertedIndex = s),
            (n.tokenSet = a.root),
            (n.pipeline = c),
            new t.Index(n)
          );
        });
      (t.Builder = function () {
        (this._ref = "id"),
          (this._fields = Object.create(null)),
          (this._documents = Object.create(null)),
          (this.invertedIndex = Object.create(null)),
          (this.fieldTermFrequencies = {}),
          (this.fieldLengths = {}),
          (this.tokenizer = t.tokenizer),
          (this.pipeline = new t.Pipeline()),
          (this.searchPipeline = new t.Pipeline()),
          (this.documentCount = 0),
          (this._b = 0.75),
          (this._k1 = 1.2),
          (this.termIndex = 0),
          (this.metadataWhitelist = []);
      }),
        (t.Builder.prototype.ref = function (e) {
          this._ref = e;
        }),
        (t.Builder.prototype.field = function (e, n) {
          if (/\//.test(e))
            throw new RangeError(
              "Field '" + e + "' contains illegal character '/'",
            );
          this._fields[e] = n || {};
        }),
        (t.Builder.prototype.b = function (e) {
          e < 0 ? (this._b = 0) : e > 1 ? (this._b = 1) : (this._b = e);
        }),
        (t.Builder.prototype.k1 = function (e) {
          this._k1 = e;
        }),
        (t.Builder.prototype.add = function (e, n) {
          var r = e[this._ref],
            i = Object.keys(this._fields);
          (this._documents[r] = n || {}), (this.documentCount += 1);
          for (var s = 0; s < i.length; s++) {
            var o = i[s],
              a = this._fields[o].extractor,
              c = a ? a(e) : e[o],
              l = this.tokenizer(c, { fields: [o] }),
              d = this.pipeline.run(l),
              f = new t.FieldRef(r, o),
              p = Object.create(null);
            (this.fieldTermFrequencies[f] = p),
              (this.fieldLengths[f] = 0),
              (this.fieldLengths[f] += d.length);
            for (var v = 0; v < d.length; v++) {
              var x = d[v];
              if (
                (p[x] == null && (p[x] = 0),
                (p[x] += 1),
                this.invertedIndex[x] == null)
              ) {
                var w = Object.create(null);
                (w._index = this.termIndex), (this.termIndex += 1);
                for (var m = 0; m < i.length; m++)
                  w[i[m]] = Object.create(null);
                this.invertedIndex[x] = w;
              }
              this.invertedIndex[x][o][r] == null &&
                (this.invertedIndex[x][o][r] = Object.create(null));
              for (var g = 0; g < this.metadataWhitelist.length; g++) {
                var T = this.metadataWhitelist[g],
                  L = x.metadata[T];
                this.invertedIndex[x][o][r][T] == null &&
                  (this.invertedIndex[x][o][r][T] = []),
                  this.invertedIndex[x][o][r][T].push(L);
              }
            }
          }
        }),
        (t.Builder.prototype.calculateAverageFieldLengths = function () {
          for (
            var e = Object.keys(this.fieldLengths),
              n = e.length,
              r = {},
              i = {},
              s = 0;
            s < n;
            s++
          ) {
            var o = t.FieldRef.fromString(e[s]),
              a = o.fieldName;
            i[a] || (i[a] = 0),
              (i[a] += 1),
              r[a] || (r[a] = 0),
              (r[a] += this.fieldLengths[o]);
          }
          for (var c = Object.keys(this._fields), s = 0; s < c.length; s++) {
            var l = c[s];
            r[l] = r[l] / i[l];
          }
          this.averageFieldLength = r;
        }),
        (t.Builder.prototype.createFieldVectors = function () {
          for (
            var e = {},
              n = Object.keys(this.fieldTermFrequencies),
              r = n.length,
              i = Object.create(null),
              s = 0;
            s < r;
            s++
          ) {
            for (
              var o = t.FieldRef.fromString(n[s]),
                a = o.fieldName,
                c = this.fieldLengths[o],
                l = new t.Vector(),
                d = this.fieldTermFrequencies[o],
                f = Object.keys(d),
                p = f.length,
                v = this._fields[a].boost || 1,
                x = this._documents[o.docRef].boost || 1,
                w = 0;
              w < p;
              w++
            ) {
              var m = f[w],
                g = d[m],
                T = this.invertedIndex[m]._index,
                L,
                C,
                O;
              i[m] === void 0
                ? ((L = t.idf(this.invertedIndex[m], this.documentCount)),
                  (i[m] = L))
                : (L = i[m]),
                (C =
                  (L * ((this._k1 + 1) * g)) /
                  (this._k1 *
                    (1 - this._b + this._b * (c / this.averageFieldLength[a])) +
                    g)),
                (C *= v),
                (C *= x),
                (O = Math.round(C * 1e3) / 1e3),
                l.insert(T, O);
            }
            e[o] = l;
          }
          this.fieldVectors = e;
        }),
        (t.Builder.prototype.createTokenSet = function () {
          this.tokenSet = t.TokenSet.fromArray(
            Object.keys(this.invertedIndex).sort(),
          );
        }),
        (t.Builder.prototype.build = function () {
          return (
            this.calculateAverageFieldLengths(),
            this.createFieldVectors(),
            this.createTokenSet(),
            new t.Index({
              invertedIndex: this.invertedIndex,
              fieldVectors: this.fieldVectors,
              tokenSet: this.tokenSet,
              fields: Object.keys(this._fields),
              pipeline: this.searchPipeline,
            })
          );
        }),
        (t.Builder.prototype.use = function (e) {
          var n = Array.prototype.slice.call(arguments, 1);
          n.unshift(this), e.apply(this, n);
        }),
        (t.MatchData = function (e, n, r) {
          for (
            var i = Object.create(null), s = Object.keys(r || {}), o = 0;
            o < s.length;
            o++
          ) {
            var a = s[o];
            i[a] = r[a].slice();
          }
          (this.metadata = Object.create(null)),
            e !== void 0 &&
              ((this.metadata[e] = Object.create(null)),
              (this.metadata[e][n] = i));
        }),
        (t.MatchData.prototype.combine = function (e) {
          for (var n = Object.keys(e.metadata), r = 0; r < n.length; r++) {
            var i = n[r],
              s = Object.keys(e.metadata[i]);
            this.metadata[i] == null &&
              (this.metadata[i] = Object.create(null));
            for (var o = 0; o < s.length; o++) {
              var a = s[o],
                c = Object.keys(e.metadata[i][a]);
              this.metadata[i][a] == null &&
                (this.metadata[i][a] = Object.create(null));
              for (var l = 0; l < c.length; l++) {
                var d = c[l];
                this.metadata[i][a][d] == null
                  ? (this.metadata[i][a][d] = e.metadata[i][a][d])
                  : (this.metadata[i][a][d] = this.metadata[i][a][d].concat(
                      e.metadata[i][a][d],
                    ));
              }
            }
          }
        }),
        (t.MatchData.prototype.add = function (e, n, r) {
          if (!(e in this.metadata)) {
            (this.metadata[e] = Object.create(null)), (this.metadata[e][n] = r);
            return;
          }
          if (!(n in this.metadata[e])) {
            this.metadata[e][n] = r;
            return;
          }
          for (var i = Object.keys(r), s = 0; s < i.length; s++) {
            var o = i[s];
            o in this.metadata[e][n]
              ? (this.metadata[e][n][o] = this.metadata[e][n][o].concat(r[o]))
              : (this.metadata[e][n][o] = r[o]);
          }
        }),
        (t.Query = function (e) {
          (this.clauses = []), (this.allFields = e);
        }),
        (t.Query.wildcard = new String("*")),
        (t.Query.wildcard.NONE = 0),
        (t.Query.wildcard.LEADING = 1),
        (t.Query.wildcard.TRAILING = 2),
        (t.Query.presence = { OPTIONAL: 1, REQUIRED: 2, PROHIBITED: 3 }),
        (t.Query.prototype.clause = function (e) {
          return (
            "fields" in e || (e.fields = this.allFields),
            "boost" in e || (e.boost = 1),
            "usePipeline" in e || (e.usePipeline = !0),
            "wildcard" in e || (e.wildcard = t.Query.wildcard.NONE),
            e.wildcard & t.Query.wildcard.LEADING &&
              e.term.charAt(0) != t.Query.wildcard &&
              (e.term = "*" + e.term),
            e.wildcard & t.Query.wildcard.TRAILING &&
              e.term.slice(-1) != t.Query.wildcard &&
              (e.term = "" + e.term + "*"),
            "presence" in e || (e.presence = t.Query.presence.OPTIONAL),
            this.clauses.push(e),
            this
          );
        }),
        (t.Query.prototype.isNegated = function () {
          for (var e = 0; e < this.clauses.length; e++)
            if (this.clauses[e].presence != t.Query.presence.PROHIBITED)
              return !1;
          return !0;
        }),
        (t.Query.prototype.term = function (e, n) {
          if (Array.isArray(e))
            return (
              e.forEach(function (i) {
                this.term(i, t.utils.clone(n));
              }, this),
              this
            );
          var r = n || {};
          return (r.term = e.toString()), this.clause(r), this;
        }),
        (t.QueryParseError = function (e, n, r) {
          (this.name = "QueryParseError"),
            (this.message = e),
            (this.start = n),
            (this.end = r);
        }),
        (t.QueryParseError.prototype = new Error()),
        (t.QueryLexer = function (e) {
          (this.lexemes = []),
            (this.str = e),
            (this.length = e.length),
            (this.pos = 0),
            (this.start = 0),
            (this.escapeCharPositions = []);
        }),
        (t.QueryLexer.prototype.run = function () {
          for (var e = t.QueryLexer.lexText; e; ) e = e(this);
        }),
        (t.QueryLexer.prototype.sliceString = function () {
          for (
            var e = [], n = this.start, r = this.pos, i = 0;
            i < this.escapeCharPositions.length;
            i++
          )
            (r = this.escapeCharPositions[i]),
              e.push(this.str.slice(n, r)),
              (n = r + 1);
          return (
            e.push(this.str.slice(n, this.pos)),
            (this.escapeCharPositions.length = 0),
            e.join("")
          );
        }),
        (t.QueryLexer.prototype.emit = function (e) {
          this.lexemes.push({
            type: e,
            str: this.sliceString(),
            start: this.start,
            end: this.pos,
          }),
            (this.start = this.pos);
        }),
        (t.QueryLexer.prototype.escapeCharacter = function () {
          this.escapeCharPositions.push(this.pos - 1), (this.pos += 1);
        }),
        (t.QueryLexer.prototype.next = function () {
          if (this.pos >= this.length) return t.QueryLexer.EOS;
          var e = this.str.charAt(this.pos);
          return (this.pos += 1), e;
        }),
        (t.QueryLexer.prototype.width = function () {
          return this.pos - this.start;
        }),
        (t.QueryLexer.prototype.ignore = function () {
          this.start == this.pos && (this.pos += 1), (this.start = this.pos);
        }),
        (t.QueryLexer.prototype.backup = function () {
          this.pos -= 1;
        }),
        (t.QueryLexer.prototype.acceptDigitRun = function () {
          var e, n;
          do (e = this.next()), (n = e.charCodeAt(0));
          while (n > 47 && n < 58);
          e != t.QueryLexer.EOS && this.backup();
        }),
        (t.QueryLexer.prototype.more = function () {
          return this.pos < this.length;
        }),
        (t.QueryLexer.EOS = "EOS"),
        (t.QueryLexer.FIELD = "FIELD"),
        (t.QueryLexer.TERM = "TERM"),
        (t.QueryLexer.EDIT_DISTANCE = "EDIT_DISTANCE"),
        (t.QueryLexer.BOOST = "BOOST"),
        (t.QueryLexer.PRESENCE = "PRESENCE"),
        (t.QueryLexer.lexField = function (e) {
          return (
            e.backup(),
            e.emit(t.QueryLexer.FIELD),
            e.ignore(),
            t.QueryLexer.lexText
          );
        }),
        (t.QueryLexer.lexTerm = function (e) {
          if (
            (e.width() > 1 && (e.backup(), e.emit(t.QueryLexer.TERM)),
            e.ignore(),
            e.more())
          )
            return t.QueryLexer.lexText;
        }),
        (t.QueryLexer.lexEditDistance = function (e) {
          return (
            e.ignore(),
            e.acceptDigitRun(),
            e.emit(t.QueryLexer.EDIT_DISTANCE),
            t.QueryLexer.lexText
          );
        }),
        (t.QueryLexer.lexBoost = function (e) {
          return (
            e.ignore(),
            e.acceptDigitRun(),
            e.emit(t.QueryLexer.BOOST),
            t.QueryLexer.lexText
          );
        }),
        (t.QueryLexer.lexEOS = function (e) {
          e.width() > 0 && e.emit(t.QueryLexer.TERM);
        }),
        (t.QueryLexer.termSeparator = t.tokenizer.separator),
        (t.QueryLexer.lexText = function (e) {
          for (;;) {
            var n = e.next();
            if (n == t.QueryLexer.EOS) return t.QueryLexer.lexEOS;
            if (n.charCodeAt(0) == 92) {
              e.escapeCharacter();
              continue;
            }
            if (n == ":") return t.QueryLexer.lexField;
            if (n == "~")
              return (
                e.backup(),
                e.width() > 0 && e.emit(t.QueryLexer.TERM),
                t.QueryLexer.lexEditDistance
              );
            if (n == "^")
              return (
                e.backup(),
                e.width() > 0 && e.emit(t.QueryLexer.TERM),
                t.QueryLexer.lexBoost
              );
            if ((n == "+" && e.width() === 1) || (n == "-" && e.width() === 1))
              return e.emit(t.QueryLexer.PRESENCE), t.QueryLexer.lexText;
            if (n.match(t.QueryLexer.termSeparator))
              return t.QueryLexer.lexTerm;
          }
        }),
        (t.QueryParser = function (e, n) {
          (this.lexer = new t.QueryLexer(e)),
            (this.query = n),
            (this.currentClause = {}),
            (this.lexemeIdx = 0);
        }),
        (t.QueryParser.prototype.parse = function () {
          this.lexer.run(), (this.lexemes = this.lexer.lexemes);
          for (var e = t.QueryParser.parseClause; e; ) e = e(this);
          return this.query;
        }),
        (t.QueryParser.prototype.peekLexeme = function () {
          return this.lexemes[this.lexemeIdx];
        }),
        (t.QueryParser.prototype.consumeLexeme = function () {
          var e = this.peekLexeme();
          return (this.lexemeIdx += 1), e;
        }),
        (t.QueryParser.prototype.nextClause = function () {
          var e = this.currentClause;
          this.query.clause(e), (this.currentClause = {});
        }),
        (t.QueryParser.parseClause = function (e) {
          var n = e.peekLexeme();
          if (n != null)
            switch (n.type) {
              case t.QueryLexer.PRESENCE:
                return t.QueryParser.parsePresence;
              case t.QueryLexer.FIELD:
                return t.QueryParser.parseField;
              case t.QueryLexer.TERM:
                return t.QueryParser.parseTerm;
              default:
                var r = "expected either a field or a term, found " + n.type;
                throw (
                  (n.str.length >= 1 && (r += " with value '" + n.str + "'"),
                  new t.QueryParseError(r, n.start, n.end))
                );
            }
        }),
        (t.QueryParser.parsePresence = function (e) {
          var n = e.consumeLexeme();
          if (n != null) {
            switch (n.str) {
              case "-":
                e.currentClause.presence = t.Query.presence.PROHIBITED;
                break;
              case "+":
                e.currentClause.presence = t.Query.presence.REQUIRED;
                break;
              default:
                var r = "unrecognised presence operator'" + n.str + "'";
                throw new t.QueryParseError(r, n.start, n.end);
            }
            var i = e.peekLexeme();
            if (i == null) {
              var r = "expecting term or field, found nothing";
              throw new t.QueryParseError(r, n.start, n.end);
            }
            switch (i.type) {
              case t.QueryLexer.FIELD:
                return t.QueryParser.parseField;
              case t.QueryLexer.TERM:
                return t.QueryParser.parseTerm;
              default:
                var r = "expecting term or field, found '" + i.type + "'";
                throw new t.QueryParseError(r, i.start, i.end);
            }
          }
        }),
        (t.QueryParser.parseField = function (e) {
          var n = e.consumeLexeme();
          if (n != null) {
            if (e.query.allFields.indexOf(n.str) == -1) {
              var r = e.query.allFields
                  .map(function (o) {
                    return "'" + o + "'";
                  })
                  .join(", "),
                i = "unrecognised field '" + n.str + "', possible fields: " + r;
              throw new t.QueryParseError(i, n.start, n.end);
            }
            e.currentClause.fields = [n.str];
            var s = e.peekLexeme();
            if (s == null) {
              var i = "expecting term, found nothing";
              throw new t.QueryParseError(i, n.start, n.end);
            }
            switch (s.type) {
              case t.QueryLexer.TERM:
                return t.QueryParser.parseTerm;
              default:
                var i = "expecting term, found '" + s.type + "'";
                throw new t.QueryParseError(i, s.start, s.end);
            }
          }
        }),
        (t.QueryParser.parseTerm = function (e) {
          var n = e.consumeLexeme();
          if (n != null) {
            (e.currentClause.term = n.str.toLowerCase()),
              n.str.indexOf("*") != -1 && (e.currentClause.usePipeline = !1);
            var r = e.peekLexeme();
            if (r == null) {
              e.nextClause();
              return;
            }
            switch (r.type) {
              case t.QueryLexer.TERM:
                return e.nextClause(), t.QueryParser.parseTerm;
              case t.QueryLexer.FIELD:
                return e.nextClause(), t.QueryParser.parseField;
              case t.QueryLexer.EDIT_DISTANCE:
                return t.QueryParser.parseEditDistance;
              case t.QueryLexer.BOOST:
                return t.QueryParser.parseBoost;
              case t.QueryLexer.PRESENCE:
                return e.nextClause(), t.QueryParser.parsePresence;
              default:
                var i = "Unexpected lexeme type '" + r.type + "'";
                throw new t.QueryParseError(i, r.start, r.end);
            }
          }
        }),
        (t.QueryParser.parseEditDistance = function (e) {
          var n = e.consumeLexeme();
          if (n != null) {
            var r = parseInt(n.str, 10);
            if (isNaN(r)) {
              var i = "edit distance must be numeric";
              throw new t.QueryParseError(i, n.start, n.end);
            }
            e.currentClause.editDistance = r;
            var s = e.peekLexeme();
            if (s == null) {
              e.nextClause();
              return;
            }
            switch (s.type) {
              case t.QueryLexer.TERM:
                return e.nextClause(), t.QueryParser.parseTerm;
              case t.QueryLexer.FIELD:
                return e.nextClause(), t.QueryParser.parseField;
              case t.QueryLexer.EDIT_DISTANCE:
                return t.QueryParser.parseEditDistance;
              case t.QueryLexer.BOOST:
                return t.QueryParser.parseBoost;
              case t.QueryLexer.PRESENCE:
                return e.nextClause(), t.QueryParser.parsePresence;
              default:
                var i = "Unexpected lexeme type '" + s.type + "'";
                throw new t.QueryParseError(i, s.start, s.end);
            }
          }
        }),
        (t.QueryParser.parseBoost = function (e) {
          var n = e.consumeLexeme();
          if (n != null) {
            var r = parseInt(n.str, 10);
            if (isNaN(r)) {
              var i = "boost must be numeric";
              throw new t.QueryParseError(i, n.start, n.end);
            }
            e.currentClause.boost = r;
            var s = e.peekLexeme();
            if (s == null) {
              e.nextClause();
              return;
            }
            switch (s.type) {
              case t.QueryLexer.TERM:
                return e.nextClause(), t.QueryParser.parseTerm;
              case t.QueryLexer.FIELD:
                return e.nextClause(), t.QueryParser.parseField;
              case t.QueryLexer.EDIT_DISTANCE:
                return t.QueryParser.parseEditDistance;
              case t.QueryLexer.BOOST:
                return t.QueryParser.parseBoost;
              case t.QueryLexer.PRESENCE:
                return e.nextClause(), t.QueryParser.parsePresence;
              default:
                var i = "Unexpected lexeme type '" + s.type + "'";
                throw new t.QueryParseError(i, s.start, s.end);
            }
          }
        }),
        (function (e, n) {
          typeof define == "function" && define.amd
            ? define(n)
            : typeof me == "object"
              ? (ge.exports = n())
              : (e.lunr = n());
        })(this, function () {
          return t;
        });
    })();
  });
  var M,
    G = {
      getItem() {
        return null;
      },
      setItem() {},
    },
    K;
  try {
    (K = localStorage), (M = K);
  } catch {
    (K = G), (M = G);
  }
  var S = {
    getItem: (t) => M.getItem(t),
    setItem: (t, e) => M.setItem(t, e),
    disableWritingLocalStorage() {
      M = G;
    },
    disable() {
      localStorage.clear(), (M = G);
    },
    enable() {
      M = K;
    },
  };
  window.TypeDoc ||= {
    disableWritingLocalStorage() {
      S.disableWritingLocalStorage();
    },
    disableLocalStorage: () => {
      S.disable();
    },
    enableLocalStorage: () => {
      S.enable();
    },
  };
  window.translations ||= {
    copy: "Copy",
    copied: "Copied!",
    normally_hidden:
      "This member is normally hidden due to your filter settings.",
    hierarchy_expand: "Expand",
    hierarchy_collapse: "Collapse",
    search_index_not_available: "The search index is not available",
    search_no_results_found_for_0: "No results found for {0}",
    folder: "Folder",
    kind_1: "Project",
    kind_2: "Module",
    kind_4: "Namespace",
    kind_8: "Enumeration",
    kind_16: "Enumeration Member",
    kind_32: "Variable",
    kind_64: "Function",
    kind_128: "Class",
    kind_256: "Interface",
    kind_512: "Constructor",
    kind_1024: "Property",
    kind_2048: "Method",
    kind_4096: "Call Signature",
    kind_8192: "Index Signature",
    kind_16384: "Constructor Signature",
    kind_32768: "Parameter",
    kind_65536: "Type Literal",
    kind_131072: "Type Parameter",
    kind_262144: "Accessor",
    kind_524288: "Get Signature",
    kind_1048576: "Set Signature",
    kind_2097152: "Type Alias",
    kind_4194304: "Reference",
    kind_8388608: "Document",
  };
  var pe = [];
  function X(t, e) {
    pe.push({ selector: e, constructor: t });
  }
  var Z = class {
    alwaysVisibleMember = null;
    constructor() {
      this.createComponents(document.body),
        this.ensureFocusedElementVisible(),
        this.listenForCodeCopies(),
        window.addEventListener("hashchange", () =>
          this.ensureFocusedElementVisible(),
        ),
        document.body.style.display ||
          (this.ensureFocusedElementVisible(),
          this.updateIndexVisibility(),
          this.scrollToHash());
    }
    createComponents(e) {
      pe.forEach((n) => {
        e.querySelectorAll(n.selector).forEach((r) => {
          r.dataset.hasInstance ||
            (new n.constructor({ el: r, app: this }),
            (r.dataset.hasInstance = String(!0)));
        });
      });
    }
    filterChanged() {
      this.ensureFocusedElementVisible();
    }
    showPage() {
      document.body.style.display &&
        (document.body.style.removeProperty("display"),
        this.ensureFocusedElementVisible(),
        this.updateIndexVisibility(),
        this.scrollToHash());
    }
    scrollToHash() {
      if (location.hash) {
        let e = document.getElementById(location.hash.substring(1));
        if (!e) return;
        e.scrollIntoView({ behavior: "instant", block: "start" });
      }
    }
    ensureActivePageVisible() {
      let e = document.querySelector(".tsd-navigation .current"),
        n = e?.parentElement;
      for (; n && !n.classList.contains(".tsd-navigation"); )
        n instanceof HTMLDetailsElement && (n.open = !0), (n = n.parentElement);
      if (e && !rt(e)) {
        let r =
          e.getBoundingClientRect().top -
          document.documentElement.clientHeight / 4;
        (document.querySelector(".site-menu").scrollTop = r),
          (document.querySelector(".col-sidebar").scrollTop = r);
      }
    }
    updateIndexVisibility() {
      let e = document.querySelector(".tsd-index-content"),
        n = e?.open;
      e && (e.open = !0),
        document.querySelectorAll(".tsd-index-section").forEach((r) => {
          r.style.display = "block";
          let i = Array.from(r.querySelectorAll(".tsd-index-link")).every(
            (s) => s.offsetParent == null,
          );
          r.style.display = i ? "none" : "block";
        }),
        e && (e.open = n);
    }
    ensureFocusedElementVisible() {
      if (
        (this.alwaysVisibleMember &&
          (this.alwaysVisibleMember.classList.remove("always-visible"),
          this.alwaysVisibleMember.firstElementChild.remove(),
          (this.alwaysVisibleMember = null)),
        !location.hash)
      )
        return;
      let e = document.getElementById(location.hash.substring(1));
      if (!e) return;
      let n = e.parentElement;
      for (; n && n.tagName !== "SECTION"; ) n = n.parentElement;
      if (!n) return;
      let r = n.offsetParent == null,
        i = n;
      for (; i !== document.body; )
        i instanceof HTMLDetailsElement && (i.open = !0), (i = i.parentElement);
      if (n.offsetParent == null) {
        (this.alwaysVisibleMember = n), n.classList.add("always-visible");
        let s = document.createElement("p");
        s.classList.add("warning"),
          (s.textContent = window.translations.normally_hidden),
          n.prepend(s);
      }
      r && e.scrollIntoView();
    }
    listenForCodeCopies() {
      document.querySelectorAll("pre > button").forEach((e) => {
        let n;
        e.addEventListener("click", () => {
          e.previousElementSibling instanceof HTMLElement &&
            navigator.clipboard.writeText(
              e.previousElementSibling.innerText.trim(),
            ),
            (e.textContent = window.translations.copied),
            e.classList.add("visible"),
            clearTimeout(n),
            (n = setTimeout(() => {
              e.classList.remove("visible"),
                (n = setTimeout(() => {
                  e.textContent = window.translations.copy;
                }, 100));
            }, 1e3));
        });
      });
    }
  };
  function rt(t) {
    let e = t.getBoundingClientRect(),
      n = Math.max(document.documentElement.clientHeight, window.innerHeight);
    return !(e.bottom < 0 || e.top - n >= 0);
  }
  var fe = (t, e = 100) => {
    let n;
    return () => {
      clearTimeout(n), (n = setTimeout(() => t(), e));
    };
  };
  var Ie = nt(ye(), 1);
  async function R(t) {
    let e = Uint8Array.from(atob(t), (s) => s.charCodeAt(0)),
      r = new Blob([e])
        .stream()
        .pipeThrough(new DecompressionStream("deflate")),
      i = await new Response(r).text();
    return JSON.parse(i);
  }
  var Y = "closing",
    ae = "tsd-overlay";
  function it() {
    let t = Math.abs(window.innerWidth - document.documentElement.clientWidth);
    (document.body.style.overflow = "hidden"),
      (document.body.style.paddingRight = `${t}px`);
  }
  function st() {
    document.body.style.removeProperty("overflow"),
      document.body.style.removeProperty("padding-right");
  }
  function xe(t, e) {
    t.addEventListener("animationend", () => {
      t.classList.contains(Y) &&
        (t.classList.remove(Y),
        document.getElementById(ae)?.remove(),
        t.close(),
        st());
    }),
      t.addEventListener("cancel", (n) => {
        n.preventDefault(), ve(t);
      }),
      e?.closeOnClick &&
        document.addEventListener(
          "click",
          (n) => {
            t.open && !t.contains(n.target) && ve(t);
          },
          !0,
        );
  }
  function Ee(t) {
    if (t.open) return;
    let e = document.createElement("div");
    (e.id = ae), document.body.appendChild(e), t.showModal(), it();
  }
  function ve(t) {
    if (!t.open) return;
    document.getElementById(ae)?.classList.add(Y), t.classList.add(Y);
  }
  var I = class {
    el;
    app;
    constructor(e) {
      (this.el = e.el), (this.app = e.app);
    }
  };
  var be = document.head.appendChild(document.createElement("style"));
  be.dataset.for = "filters";
  var le = {};
  function we(t) {
    for (let e of t.split(/\s+/)) if (le.hasOwnProperty(e) && !le[e]) return !0;
    return !1;
  }
  var ee = class extends I {
    key;
    value;
    constructor(e) {
      super(e),
        (this.key = `filter-${this.el.name}`),
        (this.value = this.el.checked),
        this.el.addEventListener("change", () => {
          this.setLocalStorage(this.el.checked);
        }),
        this.setLocalStorage(this.fromLocalStorage()),
        (be.innerHTML += `html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; }
`),
        this.app.updateIndexVisibility();
    }
    fromLocalStorage() {
      let e = S.getItem(this.key);
      return e ? e === "true" : this.el.checked;
    }
    setLocalStorage(e) {
      S.setItem(this.key, e.toString()),
        (this.value = e),
        this.handleValueChange();
    }
    handleValueChange() {
      (this.el.checked = this.value),
        document.documentElement.classList.toggle(this.key, this.value),
        (le[`tsd-is-${this.el.name}`] = this.value),
        this.app.filterChanged(),
        this.app.updateIndexVisibility();
    }
  };
  var Le = 0;
  async function Se(t, e) {
    if (!window.searchData) return;
    let n = await R(window.searchData);
    (t.data = n), (t.index = Ie.Index.load(n.index)), (e.innerHTML = "");
  }
  function _e() {
    let t = document.getElementById("tsd-search-trigger"),
      e = document.getElementById("tsd-search"),
      n = document.getElementById("tsd-search-input"),
      r = document.getElementById("tsd-search-results"),
      i = document.getElementById("tsd-search-script"),
      s = document.getElementById("tsd-search-status");
    if (!(t && e && n && r && i && s))
      throw new Error("Search controls missing");
    let o = { base: document.documentElement.dataset.base };
    o.base.endsWith("/") || (o.base += "/"),
      i.addEventListener("error", () => {
        let a = window.translations.search_index_not_available;
        Pe(s, a);
      }),
      i.addEventListener("load", () => {
        Se(o, s);
      }),
      Se(o, s),
      ot({ trigger: t, searchEl: e, results: r, field: n, status: s }, o);
  }
  function ot(t, e) {
    let { field: n, results: r, searchEl: i, status: s, trigger: o } = t;
    xe(i, { closeOnClick: !0 });
    function a() {
      Ee(i), n.setSelectionRange(0, n.value.length);
    }
    o.addEventListener("click", a),
      n.addEventListener(
        "input",
        fe(() => {
          at(r, n, s, e);
        }, 200),
      ),
      n.addEventListener("keydown", (l) => {
        if (r.childElementCount === 0 || l.ctrlKey || l.metaKey || l.altKey)
          return;
        let d = n.getAttribute("aria-activedescendant"),
          f = d ? document.getElementById(d) : null;
        if (f) {
          let p = !1,
            v = !1;
          switch (l.key) {
            case "Home":
            case "End":
            case "ArrowLeft":
            case "ArrowRight":
              v = !0;
              break;
            case "ArrowDown":
            case "ArrowUp":
              p = l.shiftKey;
              break;
          }
          (p || v) && ke(n);
        }
        if (!l.shiftKey)
          switch (l.key) {
            case "Enter":
              f?.querySelector("a")?.click();
              break;
            case "ArrowUp":
              Te(r, n, f, -1), l.preventDefault();
              break;
            case "ArrowDown":
              Te(r, n, f, 1), l.preventDefault();
              break;
          }
      });
    function c() {
      ke(n);
    }
    n.addEventListener("change", c),
      n.addEventListener("blur", c),
      n.addEventListener("click", c),
      document.body.addEventListener("keydown", (l) => {
        if (l.altKey || l.metaKey || l.shiftKey) return;
        let d = l.ctrlKey && l.key === "k",
          f = !l.ctrlKey && !ut() && l.key === "/";
        (d || f) && (l.preventDefault(), a());
      });
  }
  function at(t, e, n, r) {
    if (!r.index || !r.data) return;
    (t.innerHTML = ""), (n.innerHTML = ""), (Le += 1);
    let i = e.value.trim(),
      s;
    if (i) {
      let a = i
        .split(" ")
        .map((c) => (c.length ? `*${c}*` : ""))
        .join(" ");
      s = r.index.search(a).filter(({ ref: c }) => {
        let l = r.data.rows[Number(c)].classes;
        return !l || !we(l);
      });
    } else s = [];
    if (s.length === 0 && i) {
      let a = window.translations.search_no_results_found_for_0.replace(
        "{0}",
        ` "<strong>${te(i)}</strong>" `,
      );
      Pe(n, a);
      return;
    }
    for (let a = 0; a < s.length; a++) {
      let c = s[a],
        l = r.data.rows[Number(c.ref)],
        d = 1;
      l.name.toLowerCase().startsWith(i.toLowerCase()) &&
        (d *= 10 / (1 + Math.abs(l.name.length - i.length))),
        (c.score *= d);
    }
    s.sort((a, c) => c.score - a.score);
    let o = Math.min(10, s.length);
    for (let a = 0; a < o; a++) {
      let c = r.data.rows[Number(s[a].ref)],
        d = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="tsd-kind-icon" aria-label="${window.translations[
          `kind_${c.kind}`
        ].replaceAll('"', "&quot;")}"><use href="#icon-${
          c.icon || c.kind
        }"></use></svg>`,
        f = Ce(c.name, i);
      globalThis.DEBUG_SEARCH_WEIGHTS &&
        (f += ` (score: ${s[a].score.toFixed(2)})`),
        c.parent &&
          (f = `<span class="parent">
                ${Ce(c.parent, i)}.</span>${f}`);
      let p = document.createElement("li");
      (p.id = `tsd-search:${Le}-${a}`),
        (p.role = "option"),
        (p.ariaSelected = "false"),
        (p.classList.value = c.classes ?? "");
      let v = document.createElement("a");
      (v.tabIndex = -1),
        (v.href = r.base + c.url),
        (v.innerHTML = d + `<span class="text">${f}</span>`),
        p.append(v),
        t.appendChild(p);
    }
  }
  function Te(t, e, n, r) {
    let i;
    if (
      (r === 1
        ? (i = n?.nextElementSibling || t.firstElementChild)
        : (i = n?.previousElementSibling || t.lastElementChild),
      i !== n)
    ) {
      if (!i || i.role !== "option") {
        console.error("Option missing");
        return;
      }
      (i.ariaSelected = "true"),
        i.scrollIntoView({ behavior: "smooth", block: "nearest" }),
        e.setAttribute("aria-activedescendant", i.id),
        n?.setAttribute("aria-selected", "false");
    }
  }
  function ke(t) {
    let e = t.getAttribute("aria-activedescendant");
    (e ? document.getElementById(e) : null)?.setAttribute(
      "aria-selected",
      "false",
    ),
      t.setAttribute("aria-activedescendant", "");
  }
  function Ce(t, e) {
    if (e === "") return t;
    let n = t.toLocaleLowerCase(),
      r = e.toLocaleLowerCase(),
      i = [],
      s = 0,
      o = n.indexOf(r);
    for (; o != -1; )
      i.push(
        te(t.substring(s, o)),
        `<mark>${te(t.substring(o, o + r.length))}</mark>`,
      ),
        (s = o + r.length),
        (o = n.indexOf(r, s));
    return i.push(te(t.substring(s))), i.join("");
  }
  var lt = {
    "&": "&amp;",
    "<": "&lt;",
    ">": "&gt;",
    "'": "&#039;",
    '"': "&quot;",
  };
  function te(t) {
    return t.replace(/[&<>"'"]/g, (e) => lt[e]);
  }
  function Pe(t, e) {
    t.innerHTML = e ? `<div>${e}</div>` : "";
  }
  var ct = [
    "button",
    "checkbox",
    "file",
    "hidden",
    "image",
    "radio",
    "range",
    "reset",
    "submit",
  ];
  function ut() {
    let t = document.activeElement;
    return t
      ? t.isContentEditable ||
        t.tagName === "TEXTAREA" ||
        t.tagName === "SEARCH"
        ? !0
        : t.tagName === "INPUT" && !ct.includes(t.type)
      : !1;
  }
  var D = "mousedown",
    Me = "mousemove",
    $ = "mouseup",
    ne = { x: 0, y: 0 },
    Qe = !1,
    ce = !1,
    dt = !1,
    F = !1,
    Oe = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
      navigator.userAgent,
    );
  document.documentElement.classList.add(Oe ? "is-mobile" : "not-mobile");
  Oe &&
    "ontouchstart" in document.documentElement &&
    ((dt = !0), (D = "touchstart"), (Me = "touchmove"), ($ = "touchend"));
  document.addEventListener(D, (t) => {
    (ce = !0), (F = !1);
    let e = D == "touchstart" ? t.targetTouches[0] : t;
    (ne.y = e.pageY || 0), (ne.x = e.pageX || 0);
  });
  document.addEventListener(Me, (t) => {
    if (ce && !F) {
      let e = D == "touchstart" ? t.targetTouches[0] : t,
        n = ne.x - (e.pageX || 0),
        r = ne.y - (e.pageY || 0);
      F = Math.sqrt(n * n + r * r) > 10;
    }
  });
  document.addEventListener($, () => {
    ce = !1;
  });
  document.addEventListener("click", (t) => {
    Qe && (t.preventDefault(), t.stopImmediatePropagation(), (Qe = !1));
  });
  var re = class extends I {
    active;
    className;
    constructor(e) {
      super(e),
        (this.className = this.el.dataset.toggle || ""),
        this.el.addEventListener($, (n) => this.onPointerUp(n)),
        this.el.addEventListener("click", (n) => n.preventDefault()),
        document.addEventListener(D, (n) => this.onDocumentPointerDown(n)),
        document.addEventListener($, (n) => this.onDocumentPointerUp(n));
    }
    setActive(e) {
      if (this.active == e) return;
      (this.active = e),
        document.documentElement.classList.toggle("has-" + this.className, e),
        this.el.classList.toggle("active", e);
      let n = (this.active ? "to-has-" : "from-has-") + this.className;
      document.documentElement.classList.add(n),
        setTimeout(() => document.documentElement.classList.remove(n), 500);
    }
    onPointerUp(e) {
      F || (this.setActive(!0), e.preventDefault());
    }
    onDocumentPointerDown(e) {
      if (this.active) {
        if (e.target.closest(".col-sidebar, .tsd-filter-group")) return;
        this.setActive(!1);
      }
    }
    onDocumentPointerUp(e) {
      if (!F && this.active && e.target.closest(".col-sidebar")) {
        let n = e.target.closest("a");
        if (n) {
          let r = window.location.href;
          r.indexOf("#") != -1 && (r = r.substring(0, r.indexOf("#"))),
            n.href.substring(0, r.length) == r &&
              setTimeout(() => this.setActive(!1), 250);
        }
      }
    }
  };
  var ue = new Map(),
    de = class {
      open;
      accordions = [];
      key;
      constructor(e, n) {
        (this.key = e), (this.open = n);
      }
      add(e) {
        this.accordions.push(e),
          (e.open = this.open),
          e.addEventListener("toggle", () => {
            this.toggle(e.open);
          });
      }
      toggle(e) {
        for (let n of this.accordions) n.open = e;
        S.setItem(this.key, e.toString());
      }
    },
    ie = class extends I {
      constructor(e) {
        super(e);
        let n = this.el.querySelector("summary"),
          r = n.querySelector("a");
        r &&
          r.addEventListener("click", () => {
            location.assign(r.href);
          });
        let i = `tsd-accordion-${
            n.dataset.key ??
            n.textContent.trim().replace(/\s+/g, "-").toLowerCase()
          }`,
          s;
        if (ue.has(i)) s = ue.get(i);
        else {
          let o = S.getItem(i),
            a = o ? o === "true" : this.el.open;
          (s = new de(i, a)), ue.set(i, s);
        }
        s.add(this.el);
      }
    };
  function He(t) {
    let e = S.getItem("tsd-theme") || "os";
    (t.value = e),
      Ae(e),
      t.addEventListener("change", () => {
        S.setItem("tsd-theme", t.value), Ae(t.value);
      });
  }
  function Ae(t) {
    document.documentElement.dataset.theme = t;
  }
  var se;
  function Ne() {
    let t = document.getElementById("tsd-nav-script");
    t && (t.addEventListener("load", Re), Re());
  }
  async function Re() {
    let t = document.getElementById("tsd-nav-container");
    if (!t || !window.navigationData) return;
    let e = await R(window.navigationData);
    (se = document.documentElement.dataset.base),
      se.endsWith("/") || (se += "/"),
      (t.innerHTML = "");
    for (let n of e) Be(n, t, []);
    window.app.createComponents(t),
      window.app.showPage(),
      window.app.ensureActivePageVisible();
  }
  function Be(t, e, n) {
    let r = e.appendChild(document.createElement("li"));
    if (t.children) {
      let i = [...n, t.text],
        s = r.appendChild(document.createElement("details"));
      s.className = t.class ? `${t.class} tsd-accordion` : "tsd-accordion";
      let o = s.appendChild(document.createElement("summary"));
      (o.className = "tsd-accordion-summary"),
        (o.dataset.key = i.join("$")),
        (o.innerHTML =
          '<svg width="20" height="20" viewBox="0 0 24 24" fill="none"><use href="#icon-chevronDown"></use></svg>'),
        De(t, o);
      let a = s.appendChild(document.createElement("div"));
      a.className = "tsd-accordion-details";
      let c = a.appendChild(document.createElement("ul"));
      c.className = "tsd-nested-navigation";
      for (let l of t.children) Be(l, c, i);
    } else De(t, r, t.class);
  }
  function De(t, e, n) {
    if (t.path) {
      let r = e.appendChild(document.createElement("a"));
      if (
        ((r.href = se + t.path),
        n && (r.className = n),
        location.pathname === r.pathname &&
          !r.href.includes("#") &&
          (r.classList.add("current"), (r.ariaCurrent = "page")),
        t.kind)
      ) {
        let i = window.translations[`kind_${t.kind}`].replaceAll('"', "&quot;");
        r.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="tsd-kind-icon" aria-label="${i}"><use href="#icon-${
          t.icon || t.kind
        }"></use></svg>`;
      }
      r.appendChild(Fe(t.text, document.createElement("span")));
    } else {
      let r = e.appendChild(document.createElement("span")),
        i = window.translations.folder.replaceAll('"', "&quot;");
      (r.innerHTML = `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" class="tsd-kind-icon" aria-label="${i}"><use href="#icon-folder"></use></svg>`),
        r.appendChild(Fe(t.text, document.createElement("span")));
    }
  }
  function Fe(t, e) {
    let n = t.split(
      /(?<=[^A-Z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[_-])(?=[^_-])/,
    );
    for (let r = 0; r < n.length; ++r)
      r !== 0 && e.appendChild(document.createElement("wbr")),
        e.appendChild(document.createTextNode(n[r]));
    return e;
  }
  var oe = document.documentElement.dataset.base;
  oe.endsWith("/") || (oe += "/");
  function $e() {
    document.querySelector(".tsd-full-hierarchy")
      ? ht()
      : document.querySelector(".tsd-hierarchy") && pt();
  }
  function ht() {
    document.addEventListener("click", (r) => {
      let i = r.target;
      for (; i.parentElement && i.parentElement.tagName != "LI"; )
        i = i.parentElement;
      i.dataset.dropdown &&
        (i.dataset.dropdown = String(i.dataset.dropdown !== "true"));
    });
    let t = new Map(),
      e = new Set();
    for (let r of document.querySelectorAll(
      ".tsd-full-hierarchy [data-refl]",
    )) {
      let i = r.querySelector("ul");
      t.has(r.dataset.refl)
        ? e.add(r.dataset.refl)
        : i && t.set(r.dataset.refl, i);
    }
    for (let r of e) n(r);
    function n(r) {
      let i = t.get(r).cloneNode(!0);
      i.querySelectorAll("[id]").forEach((s) => {
        s.removeAttribute("id");
      }),
        i.querySelectorAll("[data-dropdown]").forEach((s) => {
          s.dataset.dropdown = "false";
        });
      for (let s of document.querySelectorAll(`[data-refl="${r}"]`)) {
        let o = gt(),
          a = s.querySelector("ul");
        s.insertBefore(o, a),
          (o.dataset.dropdown = String(!!a)),
          a || s.appendChild(i.cloneNode(!0));
      }
    }
  }
  function pt() {
    let t = document.getElementById("tsd-hierarchy-script");
    t && (t.addEventListener("load", Ve), Ve());
  }
  async function Ve() {
    let t = document.querySelector(".tsd-panel.tsd-hierarchy:has(h4 a)");
    if (!t || !window.hierarchyData) return;
    let e = +t.dataset.refl,
      n = await R(window.hierarchyData),
      r = t.querySelector("ul"),
      i = document.createElement("ul");
    if (
      (i.classList.add("tsd-hierarchy"),
      ft(i, n, e),
      r.querySelectorAll("li").length == i.querySelectorAll("li").length)
    )
      return;
    let s = document.createElement("span");
    s.classList.add("tsd-hierarchy-toggle"),
      (s.textContent = window.translations.hierarchy_expand),
      t.querySelector("h4 a")?.insertAdjacentElement("afterend", s),
      s.insertAdjacentText("beforebegin", ", "),
      s.addEventListener("click", () => {
        s.textContent === window.translations.hierarchy_expand
          ? (r.insertAdjacentElement("afterend", i),
            r.remove(),
            (s.textContent = window.translations.hierarchy_collapse))
          : (i.insertAdjacentElement("afterend", r),
            i.remove(),
            (s.textContent = window.translations.hierarchy_expand));
      });
  }
  function ft(t, e, n) {
    let r = e.roots.filter((i) => mt(e, i, n));
    for (let i of r) t.appendChild(je(e, i, n));
  }
  function je(t, e, n, r = new Set()) {
    if (r.has(e)) return;
    r.add(e);
    let i = t.reflections[e],
      s = document.createElement("li");
    if ((s.classList.add("tsd-hierarchy-item"), e === n)) {
      let o = s.appendChild(document.createElement("span"));
      (o.textContent = i.name), o.classList.add("tsd-hierarchy-target");
    } else {
      for (let a of i.uniqueNameParents || []) {
        let c = t.reflections[a],
          l = s.appendChild(document.createElement("a"));
        (l.textContent = c.name),
          (l.href = oe + c.url),
          (l.className = c.class + " tsd-signature-type"),
          s.append(document.createTextNode("."));
      }
      let o = s.appendChild(document.createElement("a"));
      (o.textContent = t.reflections[e].name),
        (o.href = oe + i.url),
        (o.className = i.class + " tsd-signature-type");
    }
    if (i.children) {
      let o = s.appendChild(document.createElement("ul"));
      o.classList.add("tsd-hierarchy");
      for (let a of i.children) {
        let c = je(t, a, n, r);
        c && o.appendChild(c);
      }
    }
    return r.delete(e), s;
  }
  function mt(t, e, n) {
    if (e === n) return !0;
    let r = new Set(),
      i = [t.reflections[e]];
    for (; i.length; ) {
      let s = i.pop();
      if (!r.has(s)) {
        r.add(s);
        for (let o of s.children || []) {
          if (o === n) return !0;
          i.push(t.reflections[o]);
        }
      }
    }
    return !1;
  }
  function gt() {
    let t = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    return (
      t.setAttribute("width", "20"),
      t.setAttribute("height", "20"),
      t.setAttribute("viewBox", "0 0 24 24"),
      t.setAttribute("fill", "none"),
      (t.innerHTML = '<use href="#icon-chevronDown"></use>'),
      t
    );
  }
  X(re, "a[data-toggle]");
  X(ie, ".tsd-accordion");
  X(ee, ".tsd-filter-item input[type=checkbox]");
  var qe = document.getElementById("tsd-theme");
  qe && He(qe);
  var yt = new Z();
  Object.defineProperty(window, "app", { value: yt });
  _e();
  Ne();
  $e();
  "virtualKeyboard" in navigator &&
    (navigator.virtualKeyboard.overlaysContent = !0);
})();
/*! Bundled license information:

lunr/lunr.js:
  (**
   * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9
   * Copyright (C) 2020 Oliver Nightingale
   * @license MIT
   *)
  (*!
   * lunr.utils
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.Set
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.tokenizer
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.Pipeline
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.Vector
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.stemmer
   * Copyright (C) 2020 Oliver Nightingale
   * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt
   *)
  (*!
   * lunr.stopWordFilter
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.trimmer
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.TokenSet
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.Index
   * Copyright (C) 2020 Oliver Nightingale
   *)
  (*!
   * lunr.Builder
   * Copyright (C) 2020 Oliver Nightingale
   *)
*/

```
Page 18/20FirstPrevNextLast