Skip to content

foman/TagChecker

Repository files navigation

TagChecker

A .NET library for validating HTML tag structure and reporting parse errors with line/column positions.

Supported target frameworks: net8.0, net9.0, net10.0.

Features

  • Validates start/end tag matching and nesting order
  • Detects missing start or end tags
  • Parses attributes and detects malformed attribute syntax
  • Handles HTML comments (<!-- ... -->) and DOCTYPE (<!DOCTYPE ...>)
  • Handles raw-content tags (<script>, <style>) without false parsing on < inside content
  • Validates HTML void-element rules with strict behavior
  • Returns structured error details (ErrorCode, LineNumber, Position)

Clone, Build, and Test

git clone https://github.com/foman/TagChecker.git
cd TagChecker
dotnet restore TagChecker.sln
dotnet build TagChecker.sln -c Release
dotnet test TagChecker.sln -c Release

Install from NuGet

dotnet add package TagChecker

Or in .csproj:

<ItemGroup>
  <PackageReference Include="TagChecker" Version="1.0.0" />
</ItemGroup>

Quick Start

using TagChecker;

var html = "<html><body><div class='x'>Hello</div></body></html>";
var (ok, error) = HtmlTagChecker.Validate(html);

if (ok)
{
    Console.WriteLine("HTML is valid");
}
else
{
    Console.WriteLine($"Error: {error.ErrorCode} at line {error.LineNumber}, col {error.Position}");
}

API

HtmlTagChecker.Validate(string content, ParserOptions? options = null)

Returns:

(bool succeed, TagError tagError)
  • succeed: true when validation passes
  • tagError: null on success; populated on failure

ParserOptions

new ParserOptions
{
    TagNamePatternStrict = true
}
  • TagNamePatternStrict = false (default): compatibility mode
  • TagNamePatternStrict = true: enforces strict tag-name pattern:
    • first character must be a letter (A-Z / a-z)
    • remaining characters can be letters, digits, or hyphen (-)

Behavior Notes

Void elements

TagChecker currently uses strict void-element behavior:

  • <img /> is valid
  • <img> triggers VoidElementNotSelfClosed (strict XML-like rule)
  • </img> triggers VoidElementClosed

Void-element set: area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr

Script/style content

For <script> and <style>, content is treated as raw text until matching closing tags. This avoids incorrect parsing when the content contains < characters.

Error Codes

  • TagNotClosed: Missing closing > for a tag
  • NoStartTagFound: Closing tag has no matching opener
  • NoEndTagFound: Opening tag has no matching closer
  • InvalidTag: Invalid tag structure
  • InvalidTagName: Invalid tag name
  • InValidCloseTag: Invalid closing tag format
  • InvalidAttribute: Invalid attribute syntax
  • InvalidAttributeName: Invalid attribute name
  • AttributeNotClosed: Attribute value quote not closed
  • VoidElementClosed: Void element incorrectly closed using </...>
  • VoidElementNotSelfClosed: Void element not self-closed

Examples

Success

var (ok, err) = HtmlTagChecker.Validate("<div><span>Hello</span></div>");
// ok == true
// err == null

Missing end tag

var (ok, err) = HtmlTagChecker.Validate("<div><span>Hello</div>");
// ok == false
// err.ErrorCode == HtmlParseErrorCode.NoStartTagFound (mismatched close)

Strict tag-name validation

var options = new ParserOptions { TagNamePatternStrict = true };
var (ok, err) = HtmlTagChecker.Validate("<1bad></1bad>", options);
// ok == false
// err.ErrorCode == HtmlParseErrorCode.InvalidTagName

Publish to NuGet (lightweight script)

Use the lightweight helper script:

# Dry run (test + pack only)
./scripts/nuget-publish.sh --version 0.2.0 --dry-run

# Real publish
NUGET_API_KEY=*** ./scripts/nuget-publish.sh --version 0.2.0

Optional flags:

  • --skip-tests: skip unit tests before packing
  • --source <url>: custom NuGet source

Publish via GitHub Release (GitHub Actions)

publish.yaml is configured to publish when a GitHub Release is published.

  • Trigger: release.published
  • Version source: release tag (e.g. v0.2.0 -> package version 0.2.0)
  • Required secret: NUGET_API_KEY

Quick flow:

  1. Push tag, e.g. v0.2.0
  2. Create a GitHub Release for that tag
  3. GitHub Actions runs build/test/pack/publish automatically

Roadmap (next)

  • Add parser modes: strict (current) vs lenient HTML5 void-element behavior
  • Improve diagnostics with source snippets around error locations
  • Add performance benchmarks for large files and deep nesting

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages