Skip to content
Please note that GitHub no longer supports Internet Explorer.

We recommend upgrading to the latest Microsoft Edge, Google Chrome, or Firefox.

Learn more
HTMDX: Lightweight runtime for mdx-like markdown
TypeScript HTML
Branch: master
Clone or download
Cannot retrieve the latest commit at this time.
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github/workflows
example set marked to xhtml:true by default Jan 31, 2020
src
test lint Jan 31, 2020
.gitignore Merge branch 'master' of https://github.com/michael-klein/htmdx Dec 22, 2019
LICENSE
README.md Update README.md Jan 26, 2020
htmdx.svg readme + logo Dec 22, 2019
package-lock.json updated to htm 3 Jan 21, 2020
package.json
tsconfig.json initial commit Dec 21, 2019

README.md

HTMDX logo

HTMDX: Lightweight runtime for mdx-like markdown

build badge npm

This library is an attempt to provide a runtime to compile mdx-like markdown files (with the goal to support full JSX inside of markdown) using htm + marked that is much smaller in file-size as opposed to the official runtime (which we are not encouraged to use on actual websites).

Here is a simple example playground using HTMDX

Usage

Simple example:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { htmdx } from 'htmdx';
import * as Prism from 'prismjs';

function SomeComponent() {
  return 'something';
}

const markDownWithJSX = `
  # Hello World

  <SomeComponent />

  Mardown will be interpreted as tagged templates from htm:
  <input type="text" style=\${{width: '100%'}} value=\${this.state.inputValue || ''} onChange=\${e => {this.setState({inputValue:e.target.value});console.log(e.target.value)}}/>
  We're also using the setState method and state property passed into using the thisValue options (see below)

  With the transformJSXToHTM option enabled, you may also use normal brackets:
  <input type="text" style={{width: '100%'}} value={this.state.inputValue || ''} onChange={e => this.setState({inputValue:e.target.value})}/>
  
  Here's some code with code highlighting:
  \`\`\`
  function SomeComponent() {
    return "Some component ouput.";
  }
  \`\`\`
`;

function App() {
  const [state, setState] = React.useState({});

  return htmdx(
    markDownWithJSX,
    React.createElement, // provide a h function. You can also use HTMDX with preact or any other library that supports the format
    {
      components: { SomeComponent }, // provide components that will be available in markdown files,
      configureMarked: (
        marked // configure the underlying marked parser, e.x.: to add code highlighting:
      ) =>
        marked.setOptions({
          highlight: function(code) {
            return Prism.highlight(
              code,
              Prism.languages.javascript,
              'javascript'
            ).replace(/\n/g, '<br/>');
          },
        }),
      transformClassToClassname: true, // transforms class="some-class" to className="some-class" (default: true)
      transformJSXToHTM: true, // transforms some JSX to htm template literal syntax (such as value={} to value=${}) (default: true)
      thisValue: {
        // the this value passed to the compiled JSX
        state,
        setState: newState => setState(Object.assign({}, state, newState)),
      },
    }
  );
}

ReactDOM.render(React.createElement(App), document.getElementById('root'));

Edit htmdx example

Pluggable MDX transforms

You can supply MDX transforms, which will be applied to mdx strings before anything else:

htmdx('# Hello World', React.createElement, {
  mdxTransforms: [m => m.replace('# Hello World', '# foo')], // will replace # Hello world with # foo
})

Pluggable JSX transforms

You can supply JSX transforms which allow you to apply further transforms before the JSX pragma runs, like so:

htmdx('# Hello World', React.createElement, {
  jsxTransforms: [
    (props, type, children) => {
      if (children && children[0] === 'Hello World') {
        children[0] = 'Foo'; // this will output <h1>Foo</h1> instead of <h1>Hello World</h1> now!
      }
      return [props, type, children];
    },
  ],
})

Overwriting normal generated html elements with components:

You can also provide components for basic html elements that are generated by the markdown compiler:

htmdx("# Hello World", React.createElement, {
  components: {
    TestComponent,
    h1: props =>
      html`
        <h1 style=${{ color: 'red' }}>${props.children}</h1>
      `,
  }
})
You can’t perform that action at this time.