
Research
/Security News
Popular Go Decimal Library Targeted by Long-Running Typosquat with DNS Backdoor
A long-running Go typosquat impersonated the popular shopspring/decimal library and used DNS TXT records to execute commands.
hihtml—“high-quality HTML”—bundles several key HTML tools into one, making HTML validation and semantics control, link checking, and minification as easy as it gets: HTML-validate for validation, ObsoHTML for deprecated markup detection, Node’s built-in http/https for link checking, and HTML Minifier Next for minification. hihtml provides a CLI and a programmatic API, and comes with strong defaults but is still highly configurable.
npm i hihtml
Tip: If you don’t plan to use hihtml programmatically, just run hihtml via npx hihtml!
Without options, hihtml validates HTML files and checks for deprecated markup in the current directory. Use flags to control behavior:
| Flag | Description |
|---|---|
-c, --check-code | Check HTML code: validate and check for deprecated markup (default) |
-l, --check-links | Check all external http/https URLs for broken references |
-m, --minify | Minify HTML files in-place, or to --output |
-a, --all | Check HTML code and links, then minify if there are no validation errors (built-in conformance gate—different from using all individual flags together) |
-i, --input <dir> | Input directory (default: current directory) |
-o, --output <dir> | Output directory for minification |
-s, --settings <file> | Load configuration from a specific JSON file (overrides CWD config lookup) |
-q, --quiet | Suppress output when no issues are found |
-r, --report [file] | Save a JSON report (default: hihtml-report.json) |
-v, --version | Show version number |
-h, --help | Show help |
Check the current directory:
npx hihtml
Check a specific folder:
npx hihtml -c -i path/to/project
Check all external http/https URLs in the current directory:
npx hihtml -l
Check markup and links together:
npx hihtml -c -l
Minify HTML files in-place (prompts for confirmation):
npx hihtml -m
Minify into a separate output directory:
npx hihtml -m -i src -o dist
Check, then minify only if validation passes:
npx hihtml -a
Use a specific settings file:
npx hihtml -s ~/my-hihtml.json
npx hihtml -a -i /path/to/site -s ~/my-hihtml.json
Save a JSON report:
npx hihtml -r
npx hihtml -r results.json
Run quietly (no output when clean, useful in CI):
npx hihtml -q
npx hihtml -q -l
npx hihtml -q -a -i src -o dist
import { checkCode, checkCodeString, checkLinks, checkLinksString, minify, minifyString, collect } from 'hihtml';
const files = await collect('./src');
const checks = await checkCode(files);
// { validation: { files, countErrors, countWarnings, countIgnored }, deprecation: { files, countIssues } }
const links = await checkLinks(files);
// { files: [{ path, links: [{ url, status, ok, skipped?, warning?, error? }], countBroken }], countBroken, countChecked, countSkipped, countFileErrors }
const minification = await minify(files, files); // in-place
// { files: [{ path, sizeOriginal, sizeMinified }], saved }
// String variants—same result types, no file I/O
const minified = await minifyString('<p>Hello world</p>');
const codeGate = await checkCodeString('<p><div>Nope</div></p>');
const linksCleaned = await checkLinksString('<a href=https://example.com/>Example</a>');
collect(dir, extensions?, excludedDirs?)Recursively collects HTML files from dir. Returns Promise<string[]>.
extensions: Set<string> of file extensions without dots (default: html, htm, shtml, shtm)excludedDirs: Set<string> of directory names to skip (default: node_modules, .git)Symlinked files whose target resolves within the scanned root are followed; symlinks pointing outside the root or to directories are skipped.
checkCode(filePaths, options?)Validates HTML files and checks for deprecated markup. Returns Promise<ResultCode> with validation (HTML-validate result) and deprecation (ObsoHTML result) properties.
options.preset: HTML-validate preset name (default: 'standard')options.ignore: List of HTML-validate rule IDs to suppress (default: [])checkCodeString(content, options?)Validates an HTML string and checks for deprecated markup. Returns Promise<ResultCode>—same shape as checkCode. Useful in content-pipeline contexts (Eleventy transforms, middleware, SSR) where HTML is available as a string rather than a file.
options.preset: HTML-validate preset name (default: 'standard')options.ignore: List of HTML-validate rule IDs to suppress (default: [])Note: result.validation.files[0].path and result.deprecation.files[0].path will be '(string input)', not a real file path.
checkLinks(filePaths, options?)Checks all external http/https URLs (href, src, srcset, action attributes) found in the given HTML files. Each unique URL is checked once; results are mapped back to every file it appears in. Returns Promise<ResultLinks>.
options.timeout: Request timeout in milliseconds (default: 10000)options.concurrency: Maximum concurrent requests (default: 8)options.warnOnPermanentRedirects: Warn on 301/308 permanent redirects (default: false)options.ignore: List of hostnames or URL prefixes to skip (default: [])options.onStart: Called once with the total number of URLs to checkoptions.onProgress: Called after each URL is checkedLinks are checked via HEAD request, falling back to GET on 405. 4xx and 5xx responses are reported as broken. Skipped URLs (from the ignore list) appear in results with skipped: true and are never counted as broken.
checkLinksString(content, options?)Checks all external http/https URLs found in an HTML string. Returns Promise<ResultLinks>—same shape as checkLinks. Useful when HTML is available as a string rather than a file, e.g., to check links in a fetched document or API response.
options.timeout: Request timeout in milliseconds (default: 10000)options.concurrency: Maximum concurrent requests (default: 8)options.warnOnPermanentRedirects: Warn on 301/308 permanent redirects (default: false)options.ignore: List of hostnames or URL prefixes to skip (default: [])options.onStart: Called once with the total number of URLs to checkoptions.onProgress: Called after each URL is checkedNote: result.files[0].path will be '(string input)', not a real file path. result.countFileErrors will always be 0.
minify(filePaths, outputPaths, options?)Minifies HTML files using HTML Minifier Next. Returns Promise<ResultMinification>.
outputPaths: Parallel array of output paths; pass the same value as filePaths for in-place minificationoptions.preset: HTML Minifier Next preset name (default: 'comprehensive')options.options: Additional HTML Minifier Next options to merge with the presetminifyString(content, options?)Minifies an HTML string using HTML Minifier Next. Returns Promise<string>. Useful in content-pipeline contexts (Eleventy transforms, middleware, SSR) where HTML is available as a string rather than a file.
options.preset: HTML Minifier Next preset name (default: 'comprehensive')options.options: Additional HTML Minifier Next options to merge with the presetloadConfig(cwd?, filePath?)Loads hihtml configuration. When filePath is given, only that file is read (no CWD fallback); if it contains a "hihtml" key that value is used, otherwise the root object is used. Without filePath, reads .hihtml.json or the "hihtml" key in package.json from cwd. Returns Promise<HihtmlConfig>.
Create a .hihtml.json file in your project root, or add a "hihtml" key to package.json. Both use the same format (here showing hihtml’s defaults):
{
"extensions": ["html", "htm", "shtml", "shtm"],
"ignore": ["node_modules", ".git"],
"validation": {
"preset": "standard",
"ignore": []
},
"links": {
"timeout": 10000,
"concurrency": 8,
"warnOnPermanentRedirects": false,
"ignore": []
},
"minification": {
"preset": "comprehensive"
}
}
.hihtml.json takes precedence over package.json when both are present.
| Code | Meaning |
|---|---|
0 | No issues found (ObsoHTML warnings on deprecated markup are informational) |
1 | Validation errors, broken links, or minification errors found |
2 | Tool or runtime error |
Use the individual flags (-c, -l, -m) instead of --all/-a. Each flag only exits “1” for issues within its own scope, so you control exactly what affects the exit code. To suppress specific HTML-validate rule IDs without disabling validation entirely, use validation.ignore in your configuration. To suppress specific broken links without skipping link checking altogether, use links.ignore.
If in doubt or in a hurry, report issues here. Otherwise, if the issue is related to HTML-validate, report it with HTML-validate. If the issue is related to ObsoHTML, report it with ObsoHTML. For HTML Minifier Next issues, report them with HMN. All projects are monitored and should respond promptly. Thank you!
At the moment, ObsoHTML catches some elements and attributes that HTML-validate doesn’t. Once HTML-validate covers everything ObsoHTML covers, ObsoHTML is going to be removed from hihtml. Note that ObsoHTML is purely informational—it doesn’t prevent minification when used with the --all/-a flag.
You might like some of my other work:
FAQs
The HTML supertool to validate, link-check, and minify web pages
The npm package hihtml receives a total of 542 weekly downloads. As such, hihtml popularity was classified as not popular.
We found that hihtml demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
A long-running Go typosquat impersonated the popular shopspring/decimal library and used DNS TXT records to execute commands.

Research
Active npm supply chain attack compromises @antv packages in a fast-moving malicious publish wave tied to Mini Shai-Hulud.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.