remcohaszing / remark-mermaidjs

A remark plugin to render mermaid diagrams using playwright
MIT License
65 stars 7 forks source link

Add browser support #8

Closed elShailee closed 1 year ago

elShailee commented 1 year ago

Hey, I am trying to use this module to display MD files that uses the mermaid syntax in a React app using ReactMarkdown, but facing difficulties -

Basically - as soon as I import the module my app won't run and fail to compile with this error message -

Failed to compile.

./node_modules/remark-mermaidjs/index.js 8:28
Module parse failed: Unexpected token (8:28)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.       
| import { visit } from 'unist-util-visit';
| const mermaidScript = {
>   path: createRequire(import.meta.url).resolve('mermaid/dist/mermaid.min.js')
| };
| export const defaultSVGOOptions = {

The app run great without the module import, including the use of ReactMarkdown, which is pretty much copy of their documentation.

This is the code I am trying to use it in - (note that even if I don't use the remarkMermaid object in the ReactMarkdown component the app won't compile)

import styled from '@emotion/styled/macro';
import ReactMarkdown from 'react-markdown';
import remarkMermaid from 'remark-mermaidjs';
import { useHelpContext } from 'Apps/Help/HelpContext';

import { SyncLoader } from 'react-spinners';

export const MainPanel = () => {
    const { MDContent } = useHelpContext();

    return (
        <div style={{ height: '100%' }}>
            {MDContent !== 'loading' ? (
                <StyledMarkdownContainer>
                    <ReactMarkdown remarkPlugins={[remarkMermaid]}>{MDContent}</ReactMarkdown>
                </StyledMarkdownContainer>
            ) : (
                <LoaderContainer>
                    <SyncLoader color='#55a0b9' />
                </LoaderContainer>
            )}
        </div>
    );
};

const StyledMarkdownContainer = styled.div`
    padding: ${({ theme }) => theme.sizes.padding.XL};
    overflow: auto;
    height: 100%;
`;

const LoaderContainer = styled.div`
    height: 100%;
    ${({ theme }) => theme.centerItems}
`;

adding my package.json content - in case it's relevant:

{
    "name": "clientreact",
    "version": "6.3.34",
    "private": true,
    "dependencies": {
        "@emotion/core": "^11.0.0",
        "@emotion/css": "^11.1.3",
        "@emotion/react": "^11.4.0",
        "@emotion/styled": "^11.3.0",
        "@material-ui/core": "^5.0.0-alpha.31",
        "@material-ui/icons": "^4.11.2",
        "@material-ui/lab": "^4.0.0-alpha.57",
        "@material-ui/system": "^4.12.1",
        "@mui/icons-material": "^5.1.1",
        "@mui/lab": "^5.0.0-alpha.55",
        "@mui/material": "^5.1.1",
        "@mui/styles": "^5.1.1",
        "@reduxjs/toolkit": "^1.5.0",
        "@svgr/cli": "^5.5.0",
        "@testing-library/jest-dom": "^5.11.4",
        "@testing-library/react": "^11.1.0",
        "@testing-library/user-event": "^12.1.10",
        "@tisoap/react-flow-smart-edge": "^1.0.0",
        "autosuggest-highlight": "^3.2.0",
        "axios": "^0.21.1",
        "better-docs": "^2.3.2",
        "bootstrap": "5.1.3",
        "chart.js": "^3.2.1",
        "clsx": "^1.1.1",
        "dagre": "^0.8.5",
        "dnd-core": "^15.1.1",
        "dotenv": "^8.2.0",
        "file-loader": "^6.2.0",
        "gatsby-plugin-material-ui": "^3.0.1",
        "immutability-helper": "^3.1.1",
        "jsdoc": "^3.6.7",
        "lodash": "^4.17.21",
        "moment": "^2.29.1",
        "moment-timezone": "^0.5.34",
        "prop-types": "^15.7.2",
        "public-ip": "^4.0.4",
        "re-dropdown": "^1.0.2",
        "react": "^17.0.1",
        "react-bootstrap": "^2.0.0-rc.1",
        "react-chartjs-2": "^3.0.3",
        "react-contexify": "^5.0.0",
        "react-contextmenu": "^2.14.0",
        "react-copy-to-clipboard": "^5.0.3",
        "react-dnd": "^15.1.1",
        "react-dnd-html5-backend": "^15.1.2",
        "react-dom": "^17.0.2",
        "react-flow-renderer": "^10.3.7",
        "react-hook-form": "^7.11.1",
        "react-horizontal-stacked-bar-chart": "^8.15.2",
        "react-html-parser": "^2.0.2",
        "react-markdown": "^8.0.3",
        "react-modal": "^3.14.2",
        "react-player": "^2.9.0",
        "react-redux": "^7.2.2",
        "react-router-dom": "^5.2.0",
        "react-router-last-location": "^2.0.1",
        "react-scripts": "4.0.3",
        "react-select": "^5.1.0",
        "react-select-search": "^3.0.8",
        "react-spinners": "^0.11.0",
        "react-split": "^2.0.14",
        "react-spring": "^9.3.1",
        "react-table": "^7.7.0",
        "react-tippy": "^1.4.0",
        "react-toastify": "^8.1.1",
        "react-tooltip": "^4.2.21",
        "react-virtualized-auto-sizer": "^1.0.5",
        "react-window": "^1.8.6",
        "react-xml-viewer": "^1.3.0",
        "react.build": "^1.0.5",
        "redux-persist": "^6.0.0",
        "remark-mermaidjs": "^3.0.0",
        "use-http": "^1.0.26",
        "uuidv4": "^6.2.12",
        "validator": "^13.7.0",
        "web-vitals": "^1.0.1"
    },
    "scripts": {
        "start": "react-scripts start",
        "build": "set \"CI=false\" && react-scripts build",
        "build-linux": "react-scripts --openssl-legacy-provider build",
        "build-linux1": "react-scripts build",
        "test": "react-scripts test",
        "eject": "react-scripts eject",
        "format": "prettier --write ./src/**/*.{js,jsx}",
        "patch": "yarn version --no-git-tag-version --patch",
        "minor": "yarn version --no-git-tag-version --minor",
        "major": "yarn version --no-git-tag-version --major"
    },
    "eslintConfig": {
        "extends": [
            "react-app",
            "react-app/jest"
        ]
    },
    "browserslist": {
        "production": [
            ">0.2%",
            "not dead",
            "not op_mini all"
        ],
        "development": [
            "last 1 chrome version",
            "last 1 firefox version",
            "last 1 safari version"
        ]
    },
    "devDependencies": {
        "@emotion/babel-plugin": "^11.3.0",
        "@svgr/webpack": "^5.5.0",
        "babel-plugin-emotion": "^11.0.0",
        "babel-plugin-styled-components": "^1.12.0",
        "prettier": "2.2.1"
    }
}

I am running the app locally with yarn start on a Windows 10 machine, with Google Chrome Thanks in advance for any help!

remcohaszing commented 1 year ago

Thanks for the detailed issue! Currently this plugin doesn’t work in the browser. However, I would like to add support for this. I was planning on troubleshooting some other issues in this project this week, so I might as well look into this one.

elShailee commented 1 year ago

That would be really amazing if you could. but in case not - is there another way that I could make the mermaid-to-svg parse?

elShailee commented 1 year ago

and thanks for the blazing quick response!

remcohaszing commented 1 year ago

The current implementation runs mermaid in Chrome using puppeteer. This can’t be stubbed.

It’s actually pretty easy to add browser support. What I’m having issues with, is testing it. The only tool for the task that comes to mind is Karma, but it seems to be a bit outdated. Do you have an idea for a good testing framework?

Also I have a hunch maybe @ChristianMurphy has some ideas?

ChristianMurphy commented 1 year ago

This sounds closely related to https://github.com/remcohaszing/remark-mermaidjs/issues/3

My understanding is also that some fresh implementation would be needed to support the browser. But it should be fairly straight forward for browsers, and could potentially even be made to work at build time. (for an example, see vFile which serves up different implementations based off the environment it is being built/bundled for https://github.com/vfile/vfile/blob/5181b5d0be113a6cb698be123d1226aadcac720c/package.json#L35-L47)

What I’m having issues with, is testing it. The only tool for the task that comes to mind is Karma, but it seems to be a bit outdated. Do you have an idea for a good testing framework?

Even if it isn't used at runtime, Puppeteer could still be used at testing time, and has integrations with Jest https://jestjs.io/docs/puppeteer

Or, @playwright/test could be used as an alternative https://playwright.dev/docs/writing-tests

ChristianMurphy commented 1 year ago

Another possibility is https://japa.dev/docs, which competes with Jest. But solves some key pain points for unified adopters who have tried Jest like: ESM support and C8 support.

TomKlotzPro commented 1 year ago

Hello Team!

I encounter the same issue here, we want to add mermaid on remark for our react application ( we are using React-Markdown ).

If you need hands about testing don't hesitate!

Did you think about using Jest + Cypress ?

remcohaszing commented 1 year ago

The problem with tools like Playwright and Puppeteer is that they’re tools that focus on automating the browser, not running tests inside the browser. This means the tests need to spin up a server, this server needs to bundle the JavaScript that runs the code to test, then the test framework can only access that page and make assertions about it. I was hoping for a more integrated solution.

Anyway, I appreciate the feedback. I’ll probably go with Playwright and esbuild serve.

I expect (but don’t promise) to fix and release this tomorrow.

remcohaszing commented 1 year ago

I think this is solved by #9. The test setup has become quite unique though. I would appreciate a review, but I’ll release it this week regardless.

elShailee commented 1 year ago

thank you! I think I'm kinda underqualified, but I tried my best as far as reviews go, for what it's worth...

TomKlotzPro commented 1 year ago

Same here 😞

elShailee commented 1 year ago

Hey Thanks for the amazing support! I notice you merged the browser support, but did not advance the package version, Which means (to the best of my understanding) that the new changes are not yet available via npm/yarn. is that intentional?

remcohaszing commented 1 year ago

I was just about to release when you posted that. Browser support is now available as of version 3.1.0 :tada: