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

getting rehypePrism and rehypeSanitize plugins to work at the same time #585

Open
isimmons opened this issue Oct 27, 2023 · 1 comment
Open

Comments

@isimmons
Copy link

I have separate components. One for creating new markdown and another for viewing saved markdowns on a separate page.

This is in a nextjs app but I don't think it's a next problem.

If I use rehypePrism it works. If I use rehypeSanitize it works. But if I use them both, then the prism classes don't get added to the output.

I worked around it in my viewer component by sanitizing the data before feeding it to the viewer but would rather not have to work around it like this and don't know how to do the same with the editor

MarkDownEditor.tsx

'use client';
import MDEditor from '@uiw/react-md-editor';
import rehypeSanitize from 'rehype-sanitize';
import rehypePrism from 'rehype-prism-plus';
import { forwardRef } from 'react';

export type MarkDownEditorProps = {
  name: string;
  value: string;
  onChange: (...event: any[]) => void;
  onBlur: () => void;
};

const MarkDownEditor = forwardRef<HTMLTextAreaElement, MarkDownEditorProps>(
  ({ name, value, onChange, onBlur }, ref) => {
    MarkDownEditor.displayName = 'MarkDownEditor';
    return (
      <div className="container">
        <MDEditor
          ref={ref}
          onBlur={onBlur}
          value={value}
          onChange={onChange}
          textareaProps={{
            id: name,
            name: name,
            placeholder: 'Yo, you got issues?',
          }}
          preview="edit"
          previewOptions={{
            rehypePlugins: [[rehypeSanitize]],
          }}
          components={{
            toolbar: (command, disabled, executeCommand) => {
              if (command.keyCommand === 'code') {
                return (
                  <button
                    aria-label="Insert code"
                    disabled={disabled}
                    onClick={event => {
                      event.stopPropagation();
                      executeCommand(command, command.groupName);
                    }}
                  >
                    Code
                  </button>
                );
              }
            },
          }}
        />
      </div>
    );
  },
);

export default MarkDownEditor;

MarkDownViewer.tsx

'use client';
import { useEffect, useState } from 'react';
import MDEditor from '@uiw/react-md-editor';
import rehypePrism from 'rehype-prism-plus';
import rehypeSanitize from 'rehype-sanitize';
import rehypeParse from 'rehype-parse';
import rehypeStringify from 'rehype-stringify';
import { unified } from 'unified';

export type MarkDownViewerProps = {
  source: string;
};

const MarkDownViewer = ({ source }: MarkDownViewerProps) => {
  const [cleanSource, setCleanSource] = useState('foo');
  useEffect(() => {
    const getCleanSource = async () => {
      const data = await unified()
        .use(rehypeParse, { fragment: true })
        .use(rehypeSanitize)
        .use(rehypeStringify)
        .process(source);

      setCleanSource(String(data));
    };

    getCleanSource().catch(console.error);
  }, [source]);
  return (
    <div className="p-1 px-4">
      <MDEditor.Markdown
        source={cleanSource}
        rehypePlugins={[[rehypePrism, { ignoreMissing: true }]]}
      />
    </div>
  );
};

export default MarkDownViewer;

Is there an option to tell the editor which order to run the plugins in so it can run through sanitize and then through prism? Any ideas why prism isn't processing if I try to use both plugins?

Thanks

@isimmons
Copy link
Author

So if I put them in order this way in the editor, it is working but with a little bit of delay. I guess that's expected because of all that processing for every key typed. Order is important. If I place rehypeSanitize first then rehypePrism doesn't work.

rehypePlugins: [
    [rehypePrism, { ignoreMissing: true }, rehypeSanitize],
],

But the same doesn't work in my MarkDownViewer component. rehypePrizm first means no sanitizing. It seems like a race condition like plugins should be ran in order and async before anything is output to the viewer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant