Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem using remark-math with MDX #145

Closed
KrofDrakula opened this issue May 17, 2018 · 11 comments
Closed

Problem using remark-math with MDX #145

KrofDrakula opened this issue May 17, 2018 · 11 comments
Labels
🐛 type/bug This is a problem

Comments

@KrofDrakula
Copy link

KrofDrakula commented May 17, 2018

I've been trying to plug in the KaTeX renderer into the chain of plugins for MDX, but so far, I'm stuck with with some of the formulae incorrectly rendering.

My webpack rules part is as follows:

{
  test: /\.mdx$/,
  use: [
    ...babelLoader,
    {
      loader: '@mdx-js/loader',
      options: {
        mdPlugins: [math],
        hastPlugins: [katex]
      }
    }
  ]
}

...where math and katex are the packages remark-math and rehype-katex, respectively. I'm using preact and preact-compat with the following aliases:

alias: {
  react: 'preact-compat/dist/preact-compat',
  'react-dom': 'preact-compat/dist/preact-compat',
  'react-addons-create-fragment': 'preact-compat/dist/preact-compat'
}

To illustrate the problem, I'm trying to render the following page:

import 'katex/dist/katex.css';
import { h } from 'preact';

## Math test

$$
\sum{1}
$$

$$
\sum{i}
$$

The first equation renders fine, since 1 is a literal and is just converted to a string in the JSX. However, the second equation uses {i} in the rendered JSX and tries to evaluate the i, which fails because i is undefined.

Is there a way to have JSX be ignored or forced to escape in the math portion of the MDX?

@linonetwo
Copy link

linonetwo commented Sep 17, 2018

I have

The `style` prop expects a mapping from style properties to values, not a string. For example, style={{marginRight: spacing + 'em'}} when using JSX.
    in span (created by MDXTag)
    in MDXTag (created by Context.Consumer)
    in Unknown (at hw1.md:8)
    in span (created by MDXTag)
    in MDXTag (created by Context.Consumer)
    in Unknown (at hw1.md:8)
    in span (created by MDXTag)
    in MDXTag (created by Context.Consumer)
    in Unknown (at hw1.md:8)

From

# Homework 1

## 1. We want to evaluate the function

$$
\sum{1}
$$

And my config-overrides.js:

rule.oneOf.unshift({
      test: /\.mdx?$/,
      use: [
        {
          loader: babelLoader.loader,
          options: babelLoader.options,
        },
        {
          loader: '@mdx-js/loader',
          options: {
            mdPlugins: [math],
            hastPlugins: [katex],
          },
        },
      ],
    });

@ChristopherBiscardi
Copy link
Member

So this is because the remark plugins write out html into the AST which then tries to get used as JSX at runtime because they're all html nodes iirc.

We partially addressed this problem in gatsby-mdx (demo with katex) by introducing an html-to-jsx plugin that converts raw html to JSX before the final conversion. It might make sense to add this to MDX core (note though that our implementation is slightly faulty for some use cases and we're swapping it out for a new one).

@silvenon
Copy link
Contributor

silvenon commented Sep 17, 2018

I managed to fix #145 (comment), but I don't know how to reproduce yours, @KrofDrakula, because I'm not familiar with Preact. Is Preact relevant to your issue? If yes, could you provide a demo repository?

@silvenon silvenon added the 🐛 type/bug This is a problem label Sep 17, 2018
@KrofDrakula
Copy link
Author

I'm not sure whether it is relevant, but with Babel, an identical output would be achieved by the following JS preamble:

/** @jsx h */
import { h } from 'preact';

As long as the preact-compat package is aliased to the packages that are normally provided by React (as described in the issue description), it should work transparently as if React was being used, in the vast majority of cases (exceptions are returning an array of elements for a component base, and fragment support is missing).

I'll see if I can create a minimal setup with something like Codesandbox to post here.

@silvenon
Copy link
Contributor

I think I was missing the pragma part. I'll try to reproduce it again tomorrow.

@KrofDrakula
Copy link
Author

So here's a working example of the compiler that uses preact-render-to-string to render the HTML.

https://repl.it/@KrofDrakula/NiftyOffbeatAngle

Sorry if it's a bit contrived, but the essence is that index.js is the main function (runs webpack), which then runs the compiled source from the src dir. From there, it should be self-explanatory.

@silvenon
Copy link
Contributor

silvenon commented Sep 19, 2018

I'm not sure that I see the issue. preact-render-to-string renders the HTML result, the fact that it contains {i} means that the interpolation didn't happen, which is good. Something here leads me to believe that you're parsing this string as JSX again, causing {i} to be interpreted as interpolation.

The JSX that MDX outputs is at the bottom of this comment. As you can see, {i} is within a string, which I assume is desired behavior. It's up to you to properly parse this on your end.

JSX output from MDX
import 'katex/dist/katex.css'
import { h } from 'preact'

export default ({ components, ...props }) => (
  <MDXTag name="wrapper" components={components}>
    <MDXTag name="h2" components={components}>{`Math test`}</MDXTag>
    <MDXTag name="div" components={components} props={{ className: 'math' }}>
      <MDXTag
        name="span"
        components={components}
        parentName="div"
        props={{ className: 'katex-display' }}
      >
        <MDXTag
          name="span"
          components={components}
          parentName="span"
          props={{ className: 'katex' }}
        >
          <MDXTag
            name="span"
            components={components}
            parentName="span"
            props={{ className: 'katex-mathml' }}
          >
            <MDXTag name="math" components={components} parentName="span">
              <MDXTag
                name="semantics"
                components={components}
                parentName="math"
              >
                <MDXTag
                  name="mrow"
                  components={components}
                  parentName="semantics"
                >
                  <MDXTag
                    name="mo"
                    components={components}
                    parentName="mrow"
                  >{`∑`}</MDXTag>
                  <MDXTag name="mrow" components={components} parentName="mrow">
                    <MDXTag
                      name="mn"
                      components={components}
                      parentName="mrow"
                    >{`1`}</MDXTag>
                  </MDXTag>
                </MDXTag>
                <MDXTag
                  name="annotation"
                  components={components}
                  parentName="semantics"
                  props={{ encoding: 'application/x-tex' }}
                >{`\sum{1}`}</MDXTag>
              </MDXTag>
            </MDXTag>
          </MDXTag>
          <MDXTag
            name="span"
            components={components}
            parentName="span"
            props={{ className: 'katex-html', ariaHidden: 'true' }}
          >
            <MDXTag
              name="span"
              components={components}
              parentName="span"
              props={{ className: 'strut', style: 'height:1.05em;' }}
            />
            <MDXTag
              name="span"
              components={components}
              parentName="span"
              props={{
                className: 'strut bottom',
                style: 'height:1.6000100000000002em;vertical-align:-0.55001em;',
              }}
            />
            <MDXTag
              name="span"
              components={components}
              parentName="span"
              props={{ className: 'base' }}
            >
              <MDXTag
                name="span"
                components={components}
                parentName="span"
                props={{
                  className: 'mop op-symbol large-op',
                  style: 'position:relative;top:-0.000004999999999977245em;',
                }}
              >{`∑`}</MDXTag>
              <MDXTag
                name="span"
                components={components}
                parentName="span"
                props={{
                  className: 'mord rule',
                  style: 'margin-right:0.16666666666666666em;',
                }}
              />
              <MDXTag
                name="span"
                components={components}
                parentName="span"
                props={{ className: 'mord' }}
              >
                <MDXTag
                  name="span"
                  components={components}
                  parentName="span"
                  props={{ className: 'mord' }}
                >{`1`}</MDXTag>
              </MDXTag>
            </MDXTag>
          </MDXTag>
        </MDXTag>
      </MDXTag>
    </MDXTag>
    <MDXTag name="div" components={components} props={{ className: 'math' }}>
      <MDXTag
        name="span"
        components={components}
        parentName="div"
        props={{ className: 'katex-display' }}
      >
        <MDXTag
          name="span"
          components={components}
          parentName="span"
          props={{ className: 'katex' }}
        >
          <MDXTag
            name="span"
            components={components}
            parentName="span"
            props={{ className: 'katex-mathml' }}
          >
            <MDXTag name="math" components={components} parentName="span">
              <MDXTag
                name="semantics"
                components={components}
                parentName="math"
              >
                <MDXTag
                  name="mrow"
                  components={components}
                  parentName="semantics"
                >
                  <MDXTag
                    name="mo"
                    components={components}
                    parentName="mrow"
                  >{`∑`}</MDXTag>
                  <MDXTag name="mrow" components={components} parentName="mrow">
                    <MDXTag
                      name="mi"
                      components={components}
                      parentName="mrow"
                    >{`i`}</MDXTag>
                  </MDXTag>
                </MDXTag>
                <MDXTag
                  name="annotation"
                  components={components}
                  parentName="semantics"
                  props={{ encoding: 'application/x-tex' }}
                >{`\sum{i}`}</MDXTag>
              </MDXTag>
            </MDXTag>
          </MDXTag>
          <MDXTag
            name="span"
            components={components}
            parentName="span"
            props={{ className: 'katex-html', ariaHidden: 'true' }}
          >
            <MDXTag
              name="span"
              components={components}
              parentName="span"
              props={{ className: 'strut', style: 'height:1.05em;' }}
            />
            <MDXTag
              name="span"
              components={components}
              parentName="span"
              props={{
                className: 'strut bottom',
                style: 'height:1.6000100000000002em;vertical-align:-0.55001em;',
              }}
            />
            <MDXTag
              name="span"
              components={components}
              parentName="span"
              props={{ className: 'base' }}
            >
              <MDXTag
                name="span"
                components={components}
                parentName="span"
                props={{
                  className: 'mop op-symbol large-op',
                  style: 'position:relative;top:-0.000004999999999977245em;',
                }}
              >{`∑`}</MDXTag>
              <MDXTag
                name="span"
                components={components}
                parentName="span"
                props={{
                  className: 'mord rule',
                  style: 'margin-right:0.16666666666666666em;',
                }}
              />
              <MDXTag
                name="span"
                components={components}
                parentName="span"
                props={{ className: 'mord' }}
              >
                <MDXTag
                  name="span"
                  components={components}
                  parentName="span"
                  props={{ className: 'mord mathit' }}
                >{`i`}</MDXTag>
              </MDXTag>
            </MDXTag>
          </MDXTag>
        </MDXTag>
      </MDXTag>
    </MDXTag>
  </MDXTag>
)

@silvenon
Copy link
Contributor

I closed this issue because I resolved the bug described in #145 (comment). @KrofDrakula I'll gladly investigate your issue once I get enough info to confirm it, in that case I'll reopen.

@KrofDrakula
Copy link
Author

Sorry, I'm AFK for the next couple of days, I may have missed something in my reproduction, like an older version of MDX, maybe. I'll see if this is still an issue with my setup when I can check it. Thank you!

@silvenon
Copy link
Contributor

silvenon commented Sep 20, 2018

@linonetwo released in v0.15.3-0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 type/bug This is a problem
Development

No branches or pull requests

4 participants