mermaid-js / mermaid-cli

Command line tool for the Mermaid library
MIT License
2.52k stars 238 forks source link

Empty diagram generation. #724

Open arthurbrenno opened 3 months ago

arthurbrenno commented 3 months ago

Describe the bug I'm trying to generate a mermaid diagram from an ouput. The output generates valid mermaid diagram in mermaid.live, but the generated output using the cli just gives me a diagram with no text.

To Reproduce Execute this function:

def mermaid_to_base64(
    mermaid_string: str,
    width: int = 2048,
    height: int = 2048,
    scale: float = 3.0,
    background_color: str = "transparent",
) -> str:
    def preprocess_mermaid_string(mermaid_string: str) -> str:
        """
        Preprocesses the Mermaid string to handle quote escaping and remove accents.
        """
        try:
            data = json.loads(mermaid_string)
            mermaid_string = data
        except json.JSONDecodeError:
            pass

        mermaid_string = mermaid_string.replace('\\"', '"')

        # Remove accents
        mermaid_string = "".join(
            c
            for c in unicodedata.normalize("NFD", mermaid_string)
            if unicodedata.category(c) != "Mn"
        )

        return mermaid_string

    logger.debug("Original mermaid string: %s", mermaid_string)
    mermaid_string = preprocess_mermaid_string(mermaid_string)
    logger.debug("Preprocessed mermaid string: %s", mermaid_string)

    # Create temporary files for input and output
    with tempfile.NamedTemporaryFile(
        mode="w", suffix=".mmd", delete=False
    ) as input_file, tempfile.NamedTemporaryFile(
        mode="wb", suffix=".png", delete=False
    ) as output_file:
        # Write the Mermaid string to the input file
        input_file.write(mermaid_string)
        input_file.flush()

        # Close the files to ensure all data is written
        input_file.close()
        output_file.close()

        try:
            # Run mmdc (Mermaid CLI) command with additional parameters
            subprocess.run(
                [
                    "mmdc",
                    "-i",
                    input_file.name,
                    "-o",
                    output_file.name,
                    "-b",
                    background_color,
                    "-w",
                    str(width),
                    "-H",
                    str(height),
                    "-s",
                    str(scale),
                ],
                check=True,
                capture_output=True,
                text=True,
            )

            # Read the output PNG file and encode it to base64
            with open(output_file.name, "rb") as f:
                image_data = f.read()
                base64_encoded = base64.b64encode(image_data).decode("utf-8")

            return base64_encoded

        except subprocess.CalledProcessError as e:
            logger.error(f"Error running Mermaid CLI: {e.stderr}")
            raise
        finally:
            # Clean up temporary files
            os.unlink(input_file.name)
            os.unlink(output_file.name)

    return ""

Expected behavior To generate a mermaid diagram with the original text in it.

Screenshots any diagram will look like this: image

I'm using mmdc 10.3.1, NixOS (Google IDX) with pkgs.mermaid-cli.

Additional context Add any other context about the problem here.

Mo-way commented 3 months ago

I think this is a duplicate of: https://github.com/mermaid-js/mermaid-cli/issues/691

TLDR:

It looks like this is an issue with mermaid-cli after all: [Mermaid's] SVG uses foreignObject to embed HTML text. Supporting this would basically involve having a whole HTML renderer inside librsvg. Please tell mermaid-cli to use SVG text elements instead.

pbittencourt commented 1 month ago

Sorry, I still don't understand, @Mo-way. Is this a solution?

Please tell mermaid-cli to use SVG text elements instead.

In this case, how can I instruct mermaid-cli to do this?

aloisklink commented 1 month ago

Hi @pbittencourt, you might have some luck by following https://github.com/mermaid-js/mermaid/issues/2688#issuecomment-1242762992

Some diagrams have a htmlLabels: false config setting that you can pass that might stop them from using <foreignObject>/embedded HTML.

However, even if you do do this, some Mermaid diagrams still use CSS which is valid in the SVG 2.0, but isn't valid in SVG 1.1 that many libraries like librsvg (see https://github.com/mermaid-js/mermaid/issues/2102)

As a work-around, you could try asking mermaid-cli to make a PDF file, then using a tool like pdf2svg to create an SVG file from that PDF: https://github.com/mermaid-js/mermaid/issues/2102#issuecomment-2183791698