skip to Main Content

I have installed a mermaid plugin for Gitbook via gitbook-plugin-mermaid-gb3, this plugin can parse code via markdown code block markup and translate it to a svg file, the code block is like below:

```mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
```

But when I use it I found for some code it will not working, after check I found it was a bug inside the plugin.

The code is come from index.js and related parse code listed below:

var mermaidRegex = /^```mermaid((.*[rn]+)+?)?```$/im;

function processMermaidBlockList(page) {

  var match;

  while ((match = mermaidRegex.exec(page.content))) {
    var rawBlock = match[0];
    var mermaidContent = match[1];
    page.content = page.content.replace(rawBlock, '<div class="mermaid">' +
      mermaidContent + '</div>');
  }

  return page;
}

The regex expression is /^```mermaid((.*[rn]+)+?)?```$/im,but it can only find code bock starts with “`mermaid,if there are space before or after it,it will not working

What I expected is like below

-- valid
```mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
```

-- valid, there can be space between ``` and mermaid
``` mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
```

-- valid, there can be space before or after ```
 ```mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
  ```
  
--invalid, there can not be have extra characters before ```
abc```mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
```  

--invalid, there can not be have extra characters before ```
abc ```mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
```  

--invalid, there can not be have extra characters before ```
abc ```mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
```  

--invalid, there can not be have extra characters after ```
```mermaid
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
```  abc

--invalid, there can not be have extra characters after mermaid
```mermaid abc
graph TD;
  A-->B;
  A-->C;
  B-->D;
  C-->D;
``` 

I changed /^```mermaid((.*[rn]+)+?)?```$/im to https://regex101.com/r/CIrooL/1 and test it via https://regex101.com/r/CIrooL/1,it seems okay,but not working inside javascript, I do not know why.

// this line will be blocked using the updated regex
while ((match = mermaidRegex.exec(page.content))) {
}

Can anyone help me,please?
Thanks in advance!

2

Answers


  1. Theissue might be that the while loopis onlymatching the code block onetime. To make sure you’re matching all the code blocks, you could try usingtheString.prototype.matchAll() method instead of whileloop with regex.exec().

    Here’s anexample of how you could use matchAll():

    const mermaidRegex = /s*```mermaid((.*[rn]+)+?)?```/gm;
    const matches = [...page.content.matchAll(mermaidRegex)];
    matches.forEach((match) => {
      const [rawBlock, mermaidContent] = match;
      const div = `<div class="mermaid">${mermaidContent}</div>`;
      page.content = page.content.replace(rawBlock, div);
    });
    

    This code matches all code blocks that starts with "“`mermaid" and handles thecases with extra spaces before, after or inside the opening/closing code block tags.

    You might also want tocheck if the page.contentis updatedand the newhtml code is appearingin the htmlfile on the local machineitself and not just in your markdown editoror browser as they might display cached version of the page.

    Login or Signup to reply.
  2. Instead of matching all those blocks and "raw" replacing each block an idea is to just do a global replacement. Also modify the regex to your needs like this (regex101):

    const mermaidRegex = /^[ t]*```s*mermaid[ t]*$([^`]*(?:`[^`]+)*)```$/igm;
    
    • The global flag g is for replacing each occurance
    • The m multiline flag is for making ^ match line-start and $ line-end
    • [ t]* will match any amount of spaces or tabs
    • ([^`]*(?:`[^`]+)*) captures the relevant part to the first group.
      The negated class matches any character other than a backtick.
      To allow single occurances of backticks the repeated group is used.

    Finally change your function:

    function processMermaidBlockList(page) {
      page.content = page.content.replace(mermaidRegex, '<div class="mermaid">$1</div>');
      return page;
    }
    

    Here is a JS demo at tio.run$1 in the replacement contains what’s captured by the first group.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search