style-to-object

Parses CSS inline style strings into plain JavaScript objects, powering markdown-to-jsx, react-markdown, and dozens of other rendering pipelines.

Library
npm
v2.0.2
77stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
71/100Good
Development Activity96
Maintenance84
Community32
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture65
Code Quality88
Innovation82
Learning Curve55

style-to-object is a single-purpose TypeScript library that converts a CSS inline style string (as found in an HTML style attribute) into a plain JavaScript object of property/value pairs. It builds on the same author’s inline-style-parser for tokenizing declarations, then reduces the parsed declarations into either a flat object or, when an iterator callback is supplied, a per-declaration (and per-comment) stream that callers can use to build any custom output shape.

With tens of millions of weekly downloads, it functions as foundational plumbing for the Markdown/JSX rendering ecosystem — most notably markdown-to-jsx and the react-markdown/rehype/hast toolchain, which use it to turn raw inline style="..." strings from parsed HTML/Markdown into React-compatible style objects. It ships dual ESM and CommonJS builds with full TypeScript declarations and has no runtime dependencies beyond inline-style-parser.

What You Get

  • A single default export, StyleToObject(style, iterator?), with zero configuration required
  • Parses multi-declaration inline style strings into a flat { property: value } object
  • Optional iterator callback ((property, value, declaration) => void) for custom output shapes instead of the default object
  • Iterator mode also surfaces CSS comments as declaration-like nodes, not just property/value pairs
  • Well-defined null vs throw semantics: invalid/empty/non-string input returns null; malformed CSS (e.g. an unterminated comment) throws
  • Dual ESM (esm/) and CommonJS (cjs/) builds with generated .d.ts/.d.mts type declarations and a correct exports map
  • Zero runtime dependencies besides inline-style-parser from the same maintainer

Common Use Cases

  • Converting an HTML element’s inline style="..." attribute into a React-compatible style object when rendering parsed Markdown or HTML (as markdown-to-jsx and react-markdown/rehype plugins do)
  • Building custom CSS-declaration processors via the iterator API — e.g. collecting [property, value] tuples, filtering specific properties, or transforming values before use
  • Normalizing inline styles scraped or extracted from third-party HTML into a serializable JS object for storage, diffing, or SSR hydration
  • Validating or linting inline style strings by relying on the library’s throw-on-malformed-CSS behavior
  • Powering browser-side tools/playgrounds (as shown in the project’s own bundled example) that live-parse a style string typed by a user

Under The Hood

Architecture The entire library is one file (src/index.ts) exporting a single default function, StyleToObject, that delegates CSS tokenizing/parsing to the same author’s inline-style-parser package and then reduces its Declaration[] output into a result: either accumulating into a flat StyleObject record when no iterator is passed, or invoking the caller’s iterator once per declaration (including comment nodes) when one is. There is no internal state, class, or plugin surface — the whole “layer” is a guard clause plus a single forEach with a branch, which is an appropriately minimal design for the library’s narrow, well-defined scope.

Tech Stack Written in TypeScript and built with tsdown (an oxc/Rollup-based bundler) into dual CJS and ESM outputs matching the package.json exports map, with generated .d.ts/.d.mts declaration files for both. The sole runtime dependency is inline-style-parser. Dev tooling includes ESLint 10 with strict, type-checked typescript-eslint configs, Prettier, Husky + lint-staged pre-commit hooks, commitlint with conventional-commit enforcement, Jest 30 with ts-jest for tests, and publint for verifying the package’s export map before publish. CI runs on GitHub Actions with Codecov coverage reporting, and releases are fully automated via Release Please.

Code Quality Tests live in __tests__/index.test.ts (plus a compiled .mjs variant exercised via a dedicated test:esm script) and are driven by shared fixture tables covering valid parses, inputs that must throw, inputs that must return null, and the iterator’s comment-handling path — each behavior is explicitly enumerated rather than left implicit. Error handling is intentionally simple: malformed CSS throws by letting errors from inline-style-parser propagate, while invalid/empty/non-string input is checked upfront and returns null. The codebase is fully typed under strict TypeScript (enforced via a dedicated tsc pre-publish check), and linting/formatting are enforced pre-commit. For its size, the project has thorough, deliberately-documented test coverage and consistent tooling.

API Design The public surface is a single default export taking a style string plus an optional iterator — no config object or setup step. The iterator signature (property, value, declaration) mirrors familiar array-iteration ergonomics, letting callers either take the default flattened object or fully customize the output shape (as the README itself demonstrates by building an array of tuples). Return semantics are deliberately simple and total — invalid input always yields null rather than throwing, and this contract is exhaustively covered by both docs and tests, so consumers can rely on documented behavior rather than probing edge cases themselves. Combined with dual ESM/CJS builds and full type declarations, it’s about as low-friction a DX as a narrowly-scoped utility library can offer.

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