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

@saifulapm/emmet-cli

v1.0.1

Published

Emmet CLI - Powerful command-line interface for Emmet abbreviation expansion

Readme

Emmet CLI

A powerful command-line interface for Emmet abbreviation expansion, powered by the same library that VSCode uses (@vscode/emmet-helper).

Features

  • Full VSCode Emmet Support: All filters (BEM, comment, trim), wrapping, custom snippets, and configuration options
  • 15+ Languages: HTML, CSS, JSX, Vue, SCSS, LESS, Sass, Pug, HAML, Slim, and more
  • Flexible Configuration: Load custom snippets, variables, and syntax profiles from .emmet/ directory
  • Standard I/O: Read from stdin, write to stdout for easy piping and integration
  • Subcommands: expand, wrap, extract, and validate

Installation

# Install globally
npm install -g @saifulapm/emmet-cli

# Or install locally in your project
npm install --save-dev @saifulapm/emmet-cli

Development Setup

# Clone the repository
git clone https://github.com/saifulapm/emmet-cli.git
cd emmet-cli

# Install dependencies
npm install

# Build
npm run build

# Link globally for testing
npm link

Quick Start

# Expand HTML abbreviation
emmet expand "ul>li*3" --syntax html

# From stdin
echo "div.container>p" | emmet expand --syntax html

# CSS abbreviation
emmet expand "m10+p5" --syntax css

# Wrap text with abbreviation
echo "Hello World" | emmet wrap "div.greeting" --syntax html

# Extract abbreviation from text
emmet extract "div.test" --syntax html

Commands

emmet expand [abbreviation]

Expand Emmet abbreviation to code.

Options:

  • -s, --syntax <lang> - Language/syntax (html, css, jsx, etc.)
  • -f, --filter <filters> - Filters: bem, c, t (comma-separated)
  • -c, --config <path> - Custom config directory
  • -i, --indent <chars> - Indentation string (default: tab)
  • -t, --tab-stops - Include tab stops (default: true)
  • -n, --no-tab-stops - Disable tab stops
  • --var-<name>=<value> - Set template variables

Examples:

# Basic expansion
emmet expand "ul>li*3" --syntax html
# Output:
# <ul>
#   <li></li>
#   <li></li>
#   <li></li>
# </ul>

# Without tab stops
emmet expand "div.container>p" --syntax html --no-tab-stops

# CSS abbreviation
emmet expand "m10+p5" --syntax css
# Output: margin: 10px; padding: 5px;

# JSX with custom attributes
emmet expand "button[onClick={handleClick}]" --syntax jsx

# Custom indentation (2 spaces)
emmet expand "ul>li*2" --syntax html --indent "  " --no-tab-stops
# Or using short options:
emmet expand "ul>li*2" -s html -i "  " -n

# Set template variables
emmet expand "!" --syntax html --var-lang=en --var-charset=UTF-8

# Using short options for quick commands
emmet expand "div#app>header.header" -s html -f c -n

emmet wrap <abbreviation>

Wrap text/selection with Emmet abbreviation (text from stdin).

Options:

  • -s, --syntax <lang> - Language/syntax
  • --multi-line - Each line becomes a separate item

Examples:

# Wrap single text
echo "Hello World" | emmet wrap "div.greeting" --syntax html
# Output: <div class="greeting">Hello World</div>

# Wrap multiple lines
echo -e "Item 1\nItem 2\nItem 3" | emmet wrap "ul>li*" --syntax html --multi-line
# Output:
# <ul>
#   <li>Item 1</li>
#   <li>Item 2</li>
#   <li>Item 3</li>
# </ul>

# Wrap with nested structure
echo "Content" | emmet wrap "div.container>article" --syntax html

emmet extract [text]

Extract abbreviation from text (useful for autocomplete).

Examples:

# Extract from text
emmet extract "div.container" --syntax html

# From stdin
echo "ul>li*3" | emmet extract --syntax html

emmet validate <abbreviation>

Validate Emmet abbreviation syntax.

Examples:

# Valid abbreviation
emmet validate "div.container>p*3" --syntax html
# Output: valid

# Invalid abbreviation
emmet validate "div.>>>" --syntax html
# Output: invalid

Supported Languages

Markup Languages

  • html - HTML
  • xml - XML
  • xsl - XSL
  • jsx - React JSX
  • tsx - TypeScript JSX
  • vue - Vue.js templates
  • svelte - Svelte components
  • pug - Pug (Jade)
  • slim - Slim
  • haml - HAML

Stylesheet Languages

  • css - CSS
  • scss - Sass SCSS
  • sass - Sass (indented)
  • less - LESS
  • stylus - Stylus
  • sss - SugarSS

Configuration

The CLI supports loading custom configuration from multiple locations with the following priority (lowest to highest):

  1. Built-in defaults from @vscode/emmet-helper
  2. User home: ~/.emmet/snippets.json + ~/.emmet/syntaxProfiles.json + ~/.emmet/config.json
  3. Project root: .emmet/snippets.json + .emmet/syntaxProfiles.json + .emmet/config.json
  4. Custom path via --config <dir> flag
  5. CLI flags (--var-*, etc.)

Configuration Files Overview

All configuration files live in the .emmet/ directory:

  • snippets.json - Custom snippets and template variables per syntax
  • syntaxProfiles.json - Output formatting per syntax (tag case, quotes, self-closing style)
  • config.json - Advanced preferences (BEM separators, CSS units, comment triggers, etc.)

snippets.json

Define custom snippets and template variables:

{
  "variables": {
    "lang": "en",
    "charset": "UTF-8",
    "author": "Your Name"
  },
  "html": {
    "snippets": {
      "hero": "section.hero>div.container>h1{Hero Title}+p{Hero description}",
      "card": "div.card>img+div.card-body>h3.card-title{Title}+p.card-text{Text}"
    }
  },
  "css": {
    "snippets": {
      "fx": "display: flex;",
      "fxc": "display: flex; align-items: center; justify-content: center;"
    }
  }
}

Usage:

emmet expand "hero" --syntax html
emmet expand "fx" --syntax css

Important: Snippets must be valid Emmet abbreviation syntax (tags, classes, IDs, nesting operators like >, +, ^, etc.). Plain text or code won't work - it will be treated as a tag name.

syntaxProfiles.json

Customize output formatting per syntax:

{
  "html": {
    "tag_case": "lower",
    "attr_case": "lower",
    "attr_quotes": "double",
    "self_closing_tag": "html"
  },
  "jsx": {
    "self_closing_tag": "xhtml"
  }
}

config.json

Advanced preferences and variables:

{
  "variables": {
    "lang": "en",
    "charset": "UTF-8"
  },
  "preferences": {
    "css.intUnit": "rem",
    "css.floatUnit": "rem",
    "bem.elementSeparator": "__",
    "bem.modifierSeparator": "--",
    "profile.allowCompactBoolean": true
  }
}

Available Preferences:

CSS Preferences:

  • css.color.short - Use short color format (#fff vs #ffffff)
  • css.intUnit - Unit for integers (default: "px")
  • css.floatUnit - Unit for floats (default: "em")
  • css.fuzzySearchMinScore - Fuzzy search threshold 0-1 (default: 0.3)
  • css.valueSeparator - Between property and value (default: ": ")
  • css.propertyEnd - After each property (default: ";")

HTML Formatting:

  • format.noIndentTags - Tags to not indent (comma-separated)
  • format.forceIndentationForTags - Force indentation for tags
  • output.inlineBreak - Inline elements before line break (default: 3)
  • output.reverseAttributes - Reverse attribute order
  • output.selfClosingStyle - "html" | "xhtml" | "xml"

Boolean Attributes:

  • profile.allowCompactBoolean - <input disabled> vs <input disabled="disabled">

Comment Filter:

  • Note: Comment filter settings use special defaults from vscode-emmet-helper
  • Only override filter.commentTrigger, filter.commentBefore, filter.commentAfter if you need custom comment templates

BEM:

  • bem.elementSeparator - Element separator (default: "__")
  • bem.modifierSeparator - Modifier separator (default: "_")

Filters

Emmet filters modify the output of abbreviations. Chain multiple filters with |:

BEM Filter (|bem)

Expands BEM (Block Element Modifier) notation:

emmet expand "ul.nav>li.nav__item*2" --syntax html --filter bem

Comment Filter (|c)

Adds HTML comments to elements with ID or class:

emmet expand "div#app>header.header+main.content" --syntax html --filter c

Output:

<div id="app">
  <header class="header"></header>
  <!-- /.header -->
  <main class="content"></main>
  <!-- /.content -->
</div>
<!-- /#app -->

Trim Filter (|t)

Removes extra whitespace:

emmet expand "ul>li*3" --syntax html --filter t

Combined Filters

emmet expand "div.block>div.block__element" --syntax html --filter "bem,c"

Example Workflows

React Component Snippets

Create .emmet/snippets.json:

{
  "jsx": {
    "snippets": {
      "card": "div.card>div.card-header>h3{Title}^div.card-body>p{Content}",
      "modal": "div.modal>div.modal-content>div.modal-header>h2{Modal Title}^div.modal-body>p{Modal content}^div.modal-footer>button{Close}",
      "form": "form>div.form-group>label{Name}+input[type=text name=username]^button[type=submit]{Submit}"
    }
  }
}

Usage:

emmet expand "card" --syntax jsx --no-tab-stops
# Output: <div className="card">...</div>

emmet expand "form" --syntax jsx --no-tab-stops
# Generates complete form structure with JSX syntax

Note: Emmet snippets must use Emmet abbreviation syntax (tags, classes, nesting). They cannot contain arbitrary JavaScript code.

CSS Utility Classes

Create .emmet/snippets.json:

{
  "css": {
    "snippets": {
      "flex-center": "display: flex; align-items: center; justify-content: center;",
      "abs-center": "position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);"
    }
  }
}

Usage:

emmet expand "flex-center" --syntax css

Team Configuration

Commit .emmet/ directory to your repository:

your-project/
├── .emmet/
│   ├── snippets.json       # Team snippets
│   ├── syntaxProfiles.json # Output formatting
│   └── config.json         # Preferences
├── src/
└── package.json

All team members will use the same Emmet configuration!

Environment Variables

  • DEBUG_EMMET=1 - Enable debug logging
DEBUG_EMMET=1 emmet expand "div.test" --syntax html

API Usage

import { expandCommand, wrapCommand, extractCommand, validateCommand } from '@saifulapm/emmet-cli';

// Expand abbreviation
const html = await expandCommand({
  abbreviation: 'div.container>p*3',
  syntax: 'html',
  tabStops: false
});

// Wrap text
const wrapped = await wrapCommand({
  abbreviation: 'div.wrapper',
  text: 'Hello World',
  syntax: 'html'
});

// Extract abbreviation
const result = await extractCommand({
  text: 'div.test',
  syntax: 'html'
});

// Validate abbreviation
const result = await validateCommand({
  abbreviation: 'ul>li*3',
  syntax: 'html'
});

License

MIT

Contributing

Contributions are welcome! Please open an issue or pull request.

Credits

Built with: