hast-util-has-property

A tiny hast utility that checks whether an element node owns a given property, safely excluding inherited and falsy values.

Library
npm
v3.0.0
1stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
22/100Needs Attention
Development Activity0
Maintenance20
Community8
Maturity60
Momentum0

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
62/100Good
Architecture75
Code Quality85
Innovation32
Learning Curve55

hast-util-has-property is a minimal, single-purpose utility from the unified collective’s syntax-tree family of packages. It exports one function, hasProperty, which determines whether a given hast node is an element that safely owns a particular property — using Object.prototype.hasOwnProperty under the hood to avoid false positives from inherited properties such as toString or valueOf. It further treats null, undefined, and false property values as absent, so consumers get an accurate boolean signal about whether an attribute is meaningfully set.

This package is typically pulled in as a small building block by rehype plugins, other hast-util-* utilities, and tools that need to branch on the presence of specific HTML attributes (id, className, hidden, and similar) while walking or transforming a hast syntax tree. Its narrow scope, zero runtime dependencies beyond typings, and fully typed, type-narrowing return signature make it a safe primitive for larger AST-processing pipelines in the unified/remark/rehype ecosystem.

What You Get

  • A type-narrowing hasProperty(node, name) function usable directly in TypeScript without extra casts
  • Own-property checking via Object.prototype.hasOwnProperty.call, guarding against inherited properties like toString or valueOf
  • Treats null, undefined, and false as “not present” so boolean checks reflect meaningful attribute state, not just key existence
  • Zero runtime dependencies beyond @types/hast for typings, keeping the utility tree-shakeable and lightweight

Common Use Cases

  • Checking if an element has an id, className, or hidden attribute before applying a transform in a rehype plugin
  • Filtering or selecting nodes while traversing a hast tree based on attribute presence
  • Building higher-level hast utilities (sanitizers, minifiers, linters) that need a reliable “does this attribute exist” check
  • Writing unit tests for hast-based tooling that must distinguish “attribute absent” from “attribute falsy”

Under The Hood

Architecture The package is deliberately flat: index.js re-exports the single implementation in lib/index.js, which defines one pure function, hasProperty(node, name). There are no internal layers, classes, or state — the function short-circuits on node.type === 'element', then calls Object.prototype.hasOwnProperty.call(node.properties, name), then filters out null/undefined/false values, returning a plain boolean. Because it is stateless and side-effect-free (sideEffects: false in package.json), it composes cleanly inside larger hast-walking pipelines (e.g. unist-util-visit) without any risk of mutating the tree it inspects.

Tech Stack The package ships as ESM-only (type: module, single exports: ./index.js entry) for Node.js 16+, with JSDoc-based TypeScript types compiled via tsc --build into a .d.ts file rather than hand-written .ts sources. Its only runtime dependency is @types/hast (for the Nodes/Element type definitions); there is no bundler or transpiler step beyond tsc. Dev tooling includes xo (an ESLint preset) and prettier for formatting, remark-cli + remark-preset-wooorm for linting the markdown README, tsd and type-coverage for type-level testing, and c8 for coverage — all wired through npm scripts (build, format, test-coverage) rather than a dedicated CI config file in this repo (CI badges point to a GitHub Actions workflow inherited from the syntax-tree org template).

Code Quality Tests live in a single test.js using Node’s built-in node:test runner and node:assert/strict, covering four cases: no-element input, prototype-inherited properties (toString), a genuinely missing property, and a present property. type-coverage is configured with atLeast: 100 and strict: true, and c8 --100 enforces full statement/branch coverage on test-coverage, so despite its small size the package holds itself to a strict typed-and-tested bar. Naming is consistent with the rest of the syntax-tree/hast-util-* family, and JSDoc comments fully document parameters, return types, and edge-case behavior.

What Makes It Unique The implementation itself is a standard, well-known JavaScript pattern (own-property check via hasOwnProperty) — there is nothing algorithmically novel here. Its value instead comes from being the canonical, single source of truth for this specific check across a large ecosystem of downstream hast-util-* and rehype-* packages maintained by the unified collective, so every consumer gets identical, well-tested semantics (including the null/undefined/false handling) instead of each reimplementing a subtly different version.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search