GitHub - grigorii-horos/cli-html: Render HTML to Terminal · GitHub
Skip to content

grigorii-horos/cli-html

Repository files navigation

Welcome to cli-html

npm version Downloads Node.js Documentation Maintenance License: GPL-3.0

Renderer HTML and Markdown in the Terminal. Supports pretty tables, syntax highlighting, and GitHub Flavored Markdown

Features

  • 🎨 Full HTML rendering — headings, lists, tables, forms, figures, and 80+ tags
  • 📝 GitHub Flavored Markdown — alerts, task lists, tables, footnotes, strikethrough, and more
  • ⚛️ JSX / React — render React elements straight to the terminal
  • 🌈 Syntax highlighting — automatic, for dozens of languages
  • 📐 Pretty tables — borders, alignment, zebra striping, responsive narrow-terminal mode
  • 🎭 Deep theming — every element themeable via config.yaml, a theme object, or per-element data-cli-* attributes
  • 🔌 CLI + library — use the html / markdown / md / jsx commands, or import renderHTML / renderMarkdown / renderJSX
  • ⌨️ Reads stdin — pipe HTML or Markdown straight in (echo '<h1>hi</h1>' | html)
Table of Contents

Install

Requires Node.js >= 18.

npm i -g cli-html

Example

HTML Rendering

# Render a full HTML document
html examples/html/full/demo.html

# Render individual tag examples
html examples/html/tags/table.html

# Pipe HTML from stdin
echo '<h1>Hello</h1><p>from <code>stdin</code></p>' | html
curl -s https://example.com | html

This will produce the following:

Screenshot of cli-html

Markdown Rendering

Render Markdown files with full GitHub Flavored Markdown support:

# Render GFM alerts
markdown examples/markdown/features/alerts.md

# Render full GFM document
md examples/markdown/full/gfm-features.md

# Pipe Markdown from stdin
echo '# Title\n\n> [!NOTE]\n> Piped markdown' | md
cat CHANGELOG.md | md

Supported GFM Features:

  • Alerts - [!NOTE], [!TIP], [!IMPORTANT], [!WARNING], [!CAUTION] with colors
  • Task Lists - - [x] and - [ ] with checkboxes
  • Tables - Full table support with borders
  • Strikethrough - ~~text~~
  • Autolinks - Automatic URL linking
  • Footnotes - [^1] references
  • Definition Lists - Term and definition pairs
  • Subscript/Superscript - H~2~O and x^2^
  • Insert/Mark - ++inserted++ and ==marked== text
  • Abbreviations - *[HTML]: Hyper Text Markup Language

JSX Rendering

Render React/JSX files straight to the terminal. JSX is transpiled, rendered to HTML via react-dom, then drawn by the same renderer used for HTML and Markdown:

# Render a JSX file
jsx examples/jsx/full/demo.jsx

# With a custom theme config
jsx examples/jsx/full/demo.jsx --config ./theme.yaml

The file's default export may be a React element (export default <App />) or a component (export default App). Neighbouring modules resolve relative to the file; react / react-dom are provided by cli-html itself.

More examples (components, data-driven tables, dashboards, boxed layouts) live in examples/jsx.

Usage as module

npm i cli-html

Library Examples

For practical, runnable examples of using cli-html and cli-markdown as libraries, check out the examples/library-usage directory:

Run any example:

node examples/library-usage/<example-name>.js

See the Library Examples README for detailed documentation.

API Reference

renderHTML(html, theme?)

Renders HTML content to formatted terminal output.

Parameters:

  • html (string) - HTML content to render
  • theme (object, optional) - Custom theme configuration (see Customizing Styles)

Returns: string - Formatted terminal output

Example:

import { renderHTML } from 'cli-html';

const html = `
<h1>Hello World</h1>
<p>This is a <strong>bold</strong> paragraph with <code>code</code>.</p>
<ul>
  <li>Item 1</li>
  <li>Item 2</li>
</ul>
`;

console.log(renderHTML(html));

With custom theme:

import { renderHTML } from 'cli-html';

const customTheme = {
  h1: "magenta bold",
  code: { inline: "bgBlack yellow" }
};

const html = '<h1>Styled Title</h1>';
console.log(renderHTML(html, customTheme));

renderMarkdown(markdown, theme?)

Renders Markdown content to formatted terminal output with full GitHub Flavored Markdown support.

Parameters:

  • markdown (string) - Markdown content to render
  • theme (object, optional) - Custom theme configuration (see Customizing Styles)

Returns: string - Formatted terminal output

Example:

import { renderMarkdown } from 'cli-html';

const markdown = `
# Hello World

> [!NOTE]
> This is a note with **bold** text

- [x] Task 1
- [ ] Task 2

## Code Example

\`\`\`javascript
function greet(name) {
  return \`Hello, \${name}!\`;
}
\`\`\`
`;

console.log(renderMarkdown(markdown));

With custom theme:

import { renderMarkdown } from 'cli-html';

const customTheme = {
  h1: "cyan bold",
  h2: "blue bold",
  code: {
    color: "yellowBright",
    inline: "bgBlack yellow"
  }
};

const markdown = '# Title\n\nParagraph with `code`.';
console.log(renderMarkdown(markdown, customTheme));

renderJSX(jsx, theme?)

Renders a React/JSX element or component to formatted terminal output.

react and react-dom are loaded lazily, so importing cli-html for plain HTML/Markdown rendering never pays for them.

Parameters:

  • jsx (React element | component) - e.g. <App /> or App
  • theme (object, optional) - Custom theme configuration (see Customizing Styles)

Returns: Promise<string> - Formatted terminal output (async)

Example:

import { renderJSX } from 'cli-html';

const App = () => (
  <>
    <h1>Hello from JSX</h1>
    <p>Rendered with <strong>cli-html</strong></p>
  </>
);

console.log(await renderJSX(<App />));

Default Export: cliHtml(html, theme?)

Alias for renderHTML(). Use this for backward compatibility or shorter imports.

import cliHtml from 'cli-html';

const html = '<h1>Hello World</h1>';
console.log(cliHtml(html));

Common Use Cases

Reading HTML from file:

import { renderHTML } from 'cli-html';
import { readFileSync } from 'fs';

const html = readFileSync('document.html', 'utf8');
console.log(renderHTML(html));

Reading Markdown from file:

import { renderMarkdown } from 'cli-html';
import { readFileSync } from 'fs';

const markdown = readFileSync('README.md', 'utf8');
console.log(renderMarkdown(markdown));

Rendering dynamic content:

import { renderHTML } from 'cli-html';

const data = {
  title: 'User Report',
  items: ['Item 1', 'Item 2', 'Item 3']
};

const html = `
<h1>${data.title}</h1>
<ul>
  ${data.items.map(item => `<li>${item}</li>`).join('\n')}
</ul>
`;

console.log(renderHTML(html));

Converting Markdown to HTML then to Terminal:

import { renderMarkdown } from 'cli-html';

// renderMarkdown handles the conversion internally
const markdown = '# Title\n\n**Bold** and *italic*';
console.log(renderMarkdown(markdown));

Inline Style Customization

You can customize individual elements using data-cli-* attributes without modifying the global theme.

Using data-cli-* Attributes

<!-- Custom color and styles in a single attribute -->
<h1 data-cli-color="magenta bold">Magenta Bold Header</h1>
<h2 data-cli-color="cyan underline italic">Cyan Underlined Italic Header</h2>

<!-- Custom markers for headers -->
<h1 data-cli-marker="">Triangle Marker</h1>
<h2 data-cli-marker="•••">Triple Dot Marker</h2>

<!-- Combined attributes -->
<h1 data-cli-color="red bold"
    data-cli-marker="">
  Warning Header
</h1>

<!-- Background colors -->
<span data-cli-color="bgRed white bold">White bold on red</span>

<!-- Lists customization -->
<ol data-cli-color="green" data-cli-marker-color="red bold" data-cli-decimal=")">
  <li>Item with green text and red bold marker with ) separator</li>
  <li>Another item</li>
</ol>

<ul data-cli-color="yellow" data-cli-marker="" data-cli-marker-color="cyan">
  <li>Item with yellow text and cyan star marker</li>
  <li>Another item</li>
</ul>

Available Attributes:

  • data-cli-color: Full chalk-string specification (color + styles), e.g., "red bold italic", "bgBlue white"
    • For ol/ul: applies to list item text
  • data-cli-marker: Custom marker symbol
    • For headers/blockquotes: e.g., "►", "▌ ", "•••"
    • For ul: custom bullet marker, e.g., "★", "►", "•"
  • data-cli-marker-color: Marker color (for ol/ul), e.g., "red bold", "cyan"
  • data-cli-decimal: Decimal separator for ol, e.g., ")", ":", "-"
  • data-cli-title-* (abbr/dfn):
    • data-cli-title-color: Title color
    • data-cli-title-prefix-marker / data-cli-title-prefix-color: Opening marker + color
    • data-cli-title-suffix-marker / data-cli-title-suffix-color: Closing marker + color

Available Colors:

  • Basic: black, red, green, yellow, blue, magenta, cyan, white, gray
  • Bright: redBright, greenBright, yellowBright, blueBright, magentaBright, cyanBright, whiteBright
  • Background: bgRed, bgGreen, bgBlue, bgYellow, bgMagenta, bgCyan, bgWhite, etc.

Available Styles:

  • bold, italic, underline, dim, inverse, strikethrough

Examples:

  • Color only: data-cli-color="red"
  • Color + style: data-cli-color="blue bold"
  • Multiple styles: data-cli-color="green bold italic underline"
  • Background: data-cli-color="bgYellow black"
  • Background + styles: data-cli-color="bgMagenta white bold"

Supported Tags:

  • Headers (color, marker): h1, h2, h3, h4, h5, h6
  • Block (color, marker): blockquote
  • Lists (color for text, marker-color, marker, decimal): ol, ul
  • Inline (color): span, strong, b, em, i, u, del, ins, mark, code, kbd, samp, var, cite, time

See examples/html/tags-custom/ for complete examples with data-cli-* attributes.

📚 Documentation

Comprehensive documentation is available in the examples/ directory:

Customizing Styles

Every element's default style lives in config.yaml — the single source of truth. Override it three ways, in increasing precedence:

  1. Globally — a config.yaml in the config directory, or an explicit file via --config (CLI)
  2. Per render — a theme object passed to renderHTML() / renderMarkdown() / renderJSX() (library)
  3. Per elementdata-cli-* attributes on individual tags (see Inline Style Customization)

Full reference:

For CLI Usage

Each command loads config.yaml defaults, then merges your overrides from a per-command config directory:

Command Linux macOS Windows
html ~/.config/cli-html/config.yaml ~/Library/Preferences/cli-html/config.yaml %LOCALAPPDATA%\cli-html\Config\config.yaml
markdown / md ~/.config/cli-markdown/config.yaml ~/Library/Preferences/cli-markdown/config.yaml %LOCALAPPDATA%\cli-markdown\Config\config.yaml

Print the exact path for a command:

# html
node -e "import('env-paths').then(({default:e})=>console.log(e('cli-html',{suffix:''}).config))"
# markdown / md
node -e "import('env-paths').then(({default:e})=>console.log(e('cli-markdown',{suffix:''}).config))"

--config <path>

To load a specific config file instead of the one in the config directory, pass --config. Supported by every command (html, markdown, md, jsx) and works with stdin too:

html demo.html --config ./theme.yaml
md README.md --config ./theme.yaml
jsx demo.jsx --config ./theme.yaml

# with stdin
cat page.html | html --config ./theme.yaml

Values are chalk-string compatible ("red bold", "bgBlue white underline"). Example config.yaml:

theme:
  h1: "magenta bold"
  a: "cyan underline"
  blockquote: "gray italic"
  code:
    color: "yellowBright bgBlack"   # inline code
    block:
      numbers:
        color: "blackBright dim"    # line numbers in code blocks
  th: "red bold"                    # table header cells
  td: ""                            # table data cells
  caption: "blue bold"              # table caption
  var: "blue italic"
  mark: "bgYellow black"
  hr: "gray"
  progress:
    filled: { color: "bgWhite cyan", marker: "█" }
    empty:  { color: "bgBlack gray", marker: "░" }

See THEMES.md for the complete key list (headings, lists, borders, forms, and more).

For Library Usage

Pass a theme object as the second argument to any renderer. It uses the same keys as config.yaml:

import { renderHTML, renderMarkdown } from 'cli-html';

const theme = {
  h1: "magenta bold",
  a: "blue underline",
  blockquote: "gray italic",
  code: { color: "yellowBright bgBlack" },
  th: "red bold",
  td: "",
  caption: "blue bold",
  ul: {
    indicators: {
      disc:   { color: "green",  marker: "•" },
      square: { color: "yellow", marker: "▪" },
      circle: { color: "cyan",   marker: "◦" },
    },
  },
  progress: {
    filled: { color: "bgWhite cyan", marker: "█" },
    empty:  { color: "bgBlack gray", marker: "░" },
  },
};

console.log(renderHTML('<h1>Hello</h1><p>This is <code>inline code</code></p>', theme));
console.log(renderMarkdown('# Hello\n\nThis is `inline code`', theme));

Omit the theme argument to use the defaults from config.yaml. For the full set of keys, see THEMES.md.

Syntax Highlighting

Code blocks support automatic syntax highlighting using cli-highlight. To enable syntax highlighting for a code block, add a language-* or lang-* class to the <code> element:

<pre><code class="language-javascript">
function hello() {
  console.log("Hello, World!");
  return true;
}
</code></pre>

Supported languages include: javascript, typescript, python, java, sql, bash, json, yaml, nginx, go, rust, and many more.

Example:

<!-- JavaScript -->
<pre><code class="language-javascript">
const user = await User.findById(id);
</code></pre>

<!-- Python -->
<pre><code class="language-python">
def hello():
    print("Hello, World!")
</code></pre>

<!-- SQL -->
<pre><code class="language-sql">
SELECT * FROM users WHERE email = 'user@example.com';
</code></pre>

<!-- Bash -->
<pre><code class="language-bash">
npm install express
</code></pre>

Code blocks without a language class will still be displayed but without syntax highlighting.

See the comprehensive examples in examples/html/full/documentation.html, examples/html/full/blog.html, and examples/html/full/tutorial.html for more syntax highlighting examples.

Author

👤Grigorii Horos

Contributing

Contributions, issues and feature requests are welcome!

Feel free to check the issues page. Run the test suite with:

npm test

Show your support

Give a ⭐️ if this project helped you!

License

Copyright © 2019–2026 Grigorii Horos.

This project is GPL-3.0-or-later licensed.

About

Render HTML to Terminal

Resources

License

Stars

Watchers

Forks

Packages

Contributors