equiv

package
v0.11.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package equiv provides HTML/SEO/AI field comparison utilities for verifying huan output equivalence against Hugo.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NormalizeHTML

func NormalizeHTML(in string) string

NormalizeHTML returns a canonical form of the input HTML, suitable for byte-level comparison of pages that should render identically.

Normalizations applied:

  • Implicit html/head/body wrappers injected by the parser are stripped, so fragment-in == fragment-out and full-document-in == full-document-in.
  • Whitespace between tags is removed (<div>\n <p> → <div><p>)
  • Self-closing tags are canonicalized (<br/> and <br /> → <br/>)
  • Attributes are sorted by name with double-quoted values
  • Boolean attributes are normalized
  • HTML entities in text/attribute values are normalized to Go's html.EscapeString output (numeric character references for `"`, named for `& < > '`). This may differ from Hugo's named-entity usage — track and align if real data shows divergence in Phase 2b.

Types

type AIFields

type AIFields struct {
	MainText string          // innerText of <main> > <article> > <div class="main"> (first non-empty wins)
	Outline  []Heading       // h1-h6 in document order
	JSONLD   []string        // same content as SEOFields.JSONLD
	Semantic map[string]bool // which semantic elements are present
	NavLinks []string        // hrefs inside <nav>
}

AIFields is the set of HTML fields that affect LLM crawler friendliness.

func ExtractAI

func ExtractAI(htmlSrc string) AIFields

ExtractAI parses the HTML and returns AI-friendliness fields.

func (AIFields) Equal

func (a AIFields) Equal(o AIFields) bool

Equal returns true if two AIFields are field-by-field equivalent.

type Heading

type Heading struct {
	Level int
	Text  string
}

Heading is a single h1-h6 entry.

type Link struct {
	Href     string
	Nofollow bool
}

Link captures href + nofollow status for SEO link graph comparison.

type Mode

type Mode string

Mode selects which equivalence check to run.

const (
	ModeByte       Mode = "byte"       // raw cmp (radar, never fails)
	ModeNormalized Mode = "normalized" // HTML normalize then cmp (visual)
	ModeSEO        Mode = "seo"        // SEO field extract then cmp
	ModeAI         Mode = "ai"         // AI field extract then cmp
)

type Report

type Report struct {
	Mode        Mode
	Identical   int
	Differing   []string // relative paths (non-whitelisted)
	Whitelisted []string // relative paths that matched the allowlist
	MissingInA  []string // files only in B
	ExtraInA    []string // files only in A
}

Report is the output of a single mode comparison over a pair of dirs.

func CompareDirs

func CompareDirs(mode Mode, dirA, dirB string, allowlist map[string]bool) (Report, error)

CompareDirs runs the given mode across two parallel directory trees. Files considered: .html / .htm / .xml. allowlist is a set of relative paths that are accepted as permanent differences (not counted as failures).

func (Report) FormatSummary

func (r Report) FormatSummary() string

FormatSummary returns a human-readable summary line.

func (Report) Pass

func (r Report) Pass() bool

Pass returns true if this mode's gate is satisfied. byte mode always passes (radar only); others require zero non-whitelisted differing files AND zero missing/extra files.

type SEOFields

type SEOFields struct {
	Title       string
	Description string
	OG          map[string]string // property -> content
	Twitter     map[string]string // name (twitter:*) -> content
	Canonical   string
	Robots      string
	Headings    []Heading
	JSONLD      []string // normalized (re-marshaled) JSON strings
	Links       []Link   // href + nofollow pairs
}

SEOFields is the set of HTML fields that affect SEO.

func ExtractSEO

func ExtractSEO(htmlSrc string) SEOFields

ExtractSEO parses the HTML and returns normalized SEO fields.

func (SEOFields) Equal

func (s SEOFields) Equal(o SEOFields) bool

Equal returns true if two SEOFields are field-by-field equivalent.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL