Coder Social home page Coder Social logo

mdx's Introduction

MDX

Markdown for the component era

Build Coverage Sponsors Backers Chat

MDX is an authorable format that lets you seamlessly write JSX in your markdown documents. You can import components, such as interactive charts or alerts, and embed them within your content. This makes writing long-form content with components a blast. 🚀

import {Chart} from './snowfall.js'
export const year = 2013

# Last year’s snowfall

In {year}, the snowfall was above average.
It was followed by a warm spring which caused
flood conditions in many of the nearby rivers.

<Chart year={year} color="#fcb32c" />

See § What is MDX for more info on the format. See § Playground to try it out.

What is this?

This GitHub repository contains several packages for compiling the MDX format to JavaScript, integrating with bundlers such as webpack and Rollup, and for using it with frameworks such as React, Preact, and Vue.

See § Getting started for how to integrate MDX into your project.

Security

See § Security on our site for information.

Contribute

See § Contribute on our site for ways to get started. See § Support for ways to get help.

This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.

Sponsor

See § Sponsor on our site for how to help financially.

Vercel

Motif

HashiCorp

GitBook

Gatsby

Netlify

Coinbase

ThemeIsle

Expo

Boost Note

Markdown Space

Holloway


You?

License

MIT © Compositor and Vercel

mdx's People

Contributors

chenxsan avatar christianmurphy avatar christopherbiscardi avatar danielruf avatar dependabot[bot] avatar hugmanrique avatar jablko avatar jeetiss avatar johno avatar jounqin avatar jxnblk avatar karlhorky avatar leimonio avatar macklinu avatar manovotny avatar millette avatar mxstbr avatar pshrmn avatar remcohaszing avatar renovate[bot] avatar samrobbins85 avatar silvenon avatar slorber avatar timneutkens avatar trevordmiller avatar userzimmermann avatar vlad-zhukov avatar wooorm avatar xhomu avatar xyc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mdx's Issues

JSX parsing bugs

children props are overridden

<Foo children='bar' />

Children prop is empty because the ast children attribute is used.

unnecessary p tags

<Foo>
  Bar
</Foo>

Results in

<h1>
  <p>Bar</p>
</h1>

complex jsx is borked

<Foo>
  <Bar
    children={props.bar.map(b =>
      <Baz key={b}>{b}</Baz>
    )}
  />
</Foo>

Perhaps stuff like this is where we introduce the .jsx code block back?

Expression based props error

<Foo color={'pink'} />

Errors with (in next example):

Error
Error
    at tokens.reduce.type (http://localhost:3000/_next/-/page/index.js:2090:19)
    at Array.reduce (<anonymous>)
    at parse (http://localhost:3000/_next/-/page/index.js:2084:23)
    at Of.parser (http://localhost:3000/_next/-/page/index.js:823:18)
    at Of.tokenize [as tokenizeBlock] (http://localhost:3000/_next/-/page/index.js:72636:18)
    at Of.parse (http://localhost:3000/_next/-/page/index.js:68441:20)
    at Function.parse (http://localhost:3000/_next/-/page/index.js:80537:45)
    at pipelineParse (http://localhost:3000/_next/-/page/index.js:80284:16)
    at wrapped (http://localhost:3000/_next/-/page/index.js:80139:19)
    at next (http://localhost:3000/_next/-/page/index.js:80102:24)

Allow multi-line jsx

Old:

<TerminalInput prefix>npm i next@latest react@latest react-dom@latest</TerminalInput>

<Caption>In addition to bumping Next.js etc...</Caption>

new:

<TerminalInput prefix>npm i next@latest react@latest react-dom@latest</TerminalInput>
<Caption>In addition to bumping Next.js etc...</Caption>

Consider how to align with the .mdx proposal

Some thoughts inspired by rauchg's .mdx proposal and an iteration on formalizing c8r/markdown.

Inlining JSX

This is a <Text.span>span</Text.span>.

Code blocks

Specifying .jsx as the language will render the React components.
You can also specify front matter which is passed as props to the components being rendered.

---
foo: bar
---
<Awesome>{props.foo}</Awesome>

Inlining JS

{new Date()}

Providing scope/element mapping

We need to be able to provide components, props,

Perhaps this can be done with a MarkdownProvider and ScopeProvider?

Implementation details

The following detauls need to be sorted out for a solid spec/implementation:

Mdast

Depending on what syntax we arrive at, we will need to transform the MD AST to render the desired components.

Interesting related projects/implementations:

Loaders for webpack/parcel

import Post from './posts/proposal.mdx'

export default <Post />

Import syntax

Ideas:

  • imports as the beginning of a mdx file
  • using front matter

Pluggable

Similarly to how remark provides a pluggable API, we should also allow plugins to be passed in.
This allows further customization down the road, and also supporting the existing remark plugin ecosystem (toc, gh integrations, etc).

Linting and prettier

Code blocks and inlined js can be run through prettier at the mdast stage and then re-output to markdown.

I suspect the same will be possible with inlined JSX as well.

Input

Hello, <World some='prop' />

Output

Hello, <World some="prop" />

Implement a MarkdownProvider

This will add a context that provides an element to component mapping, and any other globally available components.

As an example API, this will render Heading for the h1 element in readme.md.

import React from 'react'
import { MarkdownProvider } from '@compositor/markdown'

import { Heading } from './ui'

import Readme from './readme.md

export default () =>
  <MarkdownProvider components={{ h1: Heading }}>
    <Readme />
  </MarkdownProvider>

Handle layout key in frontmatter

After some discussion with @timneutkens and @jxnblk we think it makes most sense to allow layout to be optionally specified in frontmatter.

---
title: Awesome Page
slug: /awesome
layout: ./PageLayout
team:
  - jxn
  - mrmrs
  - johno
---

Resulting in, when layout is defined, the result would be something similar to:

import PageLayout from './PageLayout'

// ... stuff

export default PostLayout(frontmatter)(Markdown)

Something to consider: Should a layout be a HOC or standard component?

Move non-react transclusion code to standalone remark-transclude module

import fs from 'fs'
import path from 'path'
import visit from 'unist-util-visit'
import { parse } from 'remark'

import {
  isTranscludable,
  isRelativeFile
} from './util'

export default () => (tree, file) =>
  visit(tree, 'text', (node, _i, parent) => {
    if (!isRelativeFile(node.value) || !isTranscludable(node.value)) {
      return
    }

    const index = tree.children.indexOf(parent)

    if (index === -1) {
      return
    }

    const transcludedFile = path.join(file.cwd, node.value)

    let content = null
    try {
      content = fs.readFileSync(transcludedFile, 'utf8')
    } catch (e) {
      console.log(`Error transcluding ${transcludedFile}`)
    }

    if (content) {
      tree.children = [].concat(
        tree.children.slice(0, index),
        parse(content).children,
        tree.children.slice(index + 1)
      )
    }
  })

Fix key error

In the renderer we should be adding a key prop, we currently aren't resulting in the following error:

Warning: Each child in an array or iterator should have a unique "key" prop

Allow ability to pass scope to MDX document

It'd be nice to be able pass in additional components and props to the component scope.

import React from 'react'
import { Box } from './ui'
import Document from './doc.md'

export default () => <Document scope={{ title: 'Hello', Box }} />
# This is some markdown

That has `Box` and `title` in scope:

<Box>{title}</Box>

Custom jsx block

In certain cases it'd be nice to be able to render jsx components directly, the components to be rendered need to be provided in scope.

Proposed syntax:

[[jsx]]
| <MyComponent
|   with={some}
|   props={here}
| />

Another possible syntax:

Using code blocks with a ! postfix:

```.jsx!
<MyComponent
  with={some}
  props={here}
/>
\```

inlineCode parsed as code

If you create a file like:

# heading

hello `test`

It'll parse single quoted lines as code blocks instead of inlineCode as defined in the spec. I'm not sure if this is an issue with remark or mdxast 🤔

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.