diff --git a/CHANGELOG.md b/CHANGELOG.md
index e55fa7a..42ab514 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,20 @@
# check-http-status changelog
+## 2.2.0 - Unreleased
+
+### New
+
+- Crawled pages record the first `h1`, the number of H1s (`h1Count`) and the `metaDescription`
+- Assets record where they came from (`assetType`: `image`, `script`, `stylesheet`, `icon`, `media` or `iframe`)
+- Images record their `alt` texts and `title` attributes, per page and in total, and `missingAlt` when an `` has no `alt` attribute
+- Excel and CSV reports have Asset Type, H1, # H1, Meta Description, Alt Text, Image Title and Missing Alt columns
+- HTML report: filters for images, scripts, stylesheets, missing title, missing or multiple H1, missing meta description and missing alt text
+
+### Fixed
+
+- HTML report: search only looked inside the selected filter (*All issues* by default), so a URL without an issue was never found. Filter counts now follow the search, and a search with no matches in the selected filter offers to show all matches
+- HTML report: search no longer matches every link on a page whose URL contains the search text; it looks in the URL, redirect, title, H1, link text and alt text
+
## 2.1.0 - Oct 2, 2026
### New
diff --git a/README.md b/README.md
index 9492e6a..03dd1a6 100644
--- a/README.md
+++ b/README.md
@@ -238,8 +238,10 @@ await writeReport(report, 'report.xlsx', 'xlsx');
| `error` | Connection error (timeout, DNS, TLS…) if the request failed. |
| `type`, `linkType`, `scope` | `internal`/`external`, `page`/`asset`, and whether it was crawled, excluded, checked or skipped. |
| `redirectTo`, `redirectChain`, `finalUrl`, `finalStatus`, `redirectCount` | Redirect details. `note` is set for loops or too many redirects. |
-| `foundOn` | `[{ page, anchors, count, kind }]`, where `kind` is `link`, `redirect` or `sitemap`. |
-| `title`, `contentType`, `responseTime`, `depth`, `inSitemap`, `orphan` | Page details. |
+| `foundOn` | `[{ page, anchors, count, kind }]`, where `kind` is `link`, `redirect` or `sitemap`. Images also have `alt`, `imageTitle` and `missingAlt` for that page. |
+| `title`, `h1`, `h1Count`, `metaDescription` | Crawled pages: `
`, the first `
` and how many there are, and the meta description. |
+| `assetType`, `alt`, `imageTitle`, `missingAlt` | Assets: `image`, `script`, `stylesheet`, `icon`, `media` or `iframe`. Images: every alt text and `title` used for it, and whether an `` has no `alt` attribute (`alt=""` counts as set). |
+| `contentType`, `responseTime`, `depth`, `inSitemap`, `orphan` | Page details. |
## Config file
diff --git a/index.d.ts b/index.d.ts
index df79f9a..c1684f2 100644
--- a/index.d.ts
+++ b/index.d.ts
@@ -151,6 +151,12 @@ declare namespace checkHttpStatus {
/** Times the link appears on that page. */
count: number;
kind: 'link' | 'redirect' | 'sitemap' | 'seed';
+ /** Images only: `alt` texts used on that page. */
+ alt?: string[];
+ /** Images only: `title` attributes used on that page. */
+ imageTitle?: string[];
+ /** Images only: `` tags on that page without an `alt` attribute. */
+ missingAlt?: number;
}
interface RedirectHop {
@@ -167,6 +173,8 @@ declare namespace checkHttpStatus {
error: string;
type: 'internal' | 'external';
linkType: 'page' | 'asset';
+ /** Assets only: the tag it was found in. */
+ assetType: '' | 'image' | 'script' | 'stylesheet' | 'icon' | 'media' | 'iframe';
scope: Scope;
redirectTo: string;
redirectChain: RedirectHop[];
@@ -179,6 +187,15 @@ declare namespace checkHttpStatus {
note: string;
foundOn: FoundOn[];
title: string;
+ /** Crawled pages: first `
';
+ var empty = 'No URLs match this filter.';
+ // The search found URLs, just not under the selected filter.
+ if (state.query && state.filter !== 'all' && pool.length) {
+ empty = 'No matches in this filter. ';
+ }
+ $('tbody').innerHTML = slice.length ? slice.map(rowHtml).join('') : '