npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

zemdomu

v1.3.18

Published

Semantic HTML linter for HTML, JSX, TSX, and Vue templates. Detects accessibility, SEO, and structure issues before deployment.

Readme

ZemDomu Core

Semantic HTML linting engine for clean, accessible, and SEO-friendly markup. This package provides the shared core logic used by the ZemDomu VS Code extension and the GitHub Action.

What it is

ZemDomu is a semantic-first linter that helps developers write better HTML and JSX by catching accessibility and structural issues. It parses .html, .jsx, .tsx, and .vue files and exposes a simple lint() function that returns semantic violations.

Features

  • Lint semantic issues in HTML, JSX, TSX, and Vue templates.
  • Works in Node.js, CI, or any JS runtime.
  • Extensible rule system with simple custom rules.
  • Cross-component analysis for React/JSX and Vue projects.
  • Command line interface with --custom and --cross.
  • Configurable rule severity (error, warning, off).
  • Performance diagnostics for profiling lint runs.
  • Shared by the extension and GitHub Action.
  • Simple API: lint(content, options).

Why ZemDomu vs alternatives

Compared with generic linters and scanner-only workflows, ZemDomu is designed to keep semantic analysis practical in real component codebases:

  • Cross-component analysis catches issues that only appear when components are composed.
  • One shared rules engine powers VS Code, CLI, and GitHub Action for consistent results.
  • Diagnostics focus on semantic HTML and accessible naming, not broad style noise.
  • Custom-rule support lets teams extend checks without rebuilding a lint stack.

Installation

npm install zemdomu
# or
yarn add zemdomu

Usage

import { lint } from "zemdomu";

const html = "<img>";
const results = lint(html, { rules: { requireAltText: true } });

console.log(results);
// [
//   {
//     line: 0,
//     column: 0,
//     message: '<img> tag missing alt attribute',
//     rule: 'requireAltText'
//   }
// ]

// Custom rules can be supplied via the `customRules` option
// const myRule = { name: 'demo', test: node => false, message: 'demo' };
// lint(html, { customRules: [myRule] });

API

lint(content: string, options?: LinterOptions): LintResult[]

Parameters

  • content: HTML, JSX, TSX, or Vue template string input.
  • options.rules: severity settings for built-in rules.
  • options.customRules: array of additional rules.
  • options.filePath: optional source file path.
  • options.perf: attach a PerformanceRecorder instance.

Example LinterOptions

interface LinterOptions {
  rules?: Record<string, "error" | "warning" | "off">;
  customRules?: Rule[];
  filePath?: string;
  forceHtml?: boolean;
  perf?: PerformanceRecorder;
}

Example enabling one rule as a warning:

const results = lint(html, {
  rules: { requireAltText: "warning", uniqueIds: "error" }
});

Example LintResult

interface LintResult {
  line: number;
  column: number;
  message: string;
  rule: string;
}

CLI usage

Run the linter from the command line by installing the package globally or using npx. Provide one or more glob patterns to specify the files to lint. Patterns may be separated by spaces, commas, or newlines:

npx zemdomu "src/**/*.{html,jsx,tsx,vue}" --custom my-rule.js
npx zemdomu "src/**/*.html,src/**/*.jsx"

Use --custom (or -c) to provide a path to a JavaScript or TypeScript module exporting a custom rule or array of rules. For safety, the CLI only accepts files inside a ./custom-rules directory (relative to your current working directory). You can repeat --custom to load multiple rule files. Use --cross to enable cross component analysis.

Use --perf to emit a JSON timing report to stdout, and --perf-slowest to also print the slowest file and phase.

Cross-component analysis

When analyzing JSX or Vue projects you can track <h1> usage or similar patterns across component boundaries. Instantiate ProjectLinter with the crossComponentAnalysis option or pass --cross to the CLI. Use crossComponentDepth (or --cross-depth) to limit how deep component trees are traversed during analysis:

import { ProjectLinter } from "zemdomu";
const linter = new ProjectLinter({
  crossComponentAnalysis: true,
  crossComponentDepth: 2
});
await linter.lintFile("App.jsx");
npx zemdomu "src/**/*.{jsx,tsx,vue}" --cross --cross-depth 2

Performance diagnostics

Attach a PerformanceDiagnostics recorder to gather timing information for each file and rule:

import { lint, PerformanceDiagnostics } from "zemdomu";
const perf = new PerformanceDiagnostics();
lint(code, { perf });
console.log(perf.getAsJSON());

Writing custom rules

Custom rules are simple objects implementing the Rule interface. At minimum provide a name, a test function that returns true when a node violates the rule, and a message describing the problem:

interface Rule {
  name: string;
  test(node: any): boolean;
  message: string;
}
// my-rule.js
module.exports = {
  name: "noFooDiv",
  test: node => node.type === "element" && node.tagName === "foo",
  message: "<foo> is not allowed"
};

Use it programmatically:

import { lint } from "zemdomu";
const results = lint("<foo></foo>", { customRules: [require("./my-rule")] });

Helper utilities

For more advanced rules you may need direct access to the parsed HTML or JSX AST. ZemDomu exposes a few helpers to make this easier:

import {
  parseHtml,
  visitHtml,
  getAttr,
  getJsxAttr,
  getJsxAttribute,
  getJsxAttributeState,
  getJsxExpressionState,
  getTag,
  isJsxExpressionPossiblyEmpty,
  ElementNode,
  HtmlVisitor,
} from "zemdomu";

parseHtml returns the root ElementNode. The visitHtml function performs a simple depth-first traversal using an HtmlVisitor with optional enter and exit callbacks. Utility functions like getAttr and getJsxAttr help reading attributes. JSX helpers like getJsxAttribute, getJsxAttributeState, and getJsxExpressionState help interpret JSX attributes and expressions, while getTag resolves JSX element names.

Or via the CLI:

mkdir -p custom-rules
cp my-rule.js custom-rules/my-rule.js
npx zemdomu file.html --custom custom-rules/my-rule.js
npx zemdomu "src/**/*.{html,jsx,tsx,vue}" --perf --perf-slowest

There is a sample rule in custom-rules/example-rule.js you can copy and edit.

Local development (monorepo)

From the core package:

cd packages/ZemDomu-Core
npm install
npm run build

Links

  • NPM package: https://www.npmjs.com/package/zemdomu
  • Website: https://zemdomu.dev/
  • Issues and suggestions: https://github.com/Zemdomu/ZemDomu-core/issues
  • VS Code extension: https://marketplace.visualstudio.com/items?itemName=ZachariasErydBerlin.zemdomu
  • GitHub Action: https://github.com/Zemdomu/ZemDomu-action

License

MIT (c) 2025 Zacharias Eryd Berlin