frontarm / mdx-util Goto Github PK
View Code? Open in Web Editor NEWUtilities for working with MDX
License: MIT License
Utilities for working with MDX
License: MIT License
Hi there!
My impression with markdown is that you can split a paragraph of text into many lines and they will be joined together by spaces:
# header
a
b
c
d
should become
<h1>Header</h1>
<p>a b</p>
<p>c d</p>
However, I think mdxc instead returns this (no spaces)
<h1>Header</h1>
<p>ab</p>
<p>cd</p>
Not sure if that's coming from here or from markdown-it, but I'm willing to help identify/fix π
<markdown>
- some
- markdown
- here
</markdown>
renders as a plain text
(without spaces before - works as as expected)
Using the @mdx-js/parcel-plugin-mdx
parcel plugin I was able to get close to what you provide with mdx-loader
for webpack, but was unable to get front-matter working as you have here.
// mdx.config.js
const images = require("remark-images");
const slug = require("remark-slug");
const mdxTableOfContents = require("mdx-table-of-contents");
const rehypePrism = require("mdx-loader/rehype-prism");
module.exports = {
mdPlugins: [images, slug],
hastPlugins: [rehypePrism],
compilers: [mdxTableOfContents],
};
The problem (as far as I can tell) being that your front-matter solution uses the src markdown but at the compiler step, which I believe is not available at that time.
I tried using remark-frontmatter
, like so
// mdx.config.js
const images = require("remark-images");
const slug = require("remark-slug");
const frontmatter = require("remark-frontmatter");
const mdxTableOfContents = require("mdx-table-of-contents");
const rehypePrism = require("mdx-loader/rehype-prism");
module.exports = {
mdPlugins: [[frontmatter, { type: "yaml", marker: "-" }], images, slug],
hastPlugins: [rehypePrism],
compilers: [mdxTableOfContents],
};
but the frontmatter info doesn't make it through the rest of the mdx process.
Any ideas how to support your frontmatter solution in Parcel
When I use the props example I get an error with webpack-dev-server:
Uncaught SyntaxError: Unexpected token )
The created React component looks like this:
import React, { createElement, createFactory } from 'react'
export default function({ factories={}, value, onChange }) {
const {
wrapper = createFactory('div'),
h1 = createFactory('h1'),
p = createFactory('p'),
} = factories
return wrapper({},
h1({"id": "Hello!"},
"Hello!",
),
p({},
"May I kindly ask your name?",
),
createElement("input", {
value: value,
onChange: onChange
}),
createElement(
"p",
null,
value && `Thanks, ${value}!`
)
)
}
export const meta = {}
The error is here:
h1({"id": "Hello!"},
"Hello!",
), <----
The source:
prop value
prop onChange
# Hello!
May I kindly ask your name?
<input
value={value}
onChange={onChange}
/>
<p>{value && `Thanks, ${value}!`}</p>
And I get also the following error:
warning.js:36 Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
The mdx file is used in a rect component with
import TestMdx from './example.mdx';
...
render() {
...
<TestMdx />
...
}
Any hints on this?
I can't successfully navigate to that url. Is this supposed to be the right URL instead? http://dump.jamesknelson.com/mdxc-playground.html
To clarify, can mdxc be used as a parser in runtime to convert markdown to react output?
The typical usecase would be that you have markdown stored in your database and wants to display it within an application.
Tried
| Type | Default |
| :------------: | :---------: |
| number | 1 |
output
Type Default
number 1
expected
Type | Default |
---|---|
number | 1 |
The url mentioned several times in the README http://mdxc.reactarmory.com/ is not resolved by DNS.
I would like to be able to easily change the fallback from createFactory('${tag}')
to something else like (props, children) => h('${tag}', props, ...children)
.
I have a use case where I need to be able to convert my .mdx files into react components and have them be available as plaintext.
Is it possible to do something like that?
Hi! π
Firstly, thanks for your work on this project! π
I'm working on a react app to make mdx to show mermaid chart as it's really good to draw all sorts of charts.
However I've no idea how to extend the remarkPluingin without touch the source code.
Here is the diff that solved my problem:
diff --git a/node_modules/mdx-loader/index.js b/node_modules/mdx-loader/index.js
index 60c954a..bc0c9a6 100644
--- a/node_modules/mdx-loader/index.js
+++ b/node_modules/mdx-loader/index.js
@@ -10,6 +10,7 @@ const mdxExportJSONByDefault = require('mdx-constant')
const grayMatter = require('gray-matter')
const typography = require('./typography')
const rehypePrism = require('./prism')
+const mdxMermaid = require('mdx-mermaid')
module.exports = async function(source) {
let result
@@ -18,6 +19,7 @@ module.exports = async function(source) {
const options = Object.assign(
{
remarkPlugins: [
+ mdxMermaid,
slug,
images,
emoji,
This issue body was partially generated by patch-package.
with a default wrapper factory this could be simplified
to this
` const {
${['wrapper'].concat(tags).map(tag =>
` ${tag} = ${this.getFactoryForTag(tag)},`
).join('\n')}
} = factories`
@jamesknelson I need to support TOC headingοΌso do you have any plan to support TOC?
Is this package (mdx.macro) even working? I was trying to add to my own project and also I was trying to run example project and in both examples I'm facing the same error:
I'm using mdx.macro inside of a next.js app (with slightly tweaked babel config, but that shouldn't matter here). When using the inline form, the macro attempts to insert the import for MDXTag. The AST for that is generated using babel.transformSync()
. This step however loads the babel config that is available to babel since you're not suppressing loading of that config (via babelrc: false, configFile: false for). The end result is that an insufficient AST is generated, an variable declaration instead of an import declaration, when I serialize the AST back to code something like this comes out: const _tag = require("@mdx-js/tag")
.
I can fix this by suppressing the loading of config in babel.transformSync()
, like so:
let mdxTagImport = babel.transformSync(
`import { MDXTag } from '@mdx-js/tag'`,
{
babelrc: false,
configFile: false,
ast: true,
filename: "mdx.macro/mdxTagImport.js",
}
)
I believe a more robust solution would be to construct the AST by hand, it's one import declaration anyways.
Minimal reproduction here: https://github.com/bensmithett/mdx-error-repro
Example markdown: https://github.com/bensmithett/mdx-error-repro/blob/master/some_markdown.mdx
Example of what I'm trying to do with it: https://github.com/bensmithett/mdx-error-repro/blob/master/index.js#L19
If a heading other than a h1 has nested tags (e.g. code via backticks, italics via *
) the tableOfContents
expects a global MDXTag
to exist.
I don't really know enough about how MDX works to make any intelligent suggestions, but...
Could this have something to do with it?
Also noticed the error actually makes it into the output bundle code so it's not just a runtime thing?
Thanks in advance π
I use Webpack 3, so have to use [email protected]
I followed the instructions about importing a theme https://github.com/frontarm/mdx-util/tree/master/packages/mdx-loader#syntax-highlighting . But the result is that background styles are not applied because the generated markup doesn't preserve theme selectors https://github.com/PrismJS/prism/blob/master/themes/prism-tomorrow.css#L39
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #2d2d2d;
}
Built result
Using mdx.macro, if I have the following two files:
transcluded.mdx
This is some **markdown** content.
main.mdx
import Transcluded from '../../../src/transcluded.mdx';
<Transcluded />
then I get the following warning and error in the console, and the page crashes.
Warning: </static/media/Transcluded.312f719b.mdx /> is using incorrect casing. Use PascalCase for React components, or lowercase for HTML elements.
in /static/media/Transcluded.312f719b.mdx (at Main.mdx:18)
react-dom.development.js:7935 Uncaught (in promise) DOMException: Failed to execute 'createElement' on 'Document': The tag name provided ('/static/media/Transcluded.312f719b.mdx') is not a valid name.
After updating an existing React app lxkns to react-scripts 5.0.0 the documented method of using mdx-loader with babel-loader
import AboutMDX from "!babel-loader!mdx-loader!./About.mdx"
does not work anymore. AboutMDX
contains a string which is the path name to the Javascript file compiled from the .mdx source, but not the required React component or function.
I cannot see how I can use your rehype-prism
solution to pass in a prism config. Is this supported at this time?
I'm getting an error in the browser when using MDXC. This is the error:
readme.md:14 Uncaught SyntaxError: Unexpected token )
I think this is because of the trailing comma, where p
has a missing 3rd argument:
p({},
"This is the About page",
),
Here is the full transpiled code for readme.md
:
import React, { createElement, createFactory } from 'react'
export default function({ factories={} }) {
const {
wrapper = createFactory('div'),
h2 = createFactory('h2'),
p = createFactory('p'),
} = factories
return wrapper({},
p({},
"This is the About page",
),
h2({"id": "Section-1"},
"Section 1",
),
p({},
"Text about section",
),
h2({"id": "Section-2"},
"Section 2",
),
p({},
"Text about section",
)
)
}
export const meta = {}
//////////////////
// WEBPACK FOOTER
// ./src/lab/app/About/readme.md
// module id = ./src/lab/app/About/readme.md
// module chunks = 0
I'm using the basic webpack config shown in the readme:
{ test: /\.mdx?$/,
use: [
'babel-loader',
'mdx-loader',
]
},
Lastly, here is the original markdown:
This is the About page
## Section 1
Text about section
## Section 2
Text about section
i love being able to put jsx inside of markdown but im missing the ability to the same with js.
i would love to be able to do
const test = "hello world"
<p>{test}</p>
i think it should be posible
How to add and enable markdown-it plugins (and in webpack-loader)
i.e.
prop children
<div {...props} > { children } </div>
Like title suggest, it seems currently impossible to have a list of customized components added to importMDX.sync. Could it be possible to supply a list of components as a parameter of this function?
Is there any progress on adding TS definitions for the mdx.macro package?
Currently JSX does not work in the middle of components with mdx-loader
, because it is using an old version of @mdx-js/mdx
.
This works
<span style={{ color: "red }}>I'm red</span>
But this doesn't, it breaks the build π’
I'm a paragraph in markdown <span style={{ color: "red" ]}>And I'm red</span>
This should be supported with mdx version 1
Upgrading to v1 of @mdx-js/mdx
will fix this.
import { Social } from 'modules/buttons'
<footer className="my-footer"></footer>
i.e. I want <footer></footer>
, not <div><footer></footer></div>
MDX goes stable: https://mdxjs.com/blog/v1.
As per jamesknelson/mdx-loader#3:
Error: Package "[email protected]" (via "...") is trying to require the package
"loader-utils" (via "loader-utils") without it being listed in its dependencies
(@mdx-js/mdx, @mdx-js/tag, gray-matter, hast-util-to-html, hast-util-to-string,
mdx-constant, mdx-table-of-contents, prismjs, refractor, remark-emoji, remark-images,
remark-slug, remark-textr, typographic-base, unist-util-visit, mdx-loader)
There is a word missing in the line:
Because an MDX file compiles to a React Component, you'll need to name use React-style attributes.
If you use code blocks with a language, like so...
```javascript
var i = 0;
```
...then it will render the code block, as expected, using <pre>
.
However, if you use code blocks without a language, like so...
```
var i = 0;
```
...then it will render the code block as inline code using <code>
.
It appears to be an issue with MDXC and not markdown-it if you use them on their live demo sites.
Hi there, great project!
When I try to import a component below front matter like so:
---
title: Example
description: This is an example
---
import { MDXBreadboard } from 'mdx-breadboard'
It sometimes throws an error:
Uncaught ReferenceError: MDXBreadboard is not defined
When I remove the front matter, the component seems to work just fine.
Any suggestions?
The readme and your blog post states you should use mdxc <filename>.mdx
to run MDXC but the bin command in the package.json
is mdx
.
How can I render mdxc generated JS as component, like:
import React from 'react';
import MDXC from 'mdxc';
var mdxc = new MDXC({
linkify: true,
typographer: true,
});
const js = mdxc.render('# This is a heading');
export default () => js;
The code above renders js source.
PS This is just example, the use case is to load dynamically all posts for a blog or markdown content loaded via API.
Just curious, how difficult do you think it'd be to upgrade it as a person new to the project?
I want to see if I can use it with the latest next.js
Thanks,
D
Using mdx.macro on Windows gets me:
ERROR in C:/Users/thoma/OneDrive/Documents/devel/linear/node_modules/.cache/mdx.macro/icloud.c3ec31aebc.mdx.js
Module not found: Error: Can't resolve 'C:Users homaOneDriveDocumentsdevellinearpackagesarticleicloud.mdx' in 'C:\Users\thoma\OneDrive\Documents\devel\linear\node_modules\.cache\mdx.macro'
I tracked this down to a generated line that looks like this (in the cache):
import React from 'react';
import { MDXTag } from '@mdx-js/tag';
import "C:Users\thomaOneDriveDocumentsdevellinearpackagesarticlehow-to-hack-icloudicloud.mdx"; // here
export default (function (_ref) {
var components = _ref.components,
props = _objectWithoutProperties(_ref, ["components"]);
It looks like some part of mdx.macro is incorrectly processing windows slashes as escapes.
I'm guessing that what is happening here is that mdx.macro generates some code via concatenation, rather than via AST manipulation, so this line is generated by:
https://github.com/frontarm/mdx-util/blob/master/packages/mdx.macro/mdx.macro.js#L123
imports += `import '${documentPath}'\n`
then converted to an AST and transformed here, like this:
https://github.com/frontarm/mdx-util/blob/master/packages/mdx.macro/mdx.macro.js#L129
let transformedSource =
babel.transformSync(
imports+mdx.sync(source),
{
presets: [babelPresetReactApp],
filename: documentPath,
},
).code
I imagine what's going on here is that injecting the import via string concatenation on Windows is giving us something like:
import "c:\path\to\file"
which, after transformation by babel ends up being:
import "c:path\tofile"
The absolute quickest and dirtiest we can do here is just to escape all \
.
As of 2.2.0, mdx-loader:
readingTime
object which can be used to add a medium-style estimated reading timeThis needs to be documented properly in the README.
I'm attempting to use the mdx-table-of-contents
package with next.js but when I import the tableOfContents
object it's undefined:
import Document , { tableOfContents } from "../../../reference-api.mdx";
Here's what my next.config.js file looks like:
const toc = require("mdx-table-of-contents");
const withMDX = require("@next/mdx")({
options: {
remarkPlugins: [toc],
},
extension: /\.mdx?$/,
});
module.exports = withMDX({
pageExtensions: ["js", "jsx", "md", "mdx", "ts", "tsx", "svg"],
});
Any idea what I'm doing wrong?
I have a markdown file with the following content:
# Foo
## Schema
<div data-render-schema='http://schemas.taskcluster.net/queue/v1/create-task-request.json'></div>
I am trying to find a way to have access to <div>
elements in markdowns and having them replaced with a React element.
I tried the following but the schemaViewer
function is not being triggered:
const components= {
div: this.schemaViewer,
};
// ...
schemaViewer = ({ props, children }) => {
const url = children.props['data-render-schema'];
if (url) {
return <SchemaTable url={url} />;
}
return children;
};
// ...
<MarkdownDocument components={components} />
Do you know of a way I can have access to the element without modifying the original markdown file? Any help is appreciated. Thanks!
I am having trouble getting MDX (0.2.8) to work with CRA (react-scripts 2.1.8) and React (16.8.6). I am using Node 10.1.0. (Just updated to 11.13.0, problem persists)
I keep getting the error:
Can't resolve './MyComponent' in '...node_modules/.cache/mdx.macro/MyComponent.84dc28b7ef.mdx.js'
despite it being in the same dir?
Not sure if it is related but I also get a loop of errors in iTerm immediately after it fails:
node[50284] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
until it eventually errors too many times and halts the output to the terminal.
Hi
I'm having trouble importing an image (so that webpack can process it) and including that image in the rendered markdown, e.g., something like
import logo from './images/logo.png';
![Logo]({logo})
since bracess ({logo}
above) aren't treated as JSX in inline markdown.
Any ideas about how to achieve this?
First of all, great project! I've been trying to get several other projects cobbled together to do something similar to what you've built and it looks like you might save me a bunch of time.
I would like to use this library in a project (via the webpack loader), but I depend on the Babel transform-react-jsx
plugin with the { pragma: "h" }
option. This means that JSX is compiled to h(...)
instead of React.createElement(...)
. Note that specifying /** @pragma h */
at the top of a file does the same thing, but only for a single file.
Unfortunately, it looks like MDXC is hard-coded to use a pragma of createElement
. It would really help if this value could be customized for all *.md
files. Or possibly support the pragma comment within the front-matter of individual MD files.
This would open up your tool to being used with various other virtual DOM libraries that support JSX syntax, including React-clones such as Preact.
I'm creating a live documentation and demo site, so I'd like to render markup within a code highlighter, but also show it live on the page. I could write markdown like this:
prop buttonType
import Button from 'Button'
# Button
<Button className={buttonType}>Button with {buttonType} styling</Button>
β```jsx
<Button className={buttonType}>Button with {buttonType} styling</Button>
β```
However, I'd like to avoid repeating the markup in the markdown document. What I'd like is to write markdown like this:
prop buttonType
import Button from 'Button'
# Button
β```example
<Button className={buttonType}>Button with {buttonType} styling</Button>
β```
And have it render something like:
<div class="example">
<div class="live">
<Button class="primary">Button with primary styling</Button>
</div>
<div class="code">
<pre><code>
<Button className={buttonType}>Button with {buttonType} styling</Button>
</code></pre>
</div>
</div>
I can think of several possible ways to do this, but I'm hoping to get some feedback on what might be preferred.
example
code fences and converts it into html before the mdx-loader
is run.markdown-it
plugin.markdown-it-container
plugin, such as ::: example
<example> ... </example>
?I'm leaning toward option 1 since I'm experienced writing webpack loaders and am not experienced with markdown-it
, how to write plugins for it, or how to use markdown-it-container
. Option 1 would allow me to transform the markdown before MDXC even sees it.
However, I wouldn't mind giving the markdown-it
approaches a try, I'm just not sure which direction makes the most sense, or if there are other options I should consider. I played with markdown-it-container
some, but was not getting the results I was hoping. I had hoped to transform the ::: example
into to HTML markup in a "first pass", and then let MDXC/markdown-it process everything after my transform. But my HTML was getting output as raw text strings.
Note that for simplicity, in the examples above, I'm using a very basic React Button
component and a rather non-sensical buttonType
prop. In reality, this is to demo and document a library of custom Web Components as well as custom React components. Both the Web Components and React Components have much more complex interfaces, accepting multiple attributes/properties, child markup, slots, etc.
Sorry I was not able to handle by myself...
Have a markdown containing an image tag:
![My image](./images/gravity-book-fr.jpg "My image")
I was assuming, the mdx-loader would resolve the picture from the markdown document file, and then let webpack do the regular job (take the picture, move it to the static dist, hash...) .
But it looks it's not the case... Is it something I can achieve (I mean with regular markdown, without import './img.jpg')
Have you any thoughts ? Thanks
i would like to be able to wrap the jsx inside a div automatically
I have a markdown file with the following content:
3. For running tests within a test file, add "--grep <phrase>" when running
the above command to capture just the individual test name.
When I try to use mdx-loader, I get an error in the terminal Expected corresponding JSX closing tag for <phrase>
.
Do you know of any way I could have this fixed without changing the markdown file directly (i.e., without wrapping it with backticks). fwiw, none of my markdown files have jsx in them and so I was wondering if there's some kind of option I could disable so that <phrase>
is treated as plain text but something like <div>test</div>
is treated like html. Thanks!
I am getting a bunch of these errors after upgrading to [email protected]
:
@mdx-js/mdx: The hastPlugins option has been deprecated in favor of rehypePlugins
Support for hastPlugins will be removed in MDX v2
@mdx-js/mdx: The mdPlugins option has been deprecated in favor of remarkPlugins
Support for mdPlugins will be removed in MDX v2
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.