(rehype-highlight) How to programmatically ignore certain code blocks? #154
-
I have some MDX pages that use rehype-highlight for syntax highlighting. I'd also like to use Sandpack to provide little runnable sandboxes, the way the React docs do (example, code). So I need for rehype-highlight to act on standalone code blocks, but not on code blocks that are inside a // test.mdx
# Test
```js
const foo = () => {
console.log('rehype-highlight should apply syntax highlighting here')
}
```
<Sandpack>
```js
const foo = () => {
console.log('rehype-highlight should not touch this')
}
```
</Sandpack> According to the rehype-highlight docs, you can add a But in spite of the I've made a CodeSandbox repro here: Is there a better way to programmatically get rehype-highlight to ignore code blocks that are inside a |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 6 replies
-
Welcome @HerbCaudill! 👋
Note that it expects This can be resolved by prepending the class with plugin source from sandboximport { serialize } from 'next-mdx-remote/serialize';
import rehypeHighlight from 'rehype-highlight';
import { visit } from 'unist-util-visit';
import { Plugin } from 'unified';
export const loadMdx = async (source: string) => {
const serialized = await serialize(source, {
mdxOptions: {
remarkPlugins: [],
rehypePlugins: [rehypeNoHighlightInSandbox, rehypeHighlight]
}
});
return serialized;
};
function rehypeNoHighlightInSandbox(): Plugin {
const addClass = (node: any, className: string) => {
node.properties = node.properties || {};
node.properties.className = node.properties.className || [];
if (typeof node.properties.className === 'string')
node.properties.className = [node.properties.className];
node.properties.className.unshift(className);
};
return (tree) => {
visit(tree, 'mdxJsxFlowElement', (node) => {
if (node.name === 'Sandpack') {
const preNodes = node.children.filter(
(child: any) => child.tagName === 'pre'
);
preNodes.forEach((preNode) => {
const codeNode = preNode.children[0];
addClass(codeNode, 'no-highlight');
});
console.log(JSON.stringify(node, null, 3));
}
});
};
}
Using a Open to discussion on whether |
Beta Was this translation helpful? Give feedback.
-
Ah sweet - that makes total sense. It might not hurt to emphasize in the docs that I get the internal logic now -- that I didn't understand that until now, and it explains behavior that had previously frustrated me, which is that a code block with no language tag would be left completely untouched. So I had to find another way to apply the My mental model was that tagging code as I'd suggest that the current approach muddles together two orthogonal concerns -- what language the code block is in, and whether you want the block to be touched at all. Here's how I would think about the intent represented by various combinations:
|
Beta Was this translation helpful? Give feedback.
Welcome @HerbCaudill! 👋
Sorry you ran into a spot of trouble.
Note that it expects
no-highlight
/nohighlight
to be the first, or the only class on the<code>
tag.Your plugin is adding it as the second and final.
Which means the language detector will choose the language you selected https://github.com/rehypejs/rehype-highlight/blob/81f7dd1c383ffe0d5432584c3a66d281bbe9aa84/lib/index.js#L157-L179
This can be resolved by prepending the class with
unshift
.Working example: https://codesandbox.io/p/sandbox/sandpack-vs-remark-rehype-forked-v6f7tr?file=%2Flib%2FloadMdx.…