All Projects → ticky → Markdown Component Loader

ticky / Markdown Component Loader

Licence: other
📑 Turn Markdown into dynamic, stateless React components

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Markdown Component Loader

Dataformsjs
🌟 DataFormsJS 🌟 A minimal JavaScript Framework and standalone React and Web Components for rapid development of high quality websites and single page applications.
Stars: ✭ 95 (+33.8%)
Mutual labels:  markdown, react-components
Spinners React
Lightweight SVG/CSS spinners for React
Stars: ✭ 254 (+257.75%)
Mutual labels:  react-components, loader
react-awesome-loaders
🚀 High quality, super responsive and completely customisable Loading Animations to insert into your website with single line of code.
Stars: ✭ 146 (+105.63%)
Mutual labels:  loader, react-components
React Showdown
Render React components within markdown and markdown as React components!
Stars: ✭ 86 (+21.13%)
Mutual labels:  markdown, react-components
Markdown Loader
markdown loader for webpack
Stars: ✭ 335 (+371.83%)
Mutual labels:  markdown, loader
Linkify Markdown
🚀 A cli tool which automatically add references to issues, pull requests, user mentions and forks to a markdown file.
Stars: ✭ 67 (-5.63%)
Mutual labels:  markdown
Wemark
微信小程序Markdown渲染库
Stars: ✭ 1,159 (+1532.39%)
Mutual labels:  markdown
Markdown Builder
1kb Markdown builder for Node.js
Stars: ✭ 67 (-5.63%)
Mutual labels:  markdown
Neuron.js
A Full Feature CommonJS Module Manager, Dependency Graph Handler and Loader for Browsers
Stars: ✭ 66 (-7.04%)
Mutual labels:  loader
Css Loader
Simple loaders for your web applications using only one div and pure CSS ❤️
Stars: ✭ 1,165 (+1540.85%)
Mutual labels:  loader
Swift
Airbnb's Swift Style Guide.
Stars: ✭ 1,165 (+1540.85%)
Mutual labels:  markdown
Toc
🚩 TOC, zero configuration table of content generator for Markdown files, create table of contents from any Markdown file with ease.
Stars: ✭ 66 (-7.04%)
Mutual labels:  markdown
Extracted Loader
It reloads extracted stylesheets extracted with ExtractTextPlugin
Stars: ✭ 67 (-5.63%)
Mutual labels:  loader
Nice Mail
💌 Nice Mail 是一款以 Markdown 为基础的邮件编辑器。
Stars: ✭ 69 (-2.82%)
Mutual labels:  markdown
Mmarkdown
Interpret mmd fenced code blocks in a markdown file and generate a cooler version of it.
Stars: ✭ 67 (-5.63%)
Mutual labels:  markdown
Godot Engine.file Editor
A Godot Engine addon that adds a File Editor for multiple file types editing. Create and Write plain text files, configuration files and csv files with custom visualizers and previews. Also supports file translations!
Stars: ✭ 70 (-1.41%)
Mutual labels:  markdown
Docnado
Rapid documentation tool that will blow you away...
Stars: ✭ 67 (-5.63%)
Mutual labels:  markdown
Sui Components
SUI Components
Stars: ✭ 66 (-7.04%)
Mutual labels:  react-components
Starter Academic
🎓 Easily create a beautiful academic résumé or educational website using Hugo, GitHub, and Netlify
Stars: ✭ 1,158 (+1530.99%)
Mutual labels:  markdown
Gitjournal
Mobile first Note Taking integrated with Git
Stars: ✭ 1,138 (+1502.82%)
Mutual labels:  markdown

Markdown Component Loader

npm markdown-component-loader Build Status codecov

Turn Markdown into dynamic, stateless React components

  • Integrate documentation and other prose with user info and context
  • Show your real UI components alongside documentation
  • Add other dynamic components inside documentation

Usage

Installation

yarn add markdown-component-loader

~or~

npm install --save markdown-component-loader

You'll need both Babel and Webpack in order to use it.

Webpack Configuration

You then need to configure Webpack to use the loader, in your webpack.config.js;

module.exports = {
  module: {
    loaders: [
      {
        test: /\.mdx$/i,
        loader: 'babel-loader!markdown-component-loader'
      },
      {...more}
    ]
  },
  {...more}
};

Usage and Syntax

mdx allows you interleave both React props and React components within your prose and code snippets! mdx files may optionally start with yaml-formatted front-matter.

Front-matter accepts imports, which will be included in the React component's definition. Other front-matter keys are added as static properties of the resultant Markdown component.

Here's an example of an mdx file;

---
imports:
  '{ name, version }': ./package.json
displayName: MarkdownComponentLoaderReadme
---

This is a _Markdown Component_ file. Here you can include JSX-style assignment expressions; this component was generated using version {{ version }} of {{ name }}!

Props passed to this component are available as `props`, so you can embed those too! Hello there, {{ props.who || 'world' }}!

Another cool thing you can do is use JSX **directly** - here’s an SVG element, used inline: <svg style={{ display: 'inline', height: '1em' }} viewBox="0 0 304 290"><path fill="none" stroke="currentColor" strokeWidth="16" d="M2,111 h300 l-242.7,176.3 92.7,-285.3 92.7,285.3 z" /></svg>.

Note: destructuring imports must be quoted, but others need not be.

The above mdx file will produce the following module within Webpack;

import React from 'react';
import PropTypes from 'prop-types';
import { name, version } from './package.json';

MarkdownComponent.propTypes = {
  className: PropTypes.string,
  style: PropTypes.object
};

MarkdownComponent['displayName'] = 'MarkdownComponentLoaderReadme';

function MarkdownComponent(props) {
  const {className, style} = props;

  return (
    <div className={className} style={style}>
      <p>This is a <em>Markdown Component</em> file. Here you can include JSX-style assignment expressions; this component was generated using version { version } of { name }!</p>
      <p>Props passed to this component are available as <code>props</code>, so you can embed those too! Hello there, { props.who || 'world' }!</p>
      <p>Another cool thing you can do is use JSX <strong>directly</strong> - here’s an SVG element, used inline: <svg style={{ display: 'inline', height: '1em' }} viewBox="0 0 304 290"><path fill="none" stroke="currentColor" strokeWidth="16" d="M2,111 h300 l-242.7,176.3 92.7,-285.3 92.7,285.3 z" /></svg>.</p>
    </div>
  );
};

export default MarkdownComponent;

You can then include it anywhere you like in your own React code;

import ReactDOM from 'react-dom';

import Readme from './readme.mdx';

ReactDOM.render(
  <Readme who="you" />,
  document.getElementById('main')
);

Extra Configuration

Markdown Component Loader accepts configuration of options via the Webpack configuration file.

module.exports = {
  module: {
    rules: [
      {...more},
      {
        test: /\.mdx$/i,
        use: [
          'babel-loader',
          {
            loader: 'markdown-component-loader',
            options: {...options}
          }
        ]
      }
    ]
  },
  {...more}
};

Available Options

  • passElementProps: Controls whether props can be passed from the parent to the generated elements. Defaults to false.
  • implicitlyImportReact: Whether to include React and PropTypes in the imports automatically. If set to false, you need to either supply React and PropTypes or import them explicitly. Defaults to true.
  • markdownItPlugins: An array of MarkdownIt plugins (and optionally their additional arguments) to use within the markdown renderer. These can be specified either as instances, or as paths as returned by require.resolve.
MarkdownIt Plugins

If you supply an array of MarkdownIt plugins as markdownItPlugins, Markdown Component Loader will chain them into the internal MarkdownIt renderer.

{
  loader: 'markdown-component-loader',
  options: {
    markdownItPlugins: [
      require('markdown-it-anchor'),
      [require('markdown-it-table-of-contents'), { containerClass: 'my-container-class' }]
    ]
  },
  {...more}
}

The configuration above will supply both markdown-it-anchor and markdown-it-table-of-contents to MarkdownIt's use method. markdown-it-table-of-contents is supplied within an array, and the entire array is passed as the arguments to use, allowing specifying plugin configurations.

Legacy Webpack compatibility

For compatibility with Webpack 1.x, where plugin configuration must be JSON compatible, plugins can be passed as path strings rather than the plugin object itself.

The equivalent of the example above in Webpack 1.x would be as follows.

module.exports = {
  markdownComponentLoader: {
    markdownItPlugins: [
      require.resolve('markdown-it-anchor'),
      [require.resolve('markdown-it-table-of-contents'), { containerClass: 'my-container-class' }]
    ]
  },
  {...more}
};

Styling and Interaction

Container Styling

The container will have supplied className and style props passed through to it.

Inner Element Styling

If passElementProps is set to true, elements within the Markdown Component can be styled on a per-element-name basis. You can set this in the webpack.config.js (see the "Extra Configuration" section).

All generated standard elements (read: elements which are known to React.DOM) will then have elementProps['name'] spread onto them (where name is the tag name of the element). This option is intended to be used with Basscss modular CSS.

Here's the above example markdown document converted with this option;

import React from 'react';
import PropTypes from 'prop-types';
import { name, version } from './package.json';

MarkdownComponent.propTypes = {
  className: PropTypes.string,
  style: PropTypes.object,
  elementProps: PropTypes.object
};

MarkdownComponent.defaultProps = {
  elementProps: {}
};

MarkdownComponent['displayName'] = 'MarkdownComponentLoaderReadme';

function MarkdownComponent(props) {
  const {className, style, elementProps} = props;

  return (
    <div className={className} style={style}>
      <p {...elementProps['p']}>This is a <em {...elementProps['em']}>Markdown Component</em> file. Here you can include JSX-style assignment expressions; this component was generated using version { version } of { name }!</p>
      <p {...elementProps['p']}>Props passed to this component are available as <code {...elementProps['code']}>props</code>, so you can embed those too! Hello there, { props.who || 'world' }!</p>
      <p {...elementProps['p']}>Another cool thing you can do is use JSX <strong {...elementProps['strong']}>directly</strong> - here’s an SVG element, used inline: <svg style={{ display: 'inline', height: '1em' }} viewBox="0 0 304 290" {...elementProps['svg']}><path fill="none" stroke="currentColor" strokeWidth="16" d="M2,111 h300 l-242.7,176.3 92.7,-285.3 92.7,285.3 z" {...elementProps['path']} /></svg>.</p>
    </div>
  );
};

export default MarkdownComponent;

You can then specify any prop you want here, and that prop will be applied to all elements of that tag name.

For example, if you wanted to get a callback from each level-1 heading instance, you could use the component like this;

<SomeMarkdownComponent
  elementProps={{
    h1: {
      onClick: (evt) => /* do something */
    }
  }}
/>

This also facilitates the Basscss style, allowing, for instance, styling of anchor tags like so;

<SomeMarkdownComponent
  elementProps={{
    a: {
      className: 'blue hover-navy text-decoration-none hover-underline'
    }
  }}
/>

Prior Art

react-markdown-loader by Javier Cubides allows use of React components within fenced code blocks (albeit not assignment expressions), and gave me the idea to use yaml front-matter for imports. Thanks! 😁

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].