Add support of Mermaid

parent 6675bab5
...@@ -75,6 +75,7 @@ import './projects_dropdown'; ...@@ -75,6 +75,7 @@ import './projects_dropdown';
import './projects_list'; import './projects_list';
import './syntax_highlight'; import './syntax_highlight';
import './render_math'; import './render_math';
import './render_mermaid';
import './render_gfm'; import './render_gfm';
import './right_sidebar'; import './right_sidebar';
import './search'; import './search';
......
...@@ -2,12 +2,13 @@ ...@@ -2,12 +2,13 @@
// Render Gitlab flavoured Markdown // Render Gitlab flavoured Markdown
// //
// Delegates to syntax highlight and render math // Delegates to syntax highlight and render math & mermaid diagrams.
// //
(function() { (function() {
$.fn.renderGFM = function() { $.fn.renderGFM = function() {
this.find('.js-syntax-highlight').syntaxHighlight(); this.find('.js-syntax-highlight').syntaxHighlight();
this.find('.js-render-math').renderMath(); this.find('.js-render-math').renderMath();
this.find('.js-render-mermaid').renderMermaid();
return this; return this;
}; };
......
// Renders diagrams and flowcharts from text using Mermaid in any element with the
// `js-render-mermaid` class.
//
// Example markup:
//
// <pre class="js-render-mermaid">
// graph TD;
// A-- > B;
// A-- > C;
// B-- > D;
// C-- > D;
// </pre>
//
import Flash from './flash';
$.fn.renderMermaid = function renderMermaid() {
if (this.length === 0) return;
import(/* webpackChunkName: 'mermaid' */ 'blackst0ne-mermaid').then((mermaid) => {
mermaid.initialize({
loadOnStart: false,
theme: 'neutral',
});
mermaid.init(undefined, this);
}).catch((err) => {
Flash(`Can't load mermaid module: ${err}`);
});
};
---
title: 'Add support of Mermaid (generation of diagrams and flowcharts from text)'
merge_request: 15107
author: Vitaliy @blackst0ne Klachkov
type: added
# Touch the lexers so it is registered with Rouge
Rouge::Lexers::Math
# Touch the lexers so it is registered with Rouge
Rouge::Lexers::Plantuml
...@@ -368,6 +368,37 @@ _Be advised that KaTeX only supports a [subset][katex-subset] of LaTeX._ ...@@ -368,6 +368,37 @@ _Be advised that KaTeX only supports a [subset][katex-subset] of LaTeX._
>**Note:** >**Note:**
This also works for the asciidoctor `:stem: latexmath`. For details see the [asciidoctor user manual][asciidoctor-manual]. This also works for the asciidoctor `:stem: latexmath`. For details see the [asciidoctor user manual][asciidoctor-manual].
### Mermaid
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#mermaid
It is possible to generate diagrams and flowcharts from text using [Mermaid][mermaid].
In order to generate a diagram or flowchart, you should write your text inside the `mermaid` block.
Example:
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
Becomes:
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
For details see the [Mermaid official page][mermaid].
## Standard Markdown ## Standard Markdown
### Headers ### Headers
...@@ -814,6 +845,7 @@ A link starting with a `/` is relative to the wiki root. ...@@ -814,6 +845,7 @@ A link starting with a `/` is relative to the wiki root.
[^2]: This is my awesome footnote. [^2]: This is my awesome footnote.
[markdown.md]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md [markdown.md]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md
[mermaid]: https://mermaidjs.github.io/ "Mermaid website"
[rouge]: http://rouge.jneen.net/ "Rouge website" [rouge]: http://rouge.jneen.net/ "Rouge website"
[redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website" [redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website"
[katex]: https://github.com/Khan/KaTeX "KaTeX website" [katex]: https://github.com/Khan/KaTeX "KaTeX website"
......
module Banzai
module Filter
class MermaidFilter < HTML::Pipeline::Filter
def call
doc.css('pre[lang="mermaid"]').add_class('mermaid')
doc.css('pre[lang="mermaid"]').add_class('js-render-mermaid')
# The `<code></code>` blocks are added in the lib/banzai/filter/syntax_highlight_filter.rb
# We want to keep context and consistency, so we the blocks are added for all filters.
# Details: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/15107/diffs?diff_id=7962900#note_45495859
doc.css('pre[lang="mermaid"]').each do |pre|
document = pre.at('code')
document.replace(document.content)
end
doc
end
end
end
end
...@@ -14,23 +14,26 @@ module Banzai ...@@ -14,23 +14,26 @@ module Banzai
end end
def highlight_node(node) def highlight_node(node)
language = node.attr('lang')
code = node.text code = node.text
css_classes = "code highlight" css_classes = 'code highlight js-syntax-highlight'
lexer = lexer_for(language) language = node.attr('lang')
lang = lexer.tag
if use_rouge?(language)
begin lexer = lexer_for(language)
code = Rouge::Formatters::HTMLGitlab.format(lex(lexer, code), tag: lang) language = lexer.tag
css_classes << " js-syntax-highlight #{lang}" begin
rescue code = Rouge::Formatters::HTMLGitlab.format(lex(lexer, code), tag: language)
lang = nil css_classes << " #{language}"
# Gracefully handle syntax highlighter bugs/errors to ensure rescue
# users can still access an issue/comment/etc. # Gracefully handle syntax highlighter bugs/errors to ensure
# users can still access an issue/comment/etc.
language = nil
end
end end
highlighted = %(<pre class="#{css_classes}" lang="#{lang}" v-pre="true"><code>#{code}</code></pre>) highlighted = %(<pre class="#{css_classes}" lang="#{language}" v-pre="true"><code>#{code}</code></pre>)
# Extracted to a method to measure it # Extracted to a method to measure it
replace_parent_pre_element(node, highlighted) replace_parent_pre_element(node, highlighted)
...@@ -51,6 +54,10 @@ module Banzai ...@@ -51,6 +54,10 @@ module Banzai
# Replace the parent `pre` element with the entire highlighted block # Replace the parent `pre` element with the entire highlighted block
node.parent.replace(highlighted) node.parent.replace(highlighted)
end end
def use_rouge?(language)
%w(math mermaid plantuml).exclude?(language)
end
end end
end end
end end
...@@ -14,6 +14,7 @@ module Banzai ...@@ -14,6 +14,7 @@ module Banzai
Filter::SyntaxHighlightFilter, Filter::SyntaxHighlightFilter,
Filter::MathFilter, Filter::MathFilter,
Filter::MermaidFilter,
Filter::UploadLinkFilter, Filter::UploadLinkFilter,
Filter::VideoLinkFilter, Filter::VideoLinkFilter,
Filter::ImageLazyLoadFilter, Filter::ImageLazyLoadFilter,
......
module Rouge
module Lexers
class Math < PlainText
title "A passthrough lexer used for LaTeX input"
desc "PLEASE REFACTOR - this should be handled by SyntaxHighlightFilter"
tag 'math'
end
end
end
module Rouge
module Lexers
class Plantuml < PlainText
title "A passthrough lexer used for PlantUML input"
desc "PLEASE REFACTOR - this should be handled by SyntaxHighlightFilter"
tag 'plantuml'
end
end
end
...@@ -69,6 +69,12 @@ describe 'GitLab Markdown' do ...@@ -69,6 +69,12 @@ describe 'GitLab Markdown' do
end end
end end
it 'parses mermaid code block' do
aggregate_failures do
expect(doc).to have_selector('pre.code.js-render-mermaid')
end
end
it 'parses strikethroughs' do it 'parses strikethroughs' do
expect(doc).to have_selector(%{del:contains("and this text doesn't")}) expect(doc).to have_selector(%{del:contains("and this text doesn't")})
end end
......
...@@ -268,3 +268,37 @@ However the wrapping tags can not be mixed as such - ...@@ -268,3 +268,37 @@ However the wrapping tags can not be mixed as such -
### Videos ### Videos
![My Video](/assets/videos/gitlab-demo.mp4) ![My Video](/assets/videos/gitlab-demo.mp4)
### Mermaid
> If this is not rendered correctly, see
https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/user/markdown.md#mermaid
It is possible to generate diagrams and flowcharts from text using [Mermaid][mermaid].
In order to generate a diagram or flowchart, you should write your text inside the `mermaid` block.
Example:
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
Becomes:
```mermaid
graph TD;
A-->B;
A-->C;
B-->D;
C-->D;
```
For details see the [Mermaid official page][mermaid].
[mermaid]: https://mermaidjs.github.io/ "Mermaid website"
...@@ -4,8 +4,9 @@ ...@@ -4,8 +4,9 @@
import 'autosize'; import 'autosize';
import '~/gl_form'; import '~/gl_form';
import '~/lib/utils/text_utility'; import '~/lib/utils/text_utility';
import '~/render_gfm';
import '~/render_math'; import '~/render_math';
import '~/render_mermaid';
import '~/render_gfm';
import '~/notes'; import '~/notes';
(function() { (function() {
......
require 'spec_helper'
describe Banzai::Filter::MermaidFilter do
include FilterSpecHelper
it 'adds `js-render-mermaid` class to the `pre` tag' do
doc = filter("<pre class='code highlight js-syntax-highlight mermaid' lang='mermaid' v-pre='true'><code>graph TD;\n A--&gt;B;\n</code></pre>")
result = doc.xpath('descendant-or-self::pre').first
expect(result[:class]).to include('js-render-mermaid')
end
end
...@@ -31,7 +31,7 @@ describe Banzai::Filter::SyntaxHighlightFilter do ...@@ -31,7 +31,7 @@ describe Banzai::Filter::SyntaxHighlightFilter do
it "highlights as plaintext" do it "highlights as plaintext" do
result = filter('<pre><code lang="ruby">This is a test</code></pre>') result = filter('<pre><code lang="ruby">This is a test</code></pre>')
expect(result.to_html).to eq('<pre class="code highlight" lang="" v-pre="true"><code>This is a test</code></pre>') expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight" lang="" v-pre="true"><code>This is a test</code></pre>')
end end
end end
end end
...@@ -922,6 +922,17 @@ binary-extensions@^1.0.0: ...@@ -922,6 +922,17 @@ binary-extensions@^1.0.0:
version "1.10.0" version "1.10.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0"
blackst0ne-mermaid@^7.1.0-fixed:
version "7.1.0-fixed"
resolved "https://registry.yarnpkg.com/blackst0ne-mermaid/-/blackst0ne-mermaid-7.1.0-fixed.tgz#3707b3a113d78610e3068e18a588f46b4688de49"
dependencies:
d3 "3.5.17"
dagre-d3-renderer "^0.4.24"
dagre-layout "^0.8.0"
he "^1.1.1"
lodash "^4.17.4"
moment "^2.18.1"
blob@0.0.4: blob@0.0.4:
version "0.0.4" version "0.0.4"
resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921" resolved "https://registry.yarnpkg.com/blob/-/blob-0.0.4.tgz#bcf13052ca54463f30f9fc7e95b9a47630a94921"
...@@ -1638,6 +1649,10 @@ custom-event@~1.0.0: ...@@ -1638,6 +1649,10 @@ custom-event@~1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425"
d3@3.5.17:
version "3.5.17"
resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.17.tgz#bc46748004378b21a360c9fc7cf5231790762fb8"
d3@^3.5.11: d3@^3.5.11:
version "3.5.11" version "3.5.11"
resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.11.tgz#d130750eed0554db70e8432102f920a12407b69c" resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.11.tgz#d130750eed0554db70e8432102f920a12407b69c"
...@@ -1654,6 +1669,22 @@ d@^0.1.1: ...@@ -1654,6 +1669,22 @@ d@^0.1.1:
dependencies: dependencies:
es5-ext "~0.10.2" es5-ext "~0.10.2"
dagre-d3-renderer@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/dagre-d3-renderer/-/dagre-d3-renderer-0.4.24.tgz#b36ce2fe4ea20de43e7698627c6ede2a9f15ec45"
dependencies:
d3 "3.5.17"
dagre-layout "^0.8.0"
graphlib "^2.1.1"
lodash "^4.17.4"
dagre-layout@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/dagre-layout/-/dagre-layout-0.8.0.tgz#7147b6afb655602f855158dfea171db9aa98d4ff"
dependencies:
graphlib "^2.1.1"
lodash "^4.17.4"
dashdash@^1.12.0: dashdash@^1.12.0:
version "1.14.1" version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
...@@ -2852,6 +2883,12 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: ...@@ -2852,6 +2883,12 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725"
graphlib@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.1.tgz#42352c52ba2f4d035cb566eb91f7395f76ebc951"
dependencies:
lodash "^4.11.1"
gzip-size@3.0.0, gzip-size@^3.0.0: gzip-size@3.0.0, gzip-size@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-3.0.0.tgz#546188e9bdc337f673772f81660464b389dce520"
...@@ -2946,7 +2983,7 @@ hawk@~3.1.3: ...@@ -2946,7 +2983,7 @@ hawk@~3.1.3:
hoek "2.x.x" hoek "2.x.x"
sntp "1.x.x" sntp "1.x.x"
he@^1.1.0: he@^1.1.0, he@^1.1.1:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd"
...@@ -3942,7 +3979,7 @@ lodash@^3.8.0: ...@@ -3942,7 +3979,7 @@ lodash@^3.8.0:
version "3.10.1" version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
lodash@^4.0.0, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.0: lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.0:
version "4.17.4" version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
...@@ -4156,6 +4193,10 @@ moment@2.x: ...@@ -4156,6 +4193,10 @@ moment@2.x:
version "2.17.1" version "2.17.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.1.tgz#fed9506063f36b10f066c8b59a144d7faebe1d82" resolved "https://registry.yarnpkg.com/moment/-/moment-2.17.1.tgz#fed9506063f36b10f066c8b59a144d7faebe1d82"
moment@^2.18.1:
version "2.19.2"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.19.2.tgz#8a7f774c95a64550b4c7ebd496683908f9419dbe"
monaco-editor@0.10.0: monaco-editor@0.10.0:
version "0.10.0" version "0.10.0"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.10.0.tgz#6604932585fe9c1f993f000a503d0d20fbe5896a" resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.10.0.tgz#6604932585fe9c1f993f000a503d0d20fbe5896a"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment