Skip to content

feat(html): extract HTML meta, Dublin Core and Office tags - #402

Closed
swackhamer wants to merge 1 commit into
mainfrom
feat/html-metadata-tags
Closed

feat(html): extract HTML meta, Dublin Core and Office tags#402
swackhamer wants to merge 1 commit into
mainfrom
feat/html-metadata-tags

Conversation

@swackhamer

Copy link
Copy Markdown
Collaborator

What

oxidex already named the HTML file type (filetype::tables carries the magic, the htm/html extensions and the text/html MIME type) but had no FileFormat variant, so detection landed .html on the plain-text parser. The result was none of ExifTool's 57 tags, plus five TEXT:* tags ExifTool never reports for an HTML file.

This adds the variant, routes detection through ExifTool's own gate from ProcessHTML, and adds a reader transcribed from Image::ExifTool::HTML (HTML.pm 1.16).

Measured

Per file, keyed Group1:Name, File/System/ExifTool groups excluded, ExifTool 13.55 (HTML.pm is byte-identical to the 13.59 source used as the oracle). ExifTool JSON parsed with parse_float=str.

file matched missing extra
HTML.html before 0 57 5
HTML.html after 57 0 0

The five wrong TEXT:Encoding / TEXT:FileSize / TEXT:LineCount / TEXT:LineEnding / TEXT:WordCount tags are gone, because HTML is no longer treated as plain text.

Four Group1 names

The meta-tag namespace decides the group, exactly as HTML.pm does:

group count source
HTML-dc 9 Dublin Core <meta name="dc.*">
HTML-ncc 20 Daisy NCC
HTML-office 25 Microsoft Office HTML export
HTML 1 the <title> element
HTTP-equiv 1 <meta http-equiv=...>

Conversions that had to be exact or the tag omitted: HTML-dc:Creator is a list (two <meta> tags collapse into one value); the document is iso-8859-1 so HTML-dc:Subject (Greek: α β γ) and HTML-office:Category (a catégory) need charset transcoding driven by the declared encoding; HTML-office:CreateDate converts to ExifTool's colon-date form while HTML-dc:Date stays raw; HTML-office:TotalEditTime is a PrintConv (1 minute).

Zero regressions

This changes how .html/.htm files are dispatched, so the blast radius was measured rather than assumed:

  • DetectionFile:FileType for all 4104 readable corpus files is byte-identical before and after (0 differences).
  • Content — a per-tag dump of the 33 text-adjacent corpus samples (SVG, XMP, XML, TXT, VCF, ICS, EPS, TTF/OTF/dfont/PFA/PFB/AFM, JSON, KML, GPX, RTF) differs on HTML.html alone; every other file is unchanged.
  • Matched-key sets for CanonVRD.vrd, LNK.lnk and Lytro.lfp are unchanged (set comparison, not totals).
  • cargo test --workspace — 0 failed. cargo fmt --all, cargo clippy --all-targets — clean.
  • Corpus proven read-only: 4238-file manifest and SHA-256 of the samples identical before and after.

🤖 Generated with Claude Code

oxidex named the HTML file type but had no FileFormat variant, so detection
landed .html on the plain-text parser. The file produced none of ExifTool's
57 tags and five TEXT:* tags ExifTool never reports for an HTML file.

This adds the variant, routes detection through ExifTool's own gate from
ProcessHTML, and adds a reader transcribed from Image::ExifTool::HTML
(HTML.pm 1.16). Meta-tag namespaces map to the four Group1 names ExifTool
uses: HTML-dc, HTML-ncc, HTML-office, plain HTML for the <title> element,
and HTTP-equiv for http-equiv attributes.

Measured on the ExifTool corpus sample (per file, keyed Group1:Name,
File/System excluded):

  HTML.html   matched 0 -> 57   missing 57 -> 0   extra 5 -> 0

Zero regressions. Detection was re-checked across the whole corpus: the
FileType of all 4104 readable files is byte-identical before and after, and
a per-tag dump of the 33 text-adjacent samples (SVG, XMP, XML, TXT, VCF,
ICS, EPS, TTF/OTF/dfont/PFA/PFB/AFM, JSON, KML, GPX, RTF) differs on
HTML.html alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@swackhamer
swackhamer enabled auto-merge (squash) August 2, 2026 03:35
@swackhamer

Copy link
Copy Markdown
Collaborator Author

Closing in favour of #406, which supersedes this PR.

Both are the same work — I built this branch from a mid-flight snapshot of the HTML parser while its author was still iterating, so #406 is the later state of the same lineage rather than a competing implementation.

Verified before closing:

  • Output is byte-identical. A full -j dump of HTML.html (65 tag lines, FileAccessDate/FileInodeChangeDate excluded) is character-for-character the same from both branches. Both measure 57 MATCHED / 0 VALUE-DIFF / 0 MISSING / 0 EXTRA.
  • Identical file set (6 files), so nothing here is missing there.
  • The 33 deleted lines are supersessions, not losses: attr_content is the same function with its lifetime elided, and the String::from_utf8_lossy charset fallback is replaced by a more correct onefeat(html): extract HTML meta, Dublin Core and Office tags #406 reproduces ExifTool's FixUTF8, which emits one ? per bad byte where from_utf8_lossy collapses a run into a single U+FFFD.

#406 additionally carries two divergences this sample file cannot exercise (AddTagToTable name normalisation, and the FixUTF8 behaviour above) plus test_xml_rooted_formats_keep_their_own_detection, which pins the HTML/SVG/Plist/XMP detection ordering as a unit test — the exact regression risk I had to verify empirically for this branch.

No measured coverage is lost by closing this.

@swackhamer swackhamer closed this Aug 2, 2026
auto-merge was automatically disabled August 2, 2026 03:50

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant