timlrx / rehype-prism-plus

rehype plugin to highlight code blocks in HTML with Prism (via refractor) with line highlighting and line numbers
MIT License
176 stars 19 forks source link

Issues with providing highlighted lines #20

Closed Fox32 closed 2 years ago

Fox32 commented 2 years ago

I have trouble to use the highlighted lines and showLineNumbers feature.

```js {1,3-4} showLineNumbers
function fancyAlert(arg) {
  if (arg) {
    $.facebox({ div: '#foo' })
  }
}
```

In general the line numbers work, if I force showLineNumbers on plugin creation. I'm using next-mdx-remote.

I played around a little bit and build myself a small plugin that prints the HAST before rehype-prism-plus is executed. I'm not a rehype or remark expert at all! This is what my HAST looks like:

{
  type: 'element',
  tagName: 'code',
  properties: {
    className: [ 'language-js' ],
    metastring: '{1,3-4} showLineNumbers',
    '{1,3-4}': true,
    showLineNumbers: true
  },
  children: [
    {
      type: 'text',
      value: 'function fancyAlert(arg) {\n' +
        '  if (arg) {\n' +
        "    $.facebox({ div: '#foo' })\n" +
        '  }\n' +
        '}\n'
    }
  ],
  position: {
    start: { line: 6, column: 1, offset: 40 },
    end: { line: 12, column: 4, offset: 150 }
  }
}

The issue seems to be, that a property called data is expected that should contain the meta, but instead I have a metastring property as part of properties.

I have no idea if that problem is on my side, or incompatible packages, or if we should just fix it here (by supporting both). For now I solve this using a plugin on my side, that I run before this plugin:

const fixMetaPlugin = (options = {}) => {
  return (tree) => {
    visit(tree, 'element', visitor);
  };

  function visitor(node, index, parent) {
    if (!parent || parent.tagName !== 'pre' || node.tagName !== 'code') {
      return;
    }

    node.data = { ...node.data, meta: node.properties.metastring };
  }
};
timlrx commented 2 years ago

Yes, the issue is highlighted here as well: https://github.com/timlrx/rehype-prism-plus/issues/18

next-mdx-remote is using mdx v1 which is slightly different in format than xdm or mdx v2. Thanks for figuring it out and finding a work around! Will include that info in the readme as well to avoid confusion from future users.

I think it is best to use that work around and wait for next-mdx-remote to upgrade to mdx v2 or use mdx-bundler.

Fox32 commented 2 years ago

Ah perfect, then it's best to wait for it. For everyone else having the issue now the workaround above should be sufficient.

Feel free to close this issue once it's mentioned in the readme.

timlrx commented 2 years ago

Updated readme with the workaround.

Schachte commented 2 years ago

@Fox32 Do you have an example of using and applying this plugin? I attempted to add, but not getting the linenumbers to show up. @timlrx , is there a reference guide for migrating from next-mdx-remote to mdx-bundler anywhere?

timlrx commented 2 years ago

Take a look at an example of using the plugin with mdx-bundler over here - https://github.com/timlrx/tailwind-nextjs-starter-blog/blob/master/lib/mdx.js#L85

Here is an example with showLineNumbers.

No, I do not have a migration guide but the code above should give you a good idea of what's needed to get mdx-bundler working.

Schachte commented 2 years ago

@timlrx Got it working, thanks so much!

rimzzlabs commented 1 year ago

hi @timlrx , This is a great rehype plugins. I'm using next-mdx-remote and next 13 with app directory how can I pass a file name to code block like the following example from next.js blog?

image

I want to do it like so

`\`\`ts filename="@/store/atom.ts"
import { atom } from 'jotai'

const foodsAtom = useAtom(["Banana", "Apple"])
`\`\`

but in my CodeBlock component, I didn't receive the filename props

kkn1125 commented 12 months ago

Hi @rizkimcitra , i just commenting to share my solution if you haven't solved it yet. I am also using next-mdx-remote.

I suggest you try using rehype-mdx-code-props.

Below is an example of some of the code I applied.

import rehypeMdxCodeProps from "rehype-mdx-code-props";

serialize(source.trim(), {
  parseFrontmatter: true,
  mdxOptions: {
    remarkPlugins: [remarkGfm, remarkBreaks],
    rehypePlugins: [
      rehypeSlug,
      rehypePrism,
      [rehypeAutolinkHeadings, { properties: { className: ["anchor"] } }],
      rehypeMdxCodeProps,
    ],
    format: "mdx",
    development: process.env.NODE_ENV !== "production",
  },
});

Note that rehypeMdxCodeProps must be added to the array as the last element for other plugins to work.

Additionally, if you get a token related error during compile, you can fix the part where you specify the attributes of the codeblock in key=value format.

Hope this helps you solve your problem :)

Hi @timlrx , I commented on an issue that has already been resolved, I just wanted to make helpful. I apologize if it was intrusive.

This comment is a translation. There may be something incorrect.