>/g,function(){return n}),"m"),greedy:!0,inside:{info:{pattern:/^[^#$%]+/,alias:"punctuation",inside:{user:/^[^\s@:$#%*!/\\]+@[^\r\n@:$#%*!/\\]+/,punctuation:/:/,path:/[\s\S]+/}},bash:{pattern:/(^[$#%]\s*)\S[\s\S]*/,lookbehind:!0,alias:"language-bash",inside:s.languages.bash},"shell-symbol":{pattern:/^[$#%]/,alias:"important"}}},output:/.(?:.*(?:[\r\n]|.$))*/},s.languages["sh-session"]=s.languages.shellsession=s.languages["shell-session"]}(Prism);
\ No newline at end of file
diff --git a/components/prism-systemd.js b/components/prism-systemd.js
new file mode 100644
index 0000000000..1c48bfe7ed
--- /dev/null
+++ b/components/prism-systemd.js
@@ -0,0 +1,74 @@
+// https://www.freedesktop.org/software/systemd/man/systemd.syntax.html
+
+(function (Prism) {
+
+ var comment = {
+ pattern: /^[;#].*/m,
+ greedy: true
+ };
+
+ var quotesSource = /"(?:[^\r\n"\\]|\\(?:[^\r]|\r\n?))*"(?!\S)/.source;
+
+ Prism.languages.systemd = {
+ 'comment': comment,
+
+ 'section': {
+ pattern: /^\[[^\n\r\[\]]*\](?=[ \t]*$)/m,
+ greedy: true,
+ inside: {
+ 'punctuation': /^\[|\]$/,
+ 'section-name': {
+ pattern: /[\s\S]+/,
+ alias: 'selector'
+ },
+ }
+ },
+
+ 'key': {
+ pattern: /^[^\s=]+(?=[ \t]*=)/m,
+ greedy: true,
+ alias: 'attr-name'
+ },
+ 'value': {
+ // This pattern is quite complex because of two properties:
+ // 1) Quotes (strings) must be preceded by a space. Since we can't use lookbehinds, we have to "resolve"
+ // the lookbehind. You will see this in the main loop where spaces are handled separately.
+ // 2) Line continuations.
+ // After line continuations, empty lines and comments are ignored so we have to consume them.
+ pattern: RegExp(
+ /(=[ \t]*(?!\s))/.source +
+ // the value either starts with quotes or not
+ '(?:' + quotesSource + '|(?=[^"\r\n]))' +
+ // main loop
+ '(?:' + (
+ /[^\s\\]/.source +
+ // handle spaces separately because of quotes
+ '|' + '[ \t]+(?:(?![ \t"])|' + quotesSource + ')' +
+ // line continuation
+ '|' + /\\[\r\n]+(?:[#;].*[\r\n]+)*(?![#;])/.source
+ ) +
+ ')*'
+ ),
+ lookbehind: true,
+ greedy: true,
+ alias: 'attr-value',
+ inside: {
+ 'comment': comment,
+ 'quoted': {
+ pattern: RegExp(/(^|\s)/.source + quotesSource),
+ lookbehind: true,
+ greedy: true,
+ },
+ 'punctuation': /\\$/m,
+
+ 'boolean': {
+ pattern: /^(?:false|no|off|on|true|yes)$/,
+ greedy: true
+ }
+ }
+ },
+
+ 'operator': /=/
+ };
+
+}(Prism));
diff --git a/components/prism-systemd.min.js b/components/prism-systemd.min.js
new file mode 100644
index 0000000000..694cc4fbbc
--- /dev/null
+++ b/components/prism-systemd.min.js
@@ -0,0 +1 @@
+!function(e){var t={pattern:/^[;#].*/m,greedy:!0},n='"(?:[^\r\n"\\\\]|\\\\(?:[^\r]|\r\n?))*"(?!\\S)';Prism.languages.systemd={comment:t,section:{pattern:/^\[[^\n\r\[\]]*\](?=[ \t]*$)/m,greedy:!0,inside:{punctuation:/^\[|\]$/,"section-name":{pattern:/[\s\S]+/,alias:"selector"}}},key:{pattern:/^[^\s=]+(?=[ \t]*=)/m,greedy:!0,alias:"attr-name"},value:{pattern:RegExp("(=[ \t]*(?!\\s))(?:"+n+'|(?=[^"\r\n]))(?:[^\\s\\\\]|[ \t]+(?:(?![ \t"])|'+n+")|\\\\[\r\n]+(?:[#;].*[\r\n]+)*(?![#;]))*"),lookbehind:!0,greedy:!0,alias:"attr-value",inside:{comment:t,quoted:{pattern:RegExp("(^|\\s)"+n),lookbehind:!0,greedy:!0},punctuation:/\\$/m,boolean:{pattern:/^(?:false|no|off|on|true|yes)$/,greedy:!0}}},operator:/=/}}();
\ No newline at end of file
diff --git a/examples/prism-avro-idl.html b/examples/prism-avro-idl.html
new file mode 100644
index 0000000000..d6572b7130
--- /dev/null
+++ b/examples/prism-avro-idl.html
@@ -0,0 +1,44 @@
+Full example
+// Source: https://avro.apache.org/docs/current/idl.html#example
+
+/**
+ * An example protocol in Avro IDL
+ */
+@namespace("org.apache.avro.test")
+protocol Simple {
+
+ @aliases(["org.foo.KindOf"])
+ enum Kind {
+ FOO,
+ BAR, // the bar enum value
+ BAZ
+ }
+
+ fixed MD5(16);
+
+ record TestRecord {
+ @order("ignore")
+ string name;
+
+ @order("descending")
+ Kind kind;
+
+ MD5 hash;
+
+ union { MD5, null} @aliases(["hash"]) nullableHash;
+
+ array<long> arrayOfLongs;
+ }
+
+ error TestError {
+ string message;
+ }
+
+ string hello(string greeting);
+ TestRecord echo(TestRecord `record`);
+ int add(int arg1, int arg2);
+ bytes echoBytes(bytes data);
+ void `error`() throws TestError;
+ void ping() oneway;
+}
+
diff --git a/examples/prism-gn.html b/examples/prism-gn.html
new file mode 100644
index 0000000000..d0a7fa7200
--- /dev/null
+++ b/examples/prism-gn.html
@@ -0,0 +1,24 @@
+Full example
+# Source: https://gn.googlesource.com/gn/+/main/docs/cross_compiles.md
+
+declare_args() {
+ # Applies only to toolchains targeting target_cpu.
+ sysroot = ""
+}
+
+config("my_config") {
+ # Uses current_cpu because compile flags are toolchain-dependent.
+ if (current_cpu == "arm") {
+ defines = [ "CPU_IS_32_BIT" ]
+ } else {
+ defines = [ "CPU_IS_64_BIT" ]
+ }
+ # Compares current_cpu with target_cpu to see whether current_toolchain
+ # has the same architecture as target_toolchain.
+ if (sysroot != "" && current_cpu == target_cpu) {
+ cflags = [
+ "-isysroot",
+ sysroot,
+ ]
+ }
+}
diff --git a/examples/prism-mermaid.html b/examples/prism-mermaid.html
new file mode 100644
index 0000000000..c379bf27b5
--- /dev/null
+++ b/examples/prism-mermaid.html
@@ -0,0 +1,25 @@
+Full example
+%% https://github.com/mermaid-js/mermaid/blob/develop/docs/examples.md#larger-flowchart-with-some-styling
+
+graph TB
+ sq[Square shape] --> ci((Circle shape))
+
+ subgraph A
+ od>Odd shape]-- Two line<br/>edge comment --> ro
+ di{Diamond with <br/> line break} -.-> ro(Rounded<br>square<br>shape)
+ di==>ro2(Rounded square shape)
+ end
+
+ %% Notice that no text in shape are added here instead that is appended further down
+ e --> od3>Really long text with linebreak<br>in an Odd shape]
+
+ %% Comments after double percent signs
+ e((Inner / circle<br>and some odd <br>special characters)) --> f(,.?!+-*ز)
+
+ cyr[Cyrillic]-->cyr2((Circle shape Начало));
+
+ classDef green fill:#9f6,stroke:#333,stroke-width:2px;
+ classDef orange fill:#f96,stroke:#333,stroke-width:4px;
+ class sq,e green
+ class di orange
+
diff --git a/examples/prism-systemd.html b/examples/prism-systemd.html
new file mode 100644
index 0000000000..082ff8b54d
--- /dev/null
+++ b/examples/prism-systemd.html
@@ -0,0 +1,20 @@
+Full example
+# Source: https://www.freedesktop.org/software/systemd/man/systemd.syntax.html
+
+[Section A]
+KeyOne=value 1
+KeyTwo=value 2
+
+# a comment
+
+[Section B]
+Setting="something" "some thing" "…"
+KeyTwo=value 2 \
+ value 2 continued
+
+[Section C]
+KeyThree=value 3\
+# this line is ignored
+; this line is ignored too
+ value 3 continued
+
diff --git a/plugins/autoloader/prism-autoloader.js b/plugins/autoloader/prism-autoloader.js
index b8b5343175..ddefe74218 100644
--- a/plugins/autoloader/prism-autoloader.js
+++ b/plugins/autoloader/prism-autoloader.js
@@ -172,6 +172,7 @@
"js": "javascript",
"g4": "antlr4",
"adoc": "asciidoc",
+ "avdl": "avro-idl",
"shell": "bash",
"shortcode": "bbcode",
"rbnf": "bnf",
@@ -189,6 +190,7 @@
"xlsx": "excel-formula",
"xls": "excel-formula",
"gamemakerlanguage": "gml",
+ "gni": "gn",
"hbs": "handlebars",
"hs": "haskell",
"idr": "idris",
diff --git a/plugins/autoloader/prism-autoloader.min.js b/plugins/autoloader/prism-autoloader.min.js
index 7c2cd3e0ee..d5ca7c04dd 100644
--- a/plugins/autoloader/prism-autoloader.min.js
+++ b/plugins/autoloader/prism-autoloader.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document){var l={javascript:"clike",actionscript:"javascript",apex:["clike","sql"],arduino:"cpp",aspnet:["markup","csharp"],birb:"clike",bison:"c",c:"clike",csharp:"clike",cpp:"c",cfscript:"clike",chaiscript:["clike","cpp"],coffeescript:"javascript",crystal:"ruby","css-extras":"css",d:"clike",dart:"clike",django:"markup-templating",ejs:["javascript","markup-templating"],etlua:["lua","markup-templating"],erb:["ruby","markup-templating"],fsharp:"clike","firestore-security-rules":"clike",flow:"javascript",ftl:"markup-templating",gml:"clike",glsl:"c",go:"clike",groovy:"clike",haml:"ruby",handlebars:"markup-templating",haxe:"clike",hlsl:"c",idris:"haskell",java:"clike",javadoc:["markup","java","javadoclike"],jolie:"clike",jsdoc:["javascript","javadoclike","typescript"],"js-extras":"javascript",json5:"json",jsonp:"json","js-templates":"javascript",kotlin:"clike",latte:["clike","markup-templating","php"],less:"css",lilypond:"scheme",liquid:"markup-templating",markdown:"markup","markup-templating":"markup",mongodb:"javascript",n4js:"javascript",objectivec:"c",opencl:"c",parser:"markup",php:"markup-templating",phpdoc:["php","javadoclike"],"php-extras":"php",plsql:"sql",processing:"clike",protobuf:"clike",pug:["markup","javascript"],purebasic:"clike",purescript:"haskell",qsharp:"clike",qml:"javascript",qore:"clike",racket:"scheme",jsx:["markup","javascript"],tsx:["jsx","typescript"],reason:"clike",ruby:"clike",sass:"css",scss:"css",scala:"java","shell-session":"bash",smarty:"markup-templating",solidity:"clike",soy:"markup-templating",sparql:"turtle",sqf:"clike",squirrel:"clike","t4-cs":["t4-templating","csharp"],"t4-vb":["t4-templating","vbnet"],tap:"yaml",tt2:["clike","markup-templating"],textile:"markup",twig:"markup",typescript:"javascript",v:"clike",vala:"clike",vbnet:"basic",velocity:"markup",wiki:"markup",xeora:"markup","xml-doc":"markup",xquery:"markup"},n={html:"markup",xml:"markup",svg:"markup",mathml:"markup",ssml:"markup",atom:"markup",rss:"markup",js:"javascript",g4:"antlr4",adoc:"asciidoc",shell:"bash",shortcode:"bbcode",rbnf:"bnf",oscript:"bsl",cs:"csharp",dotnet:"csharp",cfc:"cfscript",coffee:"coffeescript",conc:"concurnas",jinja2:"django","dns-zone":"dns-zone-file",dockerfile:"docker",gv:"dot",eta:"ejs",xlsx:"excel-formula",xls:"excel-formula",gamemakerlanguage:"gml",hbs:"handlebars",hs:"haskell",idr:"idris",gitignore:"ignore",hgignore:"ignore",npmignore:"ignore",webmanifest:"json",kt:"kotlin",kts:"kotlin",kum:"kumir",tex:"latex",context:"latex",ly:"lilypond",emacs:"lisp",elisp:"lisp","emacs-lisp":"lisp",md:"markdown",moon:"moonscript",n4jsd:"n4js",nani:"naniscript",objc:"objectivec",qasm:"openqasm",objectpascal:"pascal",px:"pcaxis",pcode:"peoplecode",pq:"powerquery",mscript:"powerquery",pbfasm:"purebasic",purs:"purescript",py:"python",qs:"qsharp",rkt:"racket",rpy:"renpy",robot:"robotframework",rb:"ruby","sh-session":"shell-session",shellsession:"shell-session",smlnj:"sml",sol:"solidity",sln:"solution-file",rq:"sparql",t4:"t4-cs",trig:"turtle",ts:"typescript",tsconfig:"typoscript",uscript:"unrealscript",uc:"unrealscript",url:"uri",vb:"visual-basic",vba:"visual-basic",mathematica:"wolfram",nb:"wolfram",wl:"wolfram",xeoracube:"xeora",yml:"yaml"},p={},e="components/",a=Prism.util.currentScript();if(a){var r=/\bplugins\/autoloader\/prism-autoloader\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i,s=/(^|\/)[\w-]+\.(?:min\.)?js(?:\?[^\r\n/]*)?$/i,i=a.getAttribute("data-autoloader-path");if(null!=i)e=i.trim().replace(/\/?$/,"/");else{var t=a.src;r.test(t)?e=t.replace(r,"components/"):s.test(t)&&(e=t.replace(s,"$1components/"))}}var o=Prism.plugins.autoloader={languages_path:e,use_minified:!0,loadLanguages:m};Prism.hooks.add("complete",function(e){var a=e.element,r=e.language;if(a&&r&&"none"!==r){var s=function(e){var a=(e.getAttribute("data-dependencies")||"").trim();if(!a){var r=e.parentElement;r&&"pre"===r.tagName.toLowerCase()&&(a=(r.getAttribute("data-dependencies")||"").trim())}return a?a.split(/\s*,\s*/g):[]}(a);/^diff-./i.test(r)?(s.push("diff"),s.push(r.substr("diff-".length))):s.push(r),s.every(u)||m(s,function(){Prism.highlightElement(a)})}})}function u(e){if(0<=e.indexOf("!"))return!1;if((e=n[e]||e)in Prism.languages)return!0;var a=p[e];return a&&!a.error&&!1===a.loading}function m(e,a,r){"string"==typeof e&&(e=[e]);var s=e.length,i=0,t=!1;function c(){t||++i===s&&a&&a(e)}0!==s?e.forEach(function(e){!function(a,r,s){var i=0<=a.indexOf("!");function e(){var e=p[a];e||(e=p[a]={callbacks:[]}),e.callbacks.push({success:r,error:s}),!i&&u(a)?k(a,"success"):!i&&e.error?k(a,"error"):!i&&e.loading||(e.loading=!0,e.error=!1,function(e,a,r){var s=document.createElement("script");s.src=e,s.async=!0,s.onload=function(){document.body.removeChild(s),a&&a()},s.onerror=function(){document.body.removeChild(s),r&&r()},document.body.appendChild(s)}(function(e){return o.languages_path+"prism-"+e+(o.use_minified?".min":"")+".js"}(a),function(){e.loading=!1,k(a,"success")},function(){e.loading=!1,e.error=!0,k(a,"error")}))}a=a.replace("!",""),a=n[a]||a;var t=l[a];t&&t.length?m(t,e,s):e()}(e,c,function(){t||(t=!0,r&&r(e))})}):a&&setTimeout(a,0)}function k(e,a){if(p[e]){for(var r=p[e].callbacks,s=0,i=r.length;s
-
+
+
+ How to use
+
+ This plugin adds a special class for every keyword, so keyword-specific styles can be applied. These special classes allow for fine-grained control over the appearance of keywords using your own CSS rules.
+
+ For example, the keyword if
will have the class keyword-if
added. A CSS rule used to apply special highlighting could look like this:
+
+ .token.keyword.keyword-if { /* styles for 'if' */ }
+
+ Note: This plugin does not come with CSS styles. You have to define the keyword-specific CSS rules yourself.
+
+
Examples
+ This example shows the plugin in action. The keywords if
and return
will be highlighted in red. The color of all other keywords will be determined by the current theme. The CSS rules used to implement the keyword-specific highlighting can be seen in the HTML file below.
+
JavaScript
diff --git a/plugins/show-language/prism-show-language.js b/plugins/show-language/prism-show-language.js
index 33ea603483..15945f4228 100644
--- a/plugins/show-language/prism-show-language.js
+++ b/plugins/show-language/prism-show-language.js
@@ -43,6 +43,8 @@
"asm6502": "6502 Assembly",
"autohotkey": "AutoHotkey",
"autoit": "AutoIt",
+ "avro-idl": "Avro IDL",
+ "avdl": "Avro IDL",
"basic": "BASIC",
"bbcode": "BBcode",
"bnf": "BNF",
@@ -90,6 +92,8 @@
"gdscript": "GDScript",
"gedcom": "GEDCOM",
"glsl": "GLSL",
+ "gn": "GN",
+ "gni": "GN",
"graphql": "GraphQL",
"hbs": "Handlebars",
"hs": "Haskell",
@@ -209,6 +213,7 @@
"sqf": "SQF: Status Quo Function (Arma 3)",
"sql": "SQL",
"iecst": "Structured Text (IEC 61131-3)",
+ "systemd": "Systemd configuration file",
"t4-templating": "T4 templating",
"t4-cs": "T4 Text Templates (C#)",
"t4": "T4 Text Templates (C#)",
diff --git a/plugins/show-language/prism-show-language.min.js b/plugins/show-language/prism-show-language.min.js
index 371d479042..4f7ecafa40 100644
--- a/plugins/show-language/prism-show-language.min.js
+++ b/plugins/show-language/prism-show-language.min.js
@@ -1 +1 @@
-!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document)if(Prism.plugins.toolbar){var i={none:"Plain text",plain:"Plain text",plaintext:"Plain text",text:"Plain text",txt:"Plain text",html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",rss:"RSS",css:"CSS",clike:"C-like",js:"JavaScript",abap:"ABAP",abnf:"ABNF",al:"AL",antlr4:"ANTLR4",g4:"ANTLR4",apacheconf:"Apache Configuration",apl:"APL",aql:"AQL",arff:"ARFF",asciidoc:"AsciiDoc",adoc:"AsciiDoc",aspnet:"ASP.NET (C#)",asm6502:"6502 Assembly",autohotkey:"AutoHotkey",autoit:"AutoIt",basic:"BASIC",bbcode:"BBcode",bnf:"BNF",rbnf:"RBNF",bsl:"BSL (1C:Enterprise)",oscript:"OneScript",csharp:"C#",cs:"C#",dotnet:"C#",cpp:"C++",cfscript:"CFScript",cfc:"CFScript",cil:"CIL",cmake:"CMake",cobol:"COBOL",coffee:"CoffeeScript",conc:"Concurnas",csp:"Content-Security-Policy","css-extras":"CSS Extras",csv:"CSV",dataweave:"DataWeave",dax:"DAX",django:"Django/Jinja2",jinja2:"Django/Jinja2","dns-zone-file":"DNS zone file","dns-zone":"DNS zone file",dockerfile:"Docker",dot:"DOT (Graphviz)",gv:"DOT (Graphviz)",ebnf:"EBNF",editorconfig:"EditorConfig",ejs:"EJS",etlua:"Embedded Lua templating",erb:"ERB","excel-formula":"Excel Formula",xlsx:"Excel Formula",xls:"Excel Formula",fsharp:"F#","firestore-security-rules":"Firestore security rules",ftl:"FreeMarker Template Language",gml:"GameMaker Language",gamemakerlanguage:"GameMaker Language",gap:"GAP (CAS)",gcode:"G-code",gdscript:"GDScript",gedcom:"GEDCOM",glsl:"GLSL",graphql:"GraphQL",hbs:"Handlebars",hs:"Haskell",hcl:"HCL",hlsl:"HLSL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam","icu-message-format":"ICU Message Format",idr:"Idris",ignore:".ignore",gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore",inform7:"Inform 7",javadoc:"JavaDoc",javadoclike:"JavaDoc-like",javastacktrace:"Java stack trace",jq:"JQ",jsdoc:"JSDoc","js-extras":"JS Extras",json:"JSON",webmanifest:"Web App Manifest",json5:"JSON5",jsonp:"JSONP",jsstacktrace:"JS stack trace","js-templates":"JS Templates",kts:"Kotlin Script",kt:"Kotlin",kumir:"KuMir (КуМир)",kum:"KuMir (КуМир)",latex:"LaTeX",tex:"TeX",context:"ConTeXt",lilypond:"LilyPond",ly:"LilyPond",emacs:"Lisp",elisp:"Lisp","emacs-lisp":"Lisp",llvm:"LLVM IR",log:"Log file",lolcode:"LOLCODE",md:"Markdown","markup-templating":"Markup templating",matlab:"MATLAB",mel:"MEL",mongodb:"MongoDB",moon:"MoonScript",n1ql:"N1QL",n4js:"N4JS",n4jsd:"N4JS","nand2tetris-hdl":"Nand To Tetris HDL",naniscript:"Naninovel Script",nani:"Naninovel Script",nasm:"NASM",neon:"NEON",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",objc:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",openqasm:"OpenQasm",qasm:"OpenQasm",parigp:"PARI/GP",objectpascal:"Object Pascal",psl:"PATROL Scripting Language",pcaxis:"PC-Axis",px:"PC-Axis",peoplecode:"PeopleCode",pcode:"PeopleCode",php:"PHP",phpdoc:"PHPDoc","php-extras":"PHP Extras",plsql:"PL/SQL",powerquery:"PowerQuery",pq:"PowerQuery",mscript:"PowerQuery",powershell:"PowerShell",promql:"PromQL",properties:".properties",protobuf:"Protocol Buffers",purebasic:"PureBasic",pbfasm:"PureBasic",purs:"PureScript",py:"Python",qsharp:"Q#",qs:"Q#",q:"Q (kdb+ database)",qml:"QML",rkt:"Racket",jsx:"React JSX",tsx:"React TSX",renpy:"Ren'py",rpy:"Ren'py",rest:"reST (reStructuredText)",robotframework:"Robot Framework",robot:"Robot Framework",rb:"Ruby",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)","shell-session":"Shell session","sh-session":"Shell session",shellsession:"Shell session",sml:"SML",smlnj:"SML/NJ",solidity:"Solidity (Ethereum)",sol:"Solidity (Ethereum)","solution-file":"Solution file",sln:"Solution file",soy:"Soy (Closure Template)",sparql:"SPARQL",rq:"SPARQL","splunk-spl":"Splunk SPL",sqf:"SQF: Status Quo Function (Arma 3)",sql:"SQL",iecst:"Structured Text (IEC 61131-3)","t4-templating":"T4 templating","t4-cs":"T4 Text Templates (C#)",t4:"T4 Text Templates (C#)","t4-vb":"T4 Text Templates (VB)",tap:"TAP",tt2:"Template Toolkit 2",toml:"TOML",trig:"TriG",ts:"TypeScript",tsconfig:"TSConfig",uscript:"UnrealScript",uc:"UnrealScript",uri:"URI",url:"URL",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim","visual-basic":"Visual Basic",vba:"VBA",vb:"Visual Basic",wasm:"WebAssembly",wiki:"Wiki markup",wolfram:"Wolfram language",nb:"Mathematica Notebook",wl:"Wolfram language",xeoracube:"XeoraCube","xml-doc":"XML doc (.net)",xojo:"Xojo (REALbasic)",xquery:"XQuery",yaml:"YAML",yml:"YAML",yang:"YANG"};Prism.plugins.toolbar.registerButton("show-language",function(e){var a=e.element.parentNode;if(a&&/pre/i.test(a.nodeName)){var t,s=a.getAttribute("data-language")||i[e.language]||((t=e.language)?(t.substring(0,1).toUpperCase()+t.substring(1)).replace(/s(?=cript)/,"S"):t);if(s){var o=document.createElement("span");return o.textContent=s,o}}})}else console.warn("Show Languages plugin loaded before Toolbar plugin.")}();
\ No newline at end of file
+!function(){if("undefined"!=typeof Prism&&"undefined"!=typeof document)if(Prism.plugins.toolbar){var i={none:"Plain text",plain:"Plain text",plaintext:"Plain text",text:"Plain text",txt:"Plain text",html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",rss:"RSS",css:"CSS",clike:"C-like",js:"JavaScript",abap:"ABAP",abnf:"ABNF",al:"AL",antlr4:"ANTLR4",g4:"ANTLR4",apacheconf:"Apache Configuration",apl:"APL",aql:"AQL",arff:"ARFF",asciidoc:"AsciiDoc",adoc:"AsciiDoc",aspnet:"ASP.NET (C#)",asm6502:"6502 Assembly",autohotkey:"AutoHotkey",autoit:"AutoIt","avro-idl":"Avro IDL",avdl:"Avro IDL",basic:"BASIC",bbcode:"BBcode",bnf:"BNF",rbnf:"RBNF",bsl:"BSL (1C:Enterprise)",oscript:"OneScript",csharp:"C#",cs:"C#",dotnet:"C#",cpp:"C++",cfscript:"CFScript",cfc:"CFScript",cil:"CIL",cmake:"CMake",cobol:"COBOL",coffee:"CoffeeScript",conc:"Concurnas",csp:"Content-Security-Policy","css-extras":"CSS Extras",csv:"CSV",dataweave:"DataWeave",dax:"DAX",django:"Django/Jinja2",jinja2:"Django/Jinja2","dns-zone-file":"DNS zone file","dns-zone":"DNS zone file",dockerfile:"Docker",dot:"DOT (Graphviz)",gv:"DOT (Graphviz)",ebnf:"EBNF",editorconfig:"EditorConfig",ejs:"EJS",etlua:"Embedded Lua templating",erb:"ERB","excel-formula":"Excel Formula",xlsx:"Excel Formula",xls:"Excel Formula",fsharp:"F#","firestore-security-rules":"Firestore security rules",ftl:"FreeMarker Template Language",gml:"GameMaker Language",gamemakerlanguage:"GameMaker Language",gap:"GAP (CAS)",gcode:"G-code",gdscript:"GDScript",gedcom:"GEDCOM",glsl:"GLSL",gn:"GN",gni:"GN",graphql:"GraphQL",hbs:"Handlebars",hs:"Haskell",hcl:"HCL",hlsl:"HLSL",http:"HTTP",hpkp:"HTTP Public-Key-Pins",hsts:"HTTP Strict-Transport-Security",ichigojam:"IchigoJam","icu-message-format":"ICU Message Format",idr:"Idris",ignore:".ignore",gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore",inform7:"Inform 7",javadoc:"JavaDoc",javadoclike:"JavaDoc-like",javastacktrace:"Java stack trace",jq:"JQ",jsdoc:"JSDoc","js-extras":"JS Extras",json:"JSON",webmanifest:"Web App Manifest",json5:"JSON5",jsonp:"JSONP",jsstacktrace:"JS stack trace","js-templates":"JS Templates",kts:"Kotlin Script",kt:"Kotlin",kumir:"KuMir (КуМир)",kum:"KuMir (КуМир)",latex:"LaTeX",tex:"TeX",context:"ConTeXt",lilypond:"LilyPond",ly:"LilyPond",emacs:"Lisp",elisp:"Lisp","emacs-lisp":"Lisp",llvm:"LLVM IR",log:"Log file",lolcode:"LOLCODE",md:"Markdown","markup-templating":"Markup templating",matlab:"MATLAB",mel:"MEL",mongodb:"MongoDB",moon:"MoonScript",n1ql:"N1QL",n4js:"N4JS",n4jsd:"N4JS","nand2tetris-hdl":"Nand To Tetris HDL",naniscript:"Naninovel Script",nani:"Naninovel Script",nasm:"NASM",neon:"NEON",nginx:"nginx",nsis:"NSIS",objectivec:"Objective-C",objc:"Objective-C",ocaml:"OCaml",opencl:"OpenCL",openqasm:"OpenQasm",qasm:"OpenQasm",parigp:"PARI/GP",objectpascal:"Object Pascal",psl:"PATROL Scripting Language",pcaxis:"PC-Axis",px:"PC-Axis",peoplecode:"PeopleCode",pcode:"PeopleCode",php:"PHP",phpdoc:"PHPDoc","php-extras":"PHP Extras",plsql:"PL/SQL",powerquery:"PowerQuery",pq:"PowerQuery",mscript:"PowerQuery",powershell:"PowerShell",promql:"PromQL",properties:".properties",protobuf:"Protocol Buffers",purebasic:"PureBasic",pbfasm:"PureBasic",purs:"PureScript",py:"Python",qsharp:"Q#",qs:"Q#",q:"Q (kdb+ database)",qml:"QML",rkt:"Racket",jsx:"React JSX",tsx:"React TSX",renpy:"Ren'py",rpy:"Ren'py",rest:"reST (reStructuredText)",robotframework:"Robot Framework",robot:"Robot Framework",rb:"Ruby",sas:"SAS",sass:"Sass (Sass)",scss:"Sass (Scss)","shell-session":"Shell session","sh-session":"Shell session",shellsession:"Shell session",sml:"SML",smlnj:"SML/NJ",solidity:"Solidity (Ethereum)",sol:"Solidity (Ethereum)","solution-file":"Solution file",sln:"Solution file",soy:"Soy (Closure Template)",sparql:"SPARQL",rq:"SPARQL","splunk-spl":"Splunk SPL",sqf:"SQF: Status Quo Function (Arma 3)",sql:"SQL",iecst:"Structured Text (IEC 61131-3)",systemd:"Systemd configuration file","t4-templating":"T4 templating","t4-cs":"T4 Text Templates (C#)",t4:"T4 Text Templates (C#)","t4-vb":"T4 Text Templates (VB)",tap:"TAP",tt2:"Template Toolkit 2",toml:"TOML",trig:"TriG",ts:"TypeScript",tsconfig:"TSConfig",uscript:"UnrealScript",uc:"UnrealScript",uri:"URI",url:"URL",vbnet:"VB.Net",vhdl:"VHDL",vim:"vim","visual-basic":"Visual Basic",vba:"VBA",vb:"Visual Basic",wasm:"WebAssembly",wiki:"Wiki markup",wolfram:"Wolfram language",nb:"Mathematica Notebook",wl:"Wolfram language",xeoracube:"XeoraCube","xml-doc":"XML doc (.net)",xojo:"Xojo (REALbasic)",xquery:"XQuery",yaml:"YAML",yml:"YAML",yang:"YANG"};Prism.plugins.toolbar.registerButton("show-language",function(e){var a=e.element.parentNode;if(a&&/pre/i.test(a.nodeName)){var t,s=a.getAttribute("data-language")||i[e.language]||((t=e.language)?(t.substring(0,1).toUpperCase()+t.substring(1)).replace(/s(?=cript)/,"S"):t);if(s){var o=document.createElement("span");return o.textContent=s,o}}})}else console.warn("Show Languages plugin loaded before Toolbar plugin.")}();
\ No newline at end of file
diff --git a/tests/languages/avro-idl/annotation_feature.test b/tests/languages/avro-idl/annotation_feature.test
new file mode 100644
index 0000000000..35a359c4d8
--- /dev/null
+++ b/tests/languages/avro-idl/annotation_feature.test
@@ -0,0 +1,76 @@
+record MyRecord {
+ string @order("ascending") myAscendingSortField;
+ string @order("descending") myDescendingField;
+ string @order("ignore") myIgnoredField;
+}
+
+@java-class("java.util.ArrayList") array myStrings;
+
+@namespace("org.apache.avro.firstNamespace")
+
+union { MD5, null} @aliases(["hash"]) nullableHash;
+
+----------------------------------------------------
+
+[
+ ["keyword", "record"],
+ ["class-name", "MyRecord"],
+ ["punctuation", "{"],
+
+ ["keyword", "string"],
+ ["annotation", "@order"],
+ ["punctuation", "("],
+ ["string", "\"ascending\""],
+ ["punctuation", ")"],
+ " myAscendingSortField",
+ ["punctuation", ";"],
+
+ ["keyword", "string"],
+ ["annotation", "@order"],
+ ["punctuation", "("],
+ ["string", "\"descending\""],
+ ["punctuation", ")"],
+ " myDescendingField",
+ ["punctuation", ";"],
+
+ ["keyword", "string"],
+ ["annotation", "@order"],
+ ["punctuation", "("],
+ ["string", "\"ignore\""],
+ ["punctuation", ")"],
+ " myIgnoredField",
+ ["punctuation", ";"],
+
+ ["punctuation", "}"],
+
+ ["annotation", "@java-class"],
+ ["punctuation", "("],
+ ["string", "\"java.util.ArrayList\""],
+ ["punctuation", ")"],
+ ["keyword", "array"],
+ ["punctuation", "<"],
+ ["keyword", "string"],
+ ["punctuation", ">"],
+ " myStrings",
+ ["punctuation", ";"],
+
+ ["annotation", "@namespace"],
+ ["punctuation", "("],
+ ["string", "\"org.apache.avro.firstNamespace\""],
+ ["punctuation", ")"],
+
+ ["keyword", "union"],
+ ["punctuation", "{"],
+ " MD5",
+ ["punctuation", ","],
+ ["keyword", "null"],
+ ["punctuation", "}"],
+ ["annotation", "@aliases"],
+ ["punctuation", "("],
+ ["punctuation", "["],
+ ["string", "\"hash\""],
+ ["punctuation", "]"],
+ ["punctuation", ")"],
+ " nullableHash",
+ ["punctuation", ";"]
+]
diff --git a/tests/languages/avro-idl/class-name_feature.test b/tests/languages/avro-idl/class-name_feature.test
new file mode 100644
index 0000000000..4e4e549aa2
--- /dev/null
+++ b/tests/languages/avro-idl/class-name_feature.test
@@ -0,0 +1,52 @@
+protocol MyProto {
+ @namespace("org.apache.avro.someOtherNamespace")
+ record Foo {}
+
+ record Bar {}
+
+ enum Kind {
+ FOO,
+ BAR, // the bar enum value
+ BAZ
+ }
+
+ error TestError {
+ string message;
+ }
+
+}
+
+----------------------------------------------------
+
+[
+ ["keyword", "protocol"],
+ ["class-name", "MyProto"],
+ ["punctuation", "{"],
+
+ ["annotation", "@namespace"],
+ ["punctuation", "("],
+ ["string", "\"org.apache.avro.someOtherNamespace\""],
+ ["punctuation", ")"],
+
+ ["keyword", "record"],
+ ["class-name", "Foo"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "record"],
+ ["class-name", "Bar"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["keyword", "enum"], ["class-name", "Kind"], ["punctuation", "{"],
+ "\r\n FOO", ["punctuation", ","],
+ "\r\n BAR", ["punctuation", ","], ["comment", "// the bar enum value"],
+ "\r\n BAZ\r\n ",
+ ["punctuation", "}"],
+
+ ["keyword", "error"], ["class-name", "TestError"], ["punctuation", "{"],
+ ["keyword", "string"], " message", ["punctuation", ";"],
+ ["punctuation", "}"],
+
+ ["punctuation", "}"]
+]
diff --git a/tests/languages/avro-idl/comment_feature.test b/tests/languages/avro-idl/comment_feature.test
new file mode 100644
index 0000000000..8a6e067fbe
--- /dev/null
+++ b/tests/languages/avro-idl/comment_feature.test
@@ -0,0 +1,15 @@
+/* comment */
+/*
+ comment
+ */
+
+// comment
+
+----------------------------------------------------
+
+[
+ ["comment", "/* comment */"],
+ ["comment", "/*\r\n comment\r\n */"],
+
+ ["comment", "// comment"]
+]
diff --git a/tests/languages/avro-idl/function_feature.test b/tests/languages/avro-idl/function_feature.test
new file mode 100644
index 0000000000..3f1dae07dd
--- /dev/null
+++ b/tests/languages/avro-idl/function_feature.test
@@ -0,0 +1,57 @@
+int add(int foo, int bar = 0);
+
+void logMessage(string message);
+
+void goKaboom() throws Kaboom;
+
+void fireAndForget(string message) oneway;
+
+void `error`();
+
+----------------------------------------------------
+
+[
+ ["keyword", "int"],
+ ["function", "add"],
+ ["punctuation", "("],
+ ["keyword", "int"],
+ " foo",
+ ["punctuation", ","],
+ ["keyword", "int"],
+ " bar ",
+ ["operator", "="],
+ ["number", "0"],
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "void"],
+ ["function", "logMessage"],
+ ["punctuation", "("],
+ ["keyword", "string"],
+ " message",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "void"],
+ ["function", "goKaboom"],
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["keyword", "throws"],
+ ["class-name", "Kaboom"],
+ ["punctuation", ";"],
+
+ ["keyword", "void"],
+ ["function", "fireAndForget"],
+ ["punctuation", "("],
+ ["keyword", "string"],
+ " message",
+ ["punctuation", ")"],
+ ["keyword", "oneway"],
+ ["punctuation", ";"],
+
+ ["keyword", "void"],
+ ["function-identifier", "`error`"],
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["punctuation", ";"]
+]
diff --git a/tests/languages/avro-idl/keyword_feature.test b/tests/languages/avro-idl/keyword_feature.test
new file mode 100644
index 0000000000..e1ede9c750
--- /dev/null
+++ b/tests/languages/avro-idl/keyword_feature.test
@@ -0,0 +1,65 @@
+array;
+boolean;
+bytes;
+date;
+decimal;
+double;
+enum;
+error;
+false;
+fixed;
+float;
+idl;
+import;
+int;
+local_timestamp_ms;
+long;
+map;
+null;
+oneway;
+protocol;
+record;
+schema;
+string;
+throws;
+time_ms;
+timestamp_ms;
+true;
+union;
+uuid;
+void;
+
+----------------------------------------------------
+
+[
+ ["keyword", "array"], ["punctuation", ";"],
+ ["keyword", "boolean"], ["punctuation", ";"],
+ ["keyword", "bytes"], ["punctuation", ";"],
+ ["keyword", "date"], ["punctuation", ";"],
+ ["keyword", "decimal"], ["punctuation", ";"],
+ ["keyword", "double"], ["punctuation", ";"],
+ ["keyword", "enum"], ["punctuation", ";"],
+ ["keyword", "error"], ["punctuation", ";"],
+ ["keyword", "false"], ["punctuation", ";"],
+ ["keyword", "fixed"], ["punctuation", ";"],
+ ["keyword", "float"], ["punctuation", ";"],
+ ["keyword", "idl"], ["punctuation", ";"],
+ ["keyword", "import"], ["punctuation", ";"],
+ ["keyword", "int"], ["punctuation", ";"],
+ ["keyword", "local_timestamp_ms"], ["punctuation", ";"],
+ ["keyword", "long"], ["punctuation", ";"],
+ ["keyword", "map"], ["punctuation", ";"],
+ ["keyword", "null"], ["punctuation", ";"],
+ ["keyword", "oneway"], ["punctuation", ";"],
+ ["keyword", "protocol"], ["punctuation", ";"],
+ ["keyword", "record"], ["punctuation", ";"],
+ ["keyword", "schema"], ["punctuation", ";"],
+ ["keyword", "string"], ["punctuation", ";"],
+ ["keyword", "throws"], ["punctuation", ";"],
+ ["keyword", "time_ms"], ["punctuation", ";"],
+ ["keyword", "timestamp_ms"], ["punctuation", ";"],
+ ["keyword", "true"], ["punctuation", ";"],
+ ["keyword", "union"], ["punctuation", ";"],
+ ["keyword", "uuid"], ["punctuation", ";"],
+ ["keyword", "void"], ["punctuation", ";"]
+]
diff --git a/tests/languages/avro-idl/number_feature.test b/tests/languages/avro-idl/number_feature.test
new file mode 100644
index 0000000000..87869c9b4d
--- /dev/null
+++ b/tests/languages/avro-idl/number_feature.test
@@ -0,0 +1,43 @@
+0
+123
+0xFFF
+-0
+-123
+-0xFF
+12343324234L
+0xFFFFFFFFFl
+
+0.342e4
+0.342e-4f
+0.342e-4d
+.324
+123.
+0x.2Fp+323f
+0x234.p+323d
+
+NaN
+Infinity
+
+----------------------------------------------------
+
+[
+ ["number", "0"],
+ ["number", "123"],
+ ["number", "0xFFF"],
+ ["number", "-0"],
+ ["number", "-123"],
+ ["number", "-0xFF"],
+ ["number", "12343324234L"],
+ ["number", "0xFFFFFFFFFl"],
+
+ ["number", "0.342e4"],
+ ["number", "0.342e-4f"],
+ ["number", "0.342e-4d"],
+ ["number", ".324"],
+ ["number", "123."],
+ ["number", "0x.2Fp+323f"],
+ ["number", "0x234.p+323d"],
+
+ ["number", "NaN"],
+ ["number", "Infinity"]
+]
diff --git a/tests/languages/avro-idl/operator_feature.test b/tests/languages/avro-idl/operator_feature.test
new file mode 100644
index 0000000000..27b9165afc
--- /dev/null
+++ b/tests/languages/avro-idl/operator_feature.test
@@ -0,0 +1,7 @@
+=
+
+----------------------------------------------------
+
+[
+ ["operator", "="]
+]
diff --git a/tests/languages/avro-idl/punctuation_feature.test b/tests/languages/avro-idl/punctuation_feature.test
new file mode 100644
index 0000000000..f73a56287d
--- /dev/null
+++ b/tests/languages/avro-idl/punctuation_feature.test
@@ -0,0 +1,20 @@
+( ) [ ] { } < >
+. : , ;
+
+----------------------------------------------------
+
+[
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["punctuation", "["],
+ ["punctuation", "]"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+ ["punctuation", "<"],
+ ["punctuation", ">"],
+
+ ["punctuation", "."],
+ ["punctuation", ":"],
+ ["punctuation", ","],
+ ["punctuation", ";"]
+]
diff --git a/tests/languages/avro-idl/string_feature.test b/tests/languages/avro-idl/string_feature.test
new file mode 100644
index 0000000000..1811a33dd5
--- /dev/null
+++ b/tests/languages/avro-idl/string_feature.test
@@ -0,0 +1,21 @@
+""
+"foo"
+"\""
+"\n\n"
+
+'f'
+'\n'
+'\34'
+
+----------------------------------------------------
+
+[
+ ["string", "\"\""],
+ ["string", "\"foo\""],
+ ["string", "\"\\\"\""],
+ ["string", "\"\\n\\n\""],
+
+ ["string", "'f'"],
+ ["string", "'\\n'"],
+ ["string", "'\\34'"]
+]
diff --git a/tests/languages/cpp/issue3042.test b/tests/languages/cpp/issue3042.test
new file mode 100644
index 0000000000..ab5c47b4df
--- /dev/null
+++ b/tests/languages/cpp/issue3042.test
@@ -0,0 +1,126 @@
+class Foo
+{
+public:
+
+ friend bool operator== (const Foo& f1, const Foo& f2);
+ friend bool operator!= (const Foo& f1, const Foo& f2);
+
+ friend bool operator< (const Foo& f1, const Foo& f2);
+ friend bool operator> (const Foo& f1, const Foo& f2);
+
+ friend bool operator<= (const Foo& f1, const Foo& f2);
+ friend bool operator>= (const Foo& f1, const Foo& f2);
+};
+
+----------------------------------------------------
+
+[
+ ["keyword", "class"], ["class-name", "Foo"],
+ ["punctuation", "{"],
+ ["keyword", "public"], ["operator", ":"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "=="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "!="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "<"],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", ">"],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", "<="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["keyword", "friend"],
+ ["keyword", "bool"],
+ ["keyword", "operator"],
+ ["operator", ">="],
+ ["punctuation", "("],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f1",
+ ["punctuation", ","],
+ ["keyword", "const"],
+ " Foo",
+ ["operator", "&"],
+ " f2",
+ ["punctuation", ")"],
+ ["punctuation", ";"],
+
+ ["punctuation", "}"],
+ ["punctuation", ";"]
+]
diff --git a/tests/languages/gn/boolean_feature.test b/tests/languages/gn/boolean_feature.test
new file mode 100644
index 0000000000..e002f72d44
--- /dev/null
+++ b/tests/languages/gn/boolean_feature.test
@@ -0,0 +1,8 @@
+true false
+
+----------------------------------------------------
+
+[
+ ["boolean", "true"],
+ ["boolean", "false"]
+]
diff --git a/tests/languages/gn/comment_feature.test b/tests/languages/gn/comment_feature.test
new file mode 100644
index 0000000000..7883a734b3
--- /dev/null
+++ b/tests/languages/gn/comment_feature.test
@@ -0,0 +1,7 @@
+# comment
+
+----------------------------------------------------
+
+[
+ ["comment", "# comment"]
+]
diff --git a/tests/languages/gn/function_feature.test b/tests/languages/gn/function_feature.test
new file mode 100644
index 0000000000..896990e8e7
--- /dev/null
+++ b/tests/languages/gn/function_feature.test
@@ -0,0 +1,9 @@
+foo()
+
+----------------------------------------------------
+
+[
+ ["function", "foo"],
+ ["punctuation", "("],
+ ["punctuation", ")"]
+]
diff --git a/tests/languages/gn/number_feature.test b/tests/languages/gn/number_feature.test
new file mode 100644
index 0000000000..9eb1b8b987
--- /dev/null
+++ b/tests/languages/gn/number_feature.test
@@ -0,0 +1,11 @@
+0
+123
+-123
+
+----------------------------------------------------
+
+[
+ ["number", "0"],
+ ["number", "123"],
+ ["number", "-123"]
+]
diff --git a/tests/languages/gn/operator_feature.test b/tests/languages/gn/operator_feature.test
new file mode 100644
index 0000000000..61be6f76a1
--- /dev/null
+++ b/tests/languages/gn/operator_feature.test
@@ -0,0 +1,29 @@
++ +=
+- -=
+== != < > <= =>
+! =
+&& ||
+
+----------------------------------------------------
+
+[
+ ["operator", "+"],
+ ["operator", "+="],
+
+ ["operator", "-"],
+ ["operator", "-="],
+
+ ["operator", "=="],
+ ["operator", "!="],
+ ["operator", "<"],
+ ["operator", ">"],
+ ["operator", "<="],
+ ["operator", "="],
+ ["operator", ">"],
+
+ ["operator", "!"],
+ ["operator", "="],
+
+ ["operator", "&&"],
+ ["operator", "||"]
+]
diff --git a/tests/languages/gn/punctuation_feature.test b/tests/languages/gn/punctuation_feature.test
new file mode 100644
index 0000000000..2f83bd4cfb
--- /dev/null
+++ b/tests/languages/gn/punctuation_feature.test
@@ -0,0 +1,16 @@
+( ) [ ] { }
+, .
+
+----------------------------------------------------
+
+[
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["punctuation", "["],
+ ["punctuation", "]"],
+ ["punctuation", "{"],
+ ["punctuation", "}"],
+
+ ["punctuation", ","],
+ ["punctuation", "."]
+]
diff --git a/tests/languages/gn/string_feature.test b/tests/languages/gn/string_feature.test
new file mode 100644
index 0000000000..322dd572b2
--- /dev/null
+++ b/tests/languages/gn/string_feature.test
@@ -0,0 +1,70 @@
+""
+"foo"
+".$output_extension"
+"$0xFF"
+"$var_one/$var_two"
+"${var_one}"
+"$root_out_dir/lib${_output_name}${_shlib_extension}"
+
+----------------------------------------------------
+
+[
+ ["string-literal", [
+ ["string", "\"\""]
+ ]],
+ ["string-literal", [
+ ["string", "\"foo\""]
+ ]],
+ ["string-literal", [
+ ["string", "\"."],
+ ["interpolation", [
+ ["variable", "$output_extension"]
+ ]],
+ ["string", "\""]
+ ]],
+ ["string-literal", [
+ ["string", "\""],
+ ["interpolation", [
+ ["number", "$0xFF"]
+ ]],
+ ["string", "\""]
+ ]],
+ ["string-literal", [
+ ["string", "\""],
+ ["interpolation", [
+ ["variable", "$var_one"]
+ ]],
+ ["string", "/"],
+ ["interpolation", [
+ ["variable", "$var_two"]
+ ]],
+ ["string", "\""]
+ ]],
+ ["string-literal", [
+ ["string", "\""],
+ ["interpolation", [
+ ["interpolation-punctuation", "${"],
+ ["expression", ["var_one"]],
+ ["interpolation-punctuation", "}"]
+ ]],
+ ["string", "\""]
+ ]],
+ ["string-literal", [
+ ["string", "\""],
+ ["interpolation", [
+ ["variable", "$root_out_dir"]
+ ]],
+ ["string", "/lib"],
+ ["interpolation", [
+ ["interpolation-punctuation", "${"],
+ ["expression", ["_output_name"]],
+ ["interpolation-punctuation", "}"]
+ ]],
+ ["interpolation", [
+ ["interpolation-punctuation", "${"],
+ ["expression", ["_shlib_extension"]],
+ ["interpolation-punctuation", "}"]
+ ]],
+ ["string", "\""]
+ ]]
+]
diff --git a/tests/languages/mermaid/arrow_feature.test b/tests/languages/mermaid/arrow_feature.test
new file mode 100644
index 0000000000..6205a313ff
--- /dev/null
+++ b/tests/languages/mermaid/arrow_feature.test
@@ -0,0 +1,125 @@
+%% flow chart
+
+--- ---- -----
+--> ---> ---->
+<-- <--- <----
+=== ==== =====
+==> ===> ====>
+<== <=== <====
+-.- -..- -...-
+-.-> -..-> -...->
+<-.- <-..- <-...-
+--x ---x ----x
+--x -.-x -..-x
+x-- x--- x----
+x-- x-.- x-..-
+--o ---o ----o
+--o -.-o -..-o
+o-- o--- o----
+o-- o-.- o-..-
+
+<--> <----> <-..-> <====>
+x--x x----x x-..-x x====x
+o--o o----o o-..-o o====o
+
+%% sequence diagram
+
+-> --> ->> -->>
+<- <-- <<- <<--
+-x --x -) --)
+x- x-- (- (--
+
+%% class diagram
+
+<|-- *-- o-- <-- <.. <|..
+--|> --* --o --> ..> ..|>
+-- ..
+
+%% ER diagram
+
+|o--o| |o..o|
+||--|| ||..||
+}o--o{ }o..o{
+}|--|{ }|..|{
+
+|o--o| |o..o|
+||--o{ ||..o{
+}o--|{ }o..|{
+}|--|| }|..||
+
+----------------------------------------------------
+
+[
+ ["comment", "%% flow chart"],
+
+ ["arrow", "---"], ["arrow", "----"], ["arrow", "-----"],
+ ["arrow", "-->"], ["arrow", "--->"], ["arrow", "---->"],
+ ["arrow", "<--"], ["arrow", "<---"], ["arrow", "<----"],
+ ["arrow", "==="], ["arrow", "===="], ["arrow", "====="],
+ ["arrow", "==>"], ["arrow", "===>"], ["arrow", "====>"],
+ ["arrow", "<=="], ["arrow", "<==="], ["arrow", "<===="],
+ ["arrow", "-.-"], ["arrow", "-..-"], ["arrow", "-...-"],
+ ["arrow", "-.->"], ["arrow", "-..->"], ["arrow", "-...->"],
+ ["arrow", "<-.-"], ["arrow", "<-..-"], ["arrow", "<-...-"],
+ ["arrow", "--x"], ["arrow", "---x"], ["arrow", "----x"],
+ ["arrow", "--x"], ["arrow", "-.-x"], ["arrow", "-..-x"],
+ ["arrow", "x--"], ["arrow", "x---"], ["arrow", "x----"],
+ ["arrow", "x--"], ["arrow", "x-.-"], ["arrow", "x-..-"],
+ ["arrow", "--o"], ["arrow", "---o"], ["arrow", "----o"],
+ ["arrow", "--o"], ["arrow", "-.-o"], ["arrow", "-..-o"],
+ ["arrow", "o--"], ["arrow", "o---"], ["arrow", "o----"],
+ ["arrow", "o--"], ["arrow", "o-.-"], ["arrow", "o-..-"],
+
+ ["arrow", "<-->"],
+ ["arrow", "<---->"],
+ ["arrow", "<-..->"],
+ ["arrow", "<====>"],
+
+ ["arrow", "x--x"],
+ ["arrow", "x----x"],
+ ["arrow", "x-..-x"],
+ ["arrow", "x====x"],
+
+ ["arrow", "o--o"],
+ ["arrow", "o----o"],
+ ["arrow", "o-..-o"],
+ ["arrow", "o====o"],
+
+ ["comment", "%% sequence diagram"],
+
+ ["arrow", "->"], ["arrow", "-->"], ["arrow", "->>"], ["arrow", "-->>"],
+ ["arrow", "<-"], ["arrow", "<--"], ["arrow", "<<-"], ["arrow", "<<--"],
+ ["arrow", "-x"], ["arrow", "--x"], ["arrow", "-)"], ["arrow", "--)"],
+ ["arrow", "x-"], ["arrow", "x--"], ["arrow", "(-"], ["arrow", "(--"],
+
+ ["comment", "%% class diagram"],
+
+ ["arrow", "<|--"],
+ ["arrow", "*--"],
+ ["arrow", "o--"],
+ ["arrow", "<--"],
+ ["arrow", "<.."],
+ ["arrow", "<|.."],
+
+ ["arrow", "--|>"],
+ ["arrow", "--*"],
+ ["arrow", "--o"],
+ ["arrow", "-->"],
+ ["arrow", "..>"],
+ ["arrow", "..|>"],
+
+ ["arrow", "--"],
+ ["arrow", ".."],
+
+ ["comment", "%% ER diagram"],
+
+ ["arrow", "|o--o|"], ["arrow", "|o..o|"],
+ ["arrow", "||--||"], ["arrow", "||..||"],
+ ["arrow", "}o--o{"], ["arrow", "}o..o{"],
+ ["arrow", "}|--|{"], ["arrow", "}|..|{"],
+
+ ["arrow", "|o--o|"], ["arrow", "|o..o|"],
+ ["arrow", "||--o{"], ["arrow", "||..o{"],
+ ["arrow", "}o--|{"], ["arrow", "}o..|{"],
+ ["arrow", "}|--||"], ["arrow", "}|..||"]
+]
diff --git a/tests/languages/mermaid/comment_feature.test b/tests/languages/mermaid/comment_feature.test
new file mode 100644
index 0000000000..90b8493fba
--- /dev/null
+++ b/tests/languages/mermaid/comment_feature.test
@@ -0,0 +1,7 @@
+%% comment
+
+----------------------------------------------------
+
+[
+ ["comment", "%% comment"]
+]
diff --git a/tests/languages/mermaid/full_classdiagram.test b/tests/languages/mermaid/full_classdiagram.test
new file mode 100644
index 0000000000..e612373f67
--- /dev/null
+++ b/tests/languages/mermaid/full_classdiagram.test
@@ -0,0 +1,656 @@
+classDiagram
+ Animal <|-- Duck
+ Animal <|-- Fish
+ Animal <|-- Zebra
+ Animal : +int age
+ Animal : +String gender
+ Animal: +isMammal()
+ Animal: +mate()
+ class Duck{
+ +String beakColor
+ +swim()
+ +quack()
+ }
+ class Fish{
+ -int sizeInFeet
+ -canEat()
+ }
+ class Zebra{
+ +bool is_wild
+ +run()
+ }
+
+classDiagram
+ class BankAccount
+ BankAccount : +String owner
+ BankAccount : +Bigdecimal balance
+ BankAccount : +deposit(amount)
+ BankAccount : +withdrawl(amount)
+
+classDiagram
+ class Animal
+ Vehicle <|-- Car
+
+class BankAccount
+ BankAccount : +String owner
+ BankAccount : +BigDecimal balance
+ BankAccount : +deposit(amount)
+ BankAccount : +withdrawal(amount)
+
+class BankAccount{
+ +String owner
+ +BigDecimal balance
+ +deposit(amount)
+ +withdrawl(amount)
+}
+
+class BankAccount{
+ +String owner
+ +BigDecimal balance
+ +deposit(amount) bool
+ +withdrawl(amount) int
+}
+
+classDiagram
+class Square~Shape~{
+ int id
+ List~int~ position
+ setPoints(List~int~ points)
+ getPoints() List~int~
+}
+
+Square : -List~string~ messages
+Square : +setMessages(List~string~ messages)
+Square : +getMessages() List~string~
+
+classDiagram
+classA <|-- classB
+classC *-- classD
+classE o-- classF
+classG <-- classH
+classI -- classJ
+classK <.. classL
+classM <|.. classN
+classO .. classP
+
+classDiagram
+classA --|> classB : Inheritance
+classC --* classD : Composition
+classE --o classF : Aggregation
+classG --> classH : Association
+classI -- classJ : Link(Solid)
+classK ..> classL : Dependency
+classM ..|> classN : Realization
+classO .. classP : Link(Dashed)
+
+classDiagram
+classA <|-- classB : implements
+classC *-- classD : composition
+classE o-- classF : association
+
+classDiagram
+ Customer "1" --> "*" Ticket
+ Student "1" --> "1..*" Course
+ Galaxy --> "many" Star : Contains
+
+classDiagram
+class Shape
+<> Shape
+
+classDiagram
+class Shape{
+ <>
+ noOfVertices
+ draw()
+}
+class Color{
+ <>
+ RED
+ BLUE
+ GREEN
+ WHITE
+ BLACK
+}
+
+classDiagram
+%% This whole line is a comment classDiagram class Shape <>
+class Shape{
+ <>
+ noOfVertices
+ draw()
+}
+
+classDiagram
+ direction RL
+ class Student {
+ -idCard : IdCard
+ }
+ class IdCard{
+ -id : int
+ -name : string
+ }
+ class Bike{
+ -id : int
+ -name : string
+ }
+ Student "1" --o "1" IdCard : carries
+ Student "1" --o "1" Bike : rides
+
+action className "reference" "tooltip"
+click className call callback() "tooltip"
+click className href "url" "tooltip"
+
+classDiagram
+class Shape
+link Shape "http://www.github.com" "This is a tooltip for a link"
+class Shape2
+click Shape2 href "http://www.github.com" "This is a tooltip for a link"
+
+classDiagram
+class Shape
+callback Shape "callbackFunction" "This is a tooltip for a callback"
+class Shape2
+click Shape2 call callbackFunction() "This is a tooltip for a callback"
+
+classDiagram
+Animal <|-- Duck
+Animal <|-- Fish
+Animal <|-- Zebra
+Animal : +int age
+Animal : +String gender
+Animal: +isMammal()
+Animal: +mate()
+class Duck{
+ +String beakColor
+ +swim()
+ +quack()
+ }
+class Fish{
+ -int sizeInFeet
+ -canEat()
+ }
+class Zebra{
+ +bool is_wild
+ +run()
+ }
+
+ callback Duck callback "Tooltip"
+ link Zebra "http://www.github.com" "This is a link"
+
+classDiagram
+ class Animal:::cssClass
+
+classDiagram
+ class Animal:::cssClass {
+ -int sizeInFeet
+ -canEat()
+ }
+
+----------------------------------------------------
+
+[
+ ["keyword", "classDiagram"],
+
+ "\r\n Animal ",
+ ["arrow", "<|--"],
+ " Duck\r\n Animal ",
+ ["arrow", "<|--"],
+ " Fish\r\n Animal ",
+ ["arrow", "<|--"],
+ " Zebra\r\n Animal ",
+ ["operator", ":"],
+ " +int age\r\n Animal ",
+ ["operator", ":"],
+ " +String gender\r\n Animal",
+ ["operator", ":"],
+ " +isMammal",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ "\r\n Animal",
+ ["operator", ":"],
+ " +mate",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["keyword", "class"],
+ " Duck",
+ ["punctuation", "{"],
+
+ "\r\n +String beakColor\r\n +swim",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ "\r\n +quack",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "class"],
+ " Fish",
+ ["punctuation", "{"],
+
+ "\r\n -int sizeInFeet\r\n -canEat",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "class"],
+ " Zebra",
+ ["punctuation", "{"],
+
+ "\r\n +bool is_wild\r\n +run",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "classDiagram"],
+
+ ["keyword", "class"],
+ " BankAccount\r\n BankAccount ",
+ ["operator", ":"],
+ " +String owner\r\n BankAccount ",
+ ["operator", ":"],
+ " +Bigdecimal balance\r\n BankAccount ",
+ ["operator", ":"],
+ " +deposit",
+ ["text", "(amount)"],
+
+ "\r\n BankAccount ",
+ ["operator", ":"],
+ " +withdrawl",
+ ["text", "(amount)"],
+
+ ["keyword", "classDiagram"],
+
+ ["keyword", "class"],
+ " Animal\r\n Vehicle ",
+ ["arrow", "<|--"],
+ " Car\r\n\r\n",
+
+ ["keyword", "class"],
+ " BankAccount\r\n BankAccount ",
+ ["operator", ":"],
+ " +String owner\r\n BankAccount ",
+ ["operator", ":"],
+ " +BigDecimal balance\r\n BankAccount ",
+ ["operator", ":"],
+ " +deposit",
+ ["text", "(amount)"],
+
+ "\r\n BankAccount ",
+ ["operator", ":"],
+ " +withdrawal",
+ ["text", "(amount)"],
+
+ ["keyword", "class"],
+ " BankAccount",
+ ["punctuation", "{"],
+
+ "\r\n +String owner\r\n +BigDecimal balance\r\n +deposit",
+ ["text", "(amount)"],
+
+ "\r\n +withdrawl",
+ ["text", "(amount)"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "class"],
+ " BankAccount",
+ ["punctuation", "{"],
+
+ "\r\n +String owner\r\n +BigDecimal balance\r\n +deposit",
+ ["text", "(amount)"],
+ " bool\r\n +withdrawl",
+ ["text", "(amount)"],
+ " int\r\n",
+
+ ["punctuation", "}"],
+
+ ["keyword", "classDiagram"],
+
+ ["keyword", "class"],
+ " Square~Shape~",
+ ["punctuation", "{"],
+
+ "\r\n int id\r\n List~int~ position\r\n setPoints",
+ ["text", "(List~int~ points)"],
+
+ "\r\n getPoints",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ " List~int~\r\n",
+
+ ["punctuation", "}"],
+
+ "\r\n\r\nSquare ",
+ ["operator", ":"],
+ " -List~string~ messages\r\nSquare ",
+ ["operator", ":"],
+ " +setMessages",
+ ["text", "(List~string~ messages)"],
+
+ "\r\nSquare ",
+ ["operator", ":"],
+ " +getMessages",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ " List~string~\r\n\r\n",
+
+ ["keyword", "classDiagram"],
+
+ "\r\nclassA ",
+ ["arrow", "<|--"],
+ " classB\r\nclassC ",
+ ["arrow", "*--"],
+ " classD\r\nclassE ",
+ ["arrow", "o--"],
+ " classF\r\nclassG ",
+ ["arrow", "<--"],
+ " classH\r\nclassI ",
+ ["arrow", "--"],
+ " classJ\r\nclassK ",
+ ["arrow", "<.."],
+ " classL\r\nclassM ",
+ ["arrow", "<|.."],
+ " classN\r\nclassO ",
+ ["arrow", ".."],
+ " classP\r\n\r\n",
+
+ ["keyword", "classDiagram"],
+
+ "\r\nclassA ",
+ ["arrow", "--|>"],
+ " classB ",
+ ["operator", ":"],
+ " Inheritance\r\nclassC ",
+ ["arrow", "--*"],
+ " classD ",
+ ["operator", ":"],
+ " Composition\r\nclassE ",
+ ["arrow", "--o"],
+ " classF ",
+ ["operator", ":"],
+ " Aggregation\r\nclassG ",
+ ["arrow", "-->"],
+ " classH ",
+ ["operator", ":"],
+ " Association\r\nclassI ",
+ ["arrow", "--"],
+ " classJ ",
+ ["operator", ":"],
+ " Link",
+ ["text", "(Solid)"],
+
+ "\r\nclassK ",
+ ["arrow", "..>"],
+ " classL ",
+ ["operator", ":"],
+ " Dependency\r\nclassM ",
+ ["arrow", "..|>"],
+ " classN ",
+ ["operator", ":"],
+ " Realization\r\nclassO ",
+ ["arrow", ".."],
+ " classP ",
+ ["operator", ":"],
+ " Link",
+ ["text", "(Dashed)"],
+
+ ["keyword", "classDiagram"],
+
+ "\r\nclassA ",
+ ["arrow", "<|--"],
+ " classB ",
+ ["operator", ":"],
+ " implements\r\nclassC ",
+ ["arrow", "*--"],
+ " classD ",
+ ["operator", ":"],
+ " composition\r\nclassE ",
+ ["arrow", "o--"],
+ " classF ",
+ ["operator", ":"],
+ " association\r\n\r\n",
+
+ ["keyword", "classDiagram"],
+
+ "\r\n Customer ",
+ ["string", "\"1\""],
+ ["arrow", "-->"],
+ ["string", "\"*\""],
+ " Ticket\r\n Student ",
+ ["string", "\"1\""],
+ ["arrow", "-->"],
+ ["string", "\"1..*\""],
+ " Course\r\n Galaxy ",
+ ["arrow", "-->"],
+ ["string", "\"many\""],
+ " Star ",
+ ["operator", ":"],
+ " Contains\r\n\r\n",
+
+ ["keyword", "classDiagram"],
+ ["keyword", "class"], " Shape\r\n",
+ ["annotation", "<>"], " Shape\r\n\r\n",
+
+ ["keyword", "classDiagram"],
+ ["keyword", "class"],
+ " Shape",
+ ["punctuation", "{"],
+ ["annotation", "<>"],
+ "\r\n noOfVertices\r\n draw",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["punctuation", "}"],
+ ["keyword", "class"],
+ " Color",
+ ["punctuation", "{"],
+ ["annotation", "<>"],
+ "\r\n RED\r\n BLUE\r\n GREEN\r\n WHITE\r\n BLACK\r\n",
+ ["punctuation", "}"],
+
+ ["keyword", "classDiagram"],
+ ["comment", "%% This whole line is a comment classDiagram class Shape <>"],
+ ["keyword", "class"],
+ " Shape",
+ ["punctuation", "{"],
+ ["annotation", "<>"],
+ "\r\n noOfVertices\r\n draw",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["punctuation", "}"],
+
+ ["keyword", "classDiagram"],
+
+ ["keyword", "direction"],
+ " RL\r\n ",
+
+ ["keyword", "class"],
+ " Student ",
+ ["punctuation", "{"],
+
+ "\r\n -idCard ",
+ ["operator", ":"],
+ " IdCard\r\n ",
+
+ ["punctuation", "}"],
+
+ ["keyword", "class"],
+ " IdCard",
+ ["punctuation", "{"],
+
+ "\r\n -id ",
+ ["operator", ":"],
+ " int\r\n -name ",
+ ["operator", ":"],
+ " string\r\n ",
+
+ ["punctuation", "}"],
+
+ ["keyword", "class"],
+ " Bike",
+ ["punctuation", "{"],
+
+ "\r\n -id ",
+ ["operator", ":"],
+ " int\r\n -name ",
+ ["operator", ":"],
+ " string\r\n ",
+
+ ["punctuation", "}"],
+
+ "\r\n Student ",
+ ["string", "\"1\""],
+ ["arrow", "--o"],
+ ["string", "\"1\""],
+ " IdCard ",
+ ["operator", ":"],
+ " carries\r\n Student ",
+ ["string", "\"1\""],
+ ["arrow", "--o"],
+ ["string", "\"1\""],
+ " Bike ",
+ ["operator", ":"],
+ " rides\r\n\r\n",
+
+ ["keyword", "action"],
+ " className ",
+ ["string", "\"reference\""],
+ ["string", "\"tooltip\""],
+
+ ["keyword", "click"],
+ " className call callback",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["string", "\"tooltip\""],
+
+ ["keyword", "click"],
+ " className href ",
+ ["string", "\"url\""],
+ ["string", "\"tooltip\""],
+
+ ["keyword", "classDiagram"],
+
+ ["keyword", "class"],
+ " Shape\r\n",
+
+ ["keyword", "link"],
+ " Shape ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"This is a tooltip for a link\""],
+
+ ["keyword", "class"],
+ " Shape2\r\n",
+
+ ["keyword", "click"],
+ " Shape2 href ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"This is a tooltip for a link\""],
+
+ ["keyword", "classDiagram"],
+
+ ["keyword", "class"],
+ " Shape\r\n",
+
+ ["keyword", "callback"],
+ " Shape ",
+ ["string", "\"callbackFunction\""],
+ ["string", "\"This is a tooltip for a callback\""],
+
+ ["keyword", "class"],
+ " Shape2\r\n",
+
+ ["keyword", "click"],
+ " Shape2 call callbackFunction",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["string", "\"This is a tooltip for a callback\""],
+
+ ["keyword", "classDiagram"],
+
+ "\r\nAnimal ",
+ ["arrow", "<|--"],
+ " Duck\r\nAnimal ",
+ ["arrow", "<|--"],
+ " Fish\r\nAnimal ",
+ ["arrow", "<|--"],
+ " Zebra\r\nAnimal ",
+ ["operator", ":"],
+ " +int age\r\nAnimal ",
+ ["operator", ":"],
+ " +String gender\r\nAnimal",
+ ["operator", ":"],
+ " +isMammal",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ "\r\nAnimal",
+ ["operator", ":"],
+ " +mate",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["keyword", "class"],
+ " Duck",
+ ["punctuation", "{"],
+
+ "\r\n +String beakColor\r\n +swim",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ "\r\n +quack",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "class"],
+ " Fish",
+ ["punctuation", "{"],
+
+ "\r\n -int sizeInFeet\r\n -canEat",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "class"],
+ " Zebra",
+ ["punctuation", "{"],
+
+ "\r\n +bool is_wild\r\n +run",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "callback"],
+ " Duck callback ",
+ ["string", "\"Tooltip\""],
+
+ ["keyword", "link"],
+ " Zebra ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"This is a link\""],
+
+ ["keyword", "classDiagram"],
+ ["keyword", "class"], " Animal", ["operator", ":::"], "cssClass\r\n\r\n",
+
+ ["keyword", "classDiagram"],
+
+ ["keyword", "class"],
+ " Animal",
+ ["operator", ":::"],
+ "cssClass ",
+ ["punctuation", "{"],
+
+ "\r\n -int sizeInFeet\r\n -canEat",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["punctuation", "}"]
+]
diff --git a/tests/languages/mermaid/full_erdiagram.test b/tests/languages/mermaid/full_erdiagram.test
new file mode 100644
index 0000000000..c88f2d46c6
--- /dev/null
+++ b/tests/languages/mermaid/full_erdiagram.test
@@ -0,0 +1,168 @@
+erDiagram
+ CUSTOMER ||--o{ ORDER : places
+ ORDER ||--|{ LINE-ITEM : contains
+ CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
+
+erDiagram
+ CUSTOMER ||--o{ ORDER : places
+ CUSTOMER {
+ string name
+ string custNumber
+ string sector
+ }
+ ORDER ||--|{ LINE-ITEM : contains
+ ORDER {
+ int orderNumber
+ string deliveryAddress
+ }
+ LINE-ITEM {
+ string productCode
+ int quantity
+ float pricePerUnit
+ }
+
+PROPERTY ||--|{ ROOM : contains
+
+CAR ||--o{ NAMED-DRIVER : allows
+ PERSON ||--o{ NAMED-DRIVER : is
+
+erDiagram
+ CAR ||--o{ NAMED-DRIVER : allows
+ CAR {
+ string registrationNumber
+ string make
+ string model
+ }
+ PERSON ||--o{ NAMED-DRIVER : is
+ PERSON {
+ string firstName
+ string lastName
+ int age
+ }
+
+erDiagram
+ CAR ||--o{ NAMED-DRIVER : allows
+ CAR {
+ string registrationNumber
+ string make
+ string model
+ }
+ PERSON ||--o{ NAMED-DRIVER : is
+ PERSON {
+ string firstName
+ string lastName
+ int age
+ }
+
+----------------------------------------------------
+
+[
+ ["keyword", "erDiagram"],
+
+ "\r\n CUSTOMER ",
+ ["arrow", "||--o{"],
+ " ORDER ",
+ ["operator", ":"],
+ " places\r\n ORDER ",
+ ["arrow", "||--|{"],
+ " LINE-ITEM ",
+ ["operator", ":"],
+ " contains\r\n CUSTOMER ",
+ ["arrow", "}|..|{"],
+ " DELIVERY-ADDRESS ",
+ ["operator", ":"],
+ " uses\r\n\r\n",
+
+ ["keyword", "erDiagram"],
+
+ "\r\n CUSTOMER ",
+ ["arrow", "||--o{"],
+ " ORDER ",
+ ["operator", ":"],
+ " places\r\n CUSTOMER ",
+ ["punctuation", "{"],
+
+ "\r\n string name\r\n string custNumber\r\n string sector\r\n ",
+
+ ["punctuation", "}"],
+
+ "\r\n ORDER ",
+ ["arrow", "||--|{"],
+ " LINE-ITEM ",
+ ["operator", ":"],
+ " contains\r\n ORDER ",
+ ["punctuation", "{"],
+
+ "\r\n int orderNumber\r\n string deliveryAddress\r\n ",
+
+ ["punctuation", "}"],
+
+ "\r\n LINE-ITEM ",
+ ["punctuation", "{"],
+
+ "\r\n string productCode\r\n int quantity\r\n float pricePerUnit\r\n ",
+
+ ["punctuation", "}"],
+
+ "\r\n\r\nPROPERTY ",
+ ["arrow", "||--|{"],
+ " ROOM ",
+ ["operator", ":"],
+ " contains\r\n\r\nCAR ",
+ ["arrow", "||--o{"],
+ " NAMED-DRIVER ",
+ ["operator", ":"],
+ " allows\r\n PERSON ",
+ ["arrow", "||--o{"],
+ " NAMED-DRIVER ",
+ ["operator", ":"],
+ " is\r\n\r\n",
+
+ ["keyword", "erDiagram"],
+
+ "\r\n CAR ",
+ ["arrow", "||--o{"],
+ " NAMED-DRIVER ",
+ ["operator", ":"],
+ " allows\r\n CAR ",
+ ["punctuation", "{"],
+
+ "\r\n string registrationNumber\r\n string make\r\n string model\r\n ",
+
+ ["punctuation", "}"],
+
+ "\r\n PERSON ",
+ ["arrow", "||--o{"],
+ " NAMED-DRIVER ",
+ ["operator", ":"],
+ " is\r\n PERSON ",
+ ["punctuation", "{"],
+
+ "\r\n string firstName\r\n string lastName\r\n int age\r\n ",
+
+ ["punctuation", "}"],
+
+ ["keyword", "erDiagram"],
+
+ "\r\n CAR ",
+ ["arrow", "||--o{"],
+ " NAMED-DRIVER ",
+ ["operator", ":"],
+ " allows\r\n CAR ",
+ ["punctuation", "{"],
+
+ "\r\n string registrationNumber\r\n string make\r\n string model\r\n ",
+
+ ["punctuation", "}"],
+
+ "\r\n PERSON ",
+ ["arrow", "||--o{"],
+ " NAMED-DRIVER ",
+ ["operator", ":"],
+ " is\r\n PERSON ",
+ ["punctuation", "{"],
+
+ "\r\n string firstName\r\n string lastName\r\n int age\r\n ",
+
+ ["punctuation", "}"]
+]
diff --git a/tests/languages/mermaid/full_flowchart.test b/tests/languages/mermaid/full_flowchart.test
new file mode 100644
index 0000000000..948af017cb
--- /dev/null
+++ b/tests/languages/mermaid/full_flowchart.test
@@ -0,0 +1,930 @@
+flowchart LR
+ id
+
+flowchart LR
+ id1[This is the text in the box]
+
+flowchart TD
+ Start --> Stop
+
+flowchart LR
+ Start --> Stop
+
+flowchart LR
+ id1(This is the text in the box)
+
+flowchart LR
+ id1([This is the text in the box])
+
+flowchart LR
+ id1[[This is the text in the box]]
+
+flowchart LR
+ id1[(Database)]
+
+flowchart LR
+ id1((This is the text in the circle))
+
+flowchart LR
+ id1>This is the text in the box]
+
+flowchart LR
+ id1{This is the text in the box}
+
+flowchart LR
+ id1{{This is the text in the box}}
+
+flowchart TD
+ id1[/This is the text in the box/]
+
+flowchart TD
+ id1[\This is the text in the box\]
+
+flowchart TD
+ A[/Christmas\]
+
+flowchart TD
+ B[\Go shopping/]
+
+flowchart LR
+ A-->B
+
+flowchart LR
+ A --- B
+
+flowchart LR
+ A-- This is the text! ---B
+
+flowchart LR
+ A---|This is the text|B
+
+flowchart LR
+ A-->|text|B
+
+flowchart LR
+ A-- text -->B
+
+flowchart LR;
+ A-.->B;
+
+flowchart LR
+ A-. text .-> B
+
+flowchart LR
+ A ==> B
+
+flowchart LR
+ A == text ==> B
+
+flowchart LR
+ A -- text --> B -- text2 --> C
+
+flowchart LR
+ a --> b & c--> d
+
+flowchart TB
+ A & B--> C & D
+
+flowchart TB
+ A --> C
+ A --> D
+ B --> C
+ B --> D
+
+flowchart LR
+ A --o B
+ B --x C
+
+flowchart LR
+ A o--o B
+ B <--> C
+ C x--x D
+
+flowchart TD
+ A[Start] --> B{Is it?};
+ B -->|Yes| C[OK];
+ C --> D[Rethink];
+ D --> B;
+ B ---->|No| E[End];
+
+flowchart TD
+ A[Start] --> B{Is it?};
+ B -- Yes --> C[OK];
+ C --> D[Rethink];
+ D --> B;
+ B -- No ----> E[End];
+
+flowchart LR
+ id1["This is the (text) in the box"]
+
+flowchart LR
+ A["A double quote:#quot;"] -->B["A dec char:#9829;"]
+
+subgraph title
+ graph definition
+end
+
+flowchart TB
+ c1-->a2
+ subgraph one
+ a1-->a2
+ end
+ subgraph two
+ b1-->b2
+ end
+ subgraph three
+ c1-->c2
+ end
+
+flowchart TB
+ c1-->a2
+ subgraph ide1 [one]
+ a1-->a2
+ end
+
+flowchart TB
+ c1-->a2
+ subgraph one
+ a1-->a2
+ end
+ subgraph two
+ b1-->b2
+ end
+ subgraph three
+ c1-->c2
+ end
+ one --> two
+ three --> two
+ two --> c2
+
+flowchart LR
+ subgraph TOP
+ direction TB
+ subgraph B1
+ direction RL
+ i1 -->f1
+ end
+ subgraph B2
+ direction BT
+ i2 -->f2
+ end
+ end
+ A --> TOP --> B
+ B1 --> B2
+
+click nodeId callback
+click nodeId call callback()
+
+flowchart LR;
+ A-->B;
+ B-->C;
+ C-->D;
+ click A callback "Tooltip for a callback"
+ click B "http://www.github.com" "This is a tooltip for a link"
+ click A call callback() "Tooltip for a callback"
+ click B href "http://www.github.com" "This is a tooltip for a link"
+
+flowchart LR;
+ A-->B;
+ B-->C;
+ C-->D;
+ D-->E;
+ click A "http://www.github.com" _blank
+ click B "http://www.github.com" "Open this in a new tab" _blank
+ click C href "http://www.github.com" _blank
+ click D href "http://www.github.com" "Open this in a new tab" _blank
+
+flowchart LR
+%% this is a comment A -- text --> B{node}
+ A -- text --> B -- text2 --> C
+
+linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
+
+flowchart LR
+ id1(Start)-->id2(Stop)
+ style id1 fill:#f9f,stroke:#333,stroke-width:4px
+ style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
+
+classDef className fill:#f9f,stroke:#333,stroke-width:4px;
+
+class nodeId1 className;
+
+class nodeId1,nodeId2 className;
+
+flowchart LR
+ A:::someclass --> B
+ classDef someclass fill:#f96;
+
+flowchart LR;
+ A-->B[AAABBB];
+ B-->D;
+ class A cssClass;
+
+classDef default fill:#f9f,stroke:#333,stroke-width:4px;
+
+flowchart TD
+ B["fa:fa-twitter for peace"]
+ B-->C[fa:fa-ban forbidden]
+ B-->D(fa:fa-spinner);
+ B-->E(A fa:fa-camera-retro perhaps?);
+
+flowchart LR
+ A[Hard edge] -->|Link text| B(Round edge)
+ B --> C{Decision}
+ C -->|One| D[Result one]
+ C -->|Two| E[Result two]
+
+ flowchart LR;
+ A-->B;
+ B-->C;
+ C-->D;
+ click A callback "Tooltip"
+ click B "http://www.github.com" "This is a link"
+ click C call callback() "Tooltip"
+ click D href "http://www.github.com" "This is a link"
+
+----------------------------------------------------
+
+[
+ ["keyword", "flowchart"], " LR\r\n id\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "[This is the text in the box]"],
+
+ ["keyword", "flowchart"],
+ " TD\r\n Start ",
+ ["arrow", "-->"],
+ " Stop\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n Start ",
+ ["arrow", "-->"],
+ " Stop\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "(This is the text in the box)"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "([This is the text in the box])"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "[[This is the text in the box]]"],
+
+ ["keyword", "flowchart"], " LR\r\n id1", ["text", "[(Database)]"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "((This is the text in the circle))"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", ">This is the text in the box]"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "{This is the text in the box}"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "{{This is the text in the box}}"],
+
+ ["keyword", "flowchart"],
+ " TD\r\n id1",
+ ["text", "[/This is the text in the box/]"],
+
+ ["keyword", "flowchart"],
+ " TD\r\n id1",
+ ["text", "[\\This is the text in the box\\]"],
+
+ ["keyword", "flowchart"], " TD\r\n A", ["text", "[/Christmas\\]"],
+
+ ["keyword", "flowchart"], " TD\r\n B", ["text", "[\\Go shopping/]"],
+
+ ["keyword", "flowchart"], " LR\r\n A", ["arrow", "-->"], "B\r\n\r\n",
+
+ ["keyword", "flowchart"], " LR\r\n A ", ["arrow", "---"], " B\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "This is the text!"],
+ ["arrow", "---"]
+ ]],
+ "B\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["arrow", "---"],
+ ["label", "|This is the text|"],
+ "B\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["arrow", "-->"],
+ ["label", "|text|"],
+ "B\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "text"],
+ ["arrow", "-->"]
+ ]],
+ "B\r\n\r\n",
+
+ ["keyword", "flowchart"], " LR", ["punctuation", ";"],
+ "\r\n A", ["arrow", "-.->"], "B", ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["inter-arrow-label", [
+ ["arrow-head", "-."],
+ ["label", "text"],
+ ["arrow", ".->"]
+ ]],
+ " B\r\n\r\n",
+
+ ["keyword", "flowchart"], " LR\r\n A ", ["arrow", "==>"], " B\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A ",
+ ["inter-arrow-label", [
+ ["arrow-head", "=="],
+ ["label", "text"],
+ ["arrow", "==>"]
+ ]],
+ " B\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "text"],
+ ["arrow", "-->"]
+ ]],
+ " B ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "text2"],
+ ["arrow", "-->"]
+ ]],
+ " C\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n a ",
+ ["arrow", "-->"],
+ " b ",
+ ["operator", "&"],
+ " c",
+ ["arrow", "-->"],
+ " d\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " TB\r\n A ",
+ ["operator", "&"],
+ " B",
+ ["arrow", "-->"],
+ " C ",
+ ["operator", "&"],
+ " D\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " TB\r\n A ",
+ ["arrow", "-->"],
+ " C\r\n A ",
+ ["arrow", "-->"],
+ " D\r\n B ",
+ ["arrow", "-->"],
+ " C\r\n B ",
+ ["arrow", "-->"],
+ " D\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A ",
+ ["arrow", "--o"],
+ " B\r\n B ",
+ ["arrow", "--x"],
+ " C\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n A ",
+ ["arrow", "o--o"],
+ " B\r\n B ",
+ ["arrow", "<-->"],
+ " C\r\n C ",
+ ["arrow", "x--x"],
+ " D\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " TD\r\n A",
+ ["text", "[Start]"],
+ ["arrow", "-->"],
+ " B",
+ ["text", "{Is it?}"],
+ ["punctuation", ";"],
+
+ "\r\n B ",
+ ["arrow", "-->"],
+ ["label", "|Yes|"],
+ " C",
+ ["text", "[OK]"],
+ ["punctuation", ";"],
+
+ "\r\n C ",
+ ["arrow", "-->"],
+ " D",
+ ["text", "[Rethink]"],
+ ["punctuation", ";"],
+
+ "\r\n D ",
+ ["arrow", "-->"],
+ " B",
+ ["punctuation", ";"],
+
+ "\r\n B ",
+ ["arrow", "---->"],
+ ["label", "|No|"],
+ " E",
+ ["text", "[End]"],
+ ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " TD\r\n A",
+ ["text", "[Start]"],
+ ["arrow", "-->"],
+ " B",
+ ["text", "{Is it?}"],
+ ["punctuation", ";"],
+
+ "\r\n B ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "Yes"],
+ ["arrow", "-->"]
+ ]],
+ " C",
+ ["text", "[OK]"],
+ ["punctuation", ";"],
+
+ "\r\n C ",
+ ["arrow", "-->"],
+ " D",
+ ["text", "[Rethink]"],
+ ["punctuation", ";"],
+
+ "\r\n D ",
+ ["arrow", "-->"],
+ " B",
+ ["punctuation", ";"],
+
+ "\r\n B ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "No"],
+ ["arrow", "---->"]
+ ]],
+ " E",
+ ["text", "[End]"],
+ ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "[\"This is the (text) in the box\"]"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["text", "[\"A double quote:#quot;\"]"],
+ ["arrow", "-->"],
+ "B",
+ ["text", "[\"A dec char:#9829;\"]"],
+
+ ["keyword", "subgraph"], " title\r\n ",
+ ["keyword", "graph"], " definition\r\n",
+ ["keyword", "end"],
+
+ ["keyword", "flowchart"], " TB\r\n c1", ["arrow", "-->"], "a2\r\n ",
+ ["keyword", "subgraph"], " one\r\n a1", ["arrow", "-->"], "a2\r\n ",
+ ["keyword", "end"],
+ ["keyword", "subgraph"], " two\r\n b1", ["arrow", "-->"], "b2\r\n ",
+ ["keyword", "end"],
+ ["keyword", "subgraph"], " three\r\n c1", ["arrow", "-->"], "c2\r\n ",
+ ["keyword", "end"],
+
+ ["keyword", "flowchart"], " TB\r\n c1", ["arrow", "-->"], "a2\r\n ",
+ ["keyword", "subgraph"], " ide1 ", ["text", "[one]"],
+ "\r\n a1", ["arrow", "-->"], "a2\r\n ",
+ ["keyword", "end"],
+
+ ["keyword", "flowchart"],
+ " TB\r\n c1",
+ ["arrow", "-->"],
+ "a2\r\n ",
+
+ ["keyword", "subgraph"],
+ " one\r\n a1",
+ ["arrow", "-->"],
+ "a2\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "subgraph"],
+ " two\r\n b1",
+ ["arrow", "-->"],
+ "b2\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "subgraph"],
+ " three\r\n c1",
+ ["arrow", "-->"],
+ "c2\r\n ",
+
+ ["keyword", "end"],
+
+ "\r\n one ",
+ ["arrow", "-->"],
+ " two\r\n three ",
+ ["arrow", "-->"],
+ " two\r\n two ",
+ ["arrow", "-->"],
+ " c2\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n ",
+
+ ["keyword", "subgraph"],
+ " TOP\r\n ",
+
+ ["keyword", "direction"],
+ " TB\r\n ",
+
+ ["keyword", "subgraph"],
+ " B1\r\n ",
+
+ ["keyword", "direction"],
+ " RL\r\n i1 ",
+ ["arrow", "-->"],
+ "f1\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "subgraph"],
+ " B2\r\n ",
+
+ ["keyword", "direction"],
+ " BT\r\n i2 ",
+ ["arrow", "-->"],
+ "f2\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "end"],
+
+ "\r\n A ",
+ ["arrow", "-->"],
+ " TOP ",
+ ["arrow", "-->"],
+ " B\r\n B1 ",
+ ["arrow", "-->"],
+ " B2\r\n\r\n",
+
+ ["keyword", "click"],
+ " nodeId callback\r\n",
+
+ ["keyword", "click"],
+ " nodeId call callback",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+
+ ["keyword", "flowchart"],
+ " LR",
+ ["punctuation", ";"],
+
+ "\r\n A",
+ ["arrow", "-->"],
+ "B",
+ ["punctuation", ";"],
+
+ "\r\n B",
+ ["arrow", "-->"],
+ "C",
+ ["punctuation", ";"],
+
+ "\r\n C",
+ ["arrow", "-->"],
+ "D",
+ ["punctuation", ";"],
+
+ ["keyword", "click"],
+ " A callback ",
+ ["string", "\"Tooltip for a callback\""],
+
+ ["keyword", "click"],
+ " B ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"This is a tooltip for a link\""],
+
+ ["keyword", "click"],
+ " A call callback",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["string", "\"Tooltip for a callback\""],
+
+ ["keyword", "click"],
+ " B href ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"This is a tooltip for a link\""],
+
+ ["keyword", "flowchart"],
+ " LR",
+ ["punctuation", ";"],
+
+ "\r\n A",
+ ["arrow", "-->"],
+ "B",
+ ["punctuation", ";"],
+
+ "\r\n B",
+ ["arrow", "-->"],
+ "C",
+ ["punctuation", ";"],
+
+ "\r\n C",
+ ["arrow", "-->"],
+ "D",
+ ["punctuation", ";"],
+
+ "\r\n D",
+ ["arrow", "-->"],
+ "E",
+ ["punctuation", ";"],
+
+ ["keyword", "click"],
+ " A ",
+ ["string", "\"http://www.github.com\""],
+ " _blank\r\n ",
+
+ ["keyword", "click"],
+ " B ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"Open this in a new tab\""],
+ " _blank\r\n ",
+
+ ["keyword", "click"],
+ " C href ",
+ ["string", "\"http://www.github.com\""],
+ " _blank\r\n ",
+
+ ["keyword", "click"],
+ " D href ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"Open this in a new tab\""],
+ " _blank\r\n\r\n",
+
+ ["keyword", "flowchart"],
+ " LR\r\n",
+
+ ["comment", "%% this is a comment A -- text --> B{node}"],
+
+ "\r\n A ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "text"],
+ ["arrow", "-->"]
+ ]],
+ " B ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "text2"],
+ ["arrow", "-->"]
+ ]],
+ " C\r\n\r\n",
+
+ ["keyword", "linkStyle"],
+ " 3 ",
+ ["style", [
+ ["property", "stroke"],
+ ["operator", ":"],
+ "#ff3",
+ ["punctuation", ","],
+ ["property", "stroke-width"],
+ ["operator", ":"],
+ "4px",
+ ["punctuation", ","],
+ ["property", "color"],
+ ["operator", ":"],
+ "red"
+ ]],
+ ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n id1",
+ ["text", "(Start)"],
+ ["arrow", "-->"],
+ "id2",
+ ["text", "(Stop)"],
+
+ ["keyword", "style"],
+ " id1 ",
+ ["style", [
+ ["property", "fill"],
+ ["operator", ":"],
+ "#f9f",
+ ["punctuation", ","],
+ ["property", "stroke"],
+ ["operator", ":"],
+ "#333",
+ ["punctuation", ","],
+ ["property", "stroke-width"],
+ ["operator", ":"],
+ "4px"
+ ]],
+
+ ["keyword", "style"],
+ " id2 ",
+ ["style", [
+ ["property", "fill"],
+ ["operator", ":"],
+ "#bbf",
+ ["punctuation", ","],
+ ["property", "stroke"],
+ ["operator", ":"],
+ "#f66",
+ ["punctuation", ","],
+ ["property", "stroke-width"],
+ ["operator", ":"],
+ "2px",
+ ["punctuation", ","],
+ ["property", "color"],
+ ["operator", ":"],
+ "#fff",
+ ["punctuation", ","],
+ ["property", "stroke-dasharray"],
+ ["operator", ":"],
+ " 5 5"
+ ]],
+
+ ["keyword", "classDef"],
+ " className ",
+ ["style", [
+ ["property", "fill"],
+ ["operator", ":"],
+ "#f9f",
+ ["punctuation", ","],
+ ["property", "stroke"],
+ ["operator", ":"],
+ "#333",
+ ["punctuation", ","],
+ ["property", "stroke-width"],
+ ["operator", ":"],
+ "4px"
+ ]],
+ ["punctuation", ";"],
+
+ ["keyword", "class"], " nodeId1 className", ["punctuation", ";"],
+
+ ["keyword", "class"], " nodeId1,nodeId2 className", ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["operator", ":::"],
+ "someclass ",
+ ["arrow", "-->"],
+ " B\r\n ",
+
+ ["keyword", "classDef"],
+ " someclass ",
+ ["style", [
+ ["property", "fill"],
+ ["operator", ":"],
+ "#f96"
+ ]],
+ ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " LR",
+ ["punctuation", ";"],
+
+ "\r\n A",
+ ["arrow", "-->"],
+ "B",
+ ["text", "[AAABBB]"],
+ ["punctuation", ";"],
+
+ "\r\n B",
+ ["arrow", "-->"],
+ "D",
+ ["punctuation", ";"],
+
+ ["keyword", "class"],
+ " A cssClass",
+ ["punctuation", ";"],
+
+ ["keyword", "classDef"],
+ " default ",
+ ["style", [
+ ["property", "fill"],
+ ["operator", ":"],
+ "#f9f",
+ ["punctuation", ","],
+ ["property", "stroke"],
+ ["operator", ":"],
+ "#333",
+ ["punctuation", ","],
+ ["property", "stroke-width"],
+ ["operator", ":"],
+ "4px"
+ ]],
+ ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " TD\r\n B",
+ ["text", "[\"fa:fa-twitter for peace\"]"],
+
+ "\r\n B",
+ ["arrow", "-->"],
+ "C",
+ ["text", "[fa:fa-ban forbidden]"],
+
+ "\r\n B",
+ ["arrow", "-->"],
+ "D",
+ ["text", "(fa:fa-spinner)"],
+ ["punctuation", ";"],
+
+ "\r\n B",
+ ["arrow", "-->"],
+ "E",
+ ["text", "(A fa:fa-camera-retro perhaps?)"],
+ ["punctuation", ";"],
+
+ ["keyword", "flowchart"],
+ " LR\r\n A",
+ ["text", "[Hard edge]"],
+ ["arrow", "-->"],
+ ["label", "|Link text|"],
+ " B",
+ ["text", "(Round edge)"],
+
+ "\r\n B ",
+ ["arrow", "-->"],
+ " C",
+ ["text", "{Decision}"],
+
+ "\r\n C ",
+ ["arrow", "-->"],
+ ["label", "|One|"],
+ " D",
+ ["text", "[Result one]"],
+
+ "\r\n C ",
+ ["arrow", "-->"],
+ ["label", "|Two|"],
+ " E",
+ ["text", "[Result two]"],
+
+ ["keyword", "flowchart"],
+ " LR",
+ ["punctuation", ";"],
+
+ "\r\n A",
+ ["arrow", "-->"],
+ "B",
+ ["punctuation", ";"],
+
+ "\r\n B",
+ ["arrow", "-->"],
+ "C",
+ ["punctuation", ";"],
+
+ "\r\n C",
+ ["arrow", "-->"],
+ "D",
+ ["punctuation", ";"],
+
+ ["keyword", "click"],
+ " A callback ",
+ ["string", "\"Tooltip\""],
+
+ ["keyword", "click"],
+ " B ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"This is a link\""],
+
+ ["keyword", "click"],
+ " C call callback",
+ ["punctuation", "("],
+ ["punctuation", ")"],
+ ["string", "\"Tooltip\""],
+
+ ["keyword", "click"],
+ " D href ",
+ ["string", "\"http://www.github.com\""],
+ ["string", "\"This is a link\""]
+]
diff --git a/tests/languages/mermaid/full_sequencediagram.test b/tests/languages/mermaid/full_sequencediagram.test
new file mode 100644
index 0000000000..ec954bc24d
--- /dev/null
+++ b/tests/languages/mermaid/full_sequencediagram.test
@@ -0,0 +1,389 @@
+sequenceDiagram
+ Alice->>John: Hello John, how are you?
+ John-->>Alice: Great!
+ Alice-)John: See you later!
+
+sequenceDiagram
+ participant John
+ participant Alice
+ Alice->>John: Hello John, how are you?
+ John-->>Alice: Great!
+
+sequenceDiagram
+ participant A as Alice
+ participant J as John
+ A->>J: Hello John, how are you?
+ J->>A: Great!
+
+[Actor][Arrow][Actor]:Message text
+
+sequenceDiagram
+ Alice->>John: Hello John, how are you?
+ activate John
+ John-->>Alice: Great!
+ deactivate John
+
+sequenceDiagram
+ Alice->>+John: Hello John, how are you?
+ John-->>-Alice: Great!
+
+sequenceDiagram
+ Alice->>+John: Hello John, how are you?
+ Alice->>+John: John, can you hear me?
+ John-->>-Alice: Hi Alice, I can hear you!
+ John-->>-Alice: I feel great!
+
+sequenceDiagram
+ participant John
+ Note right of John: Text in note
+
+sequenceDiagram
+ Alice->John: Hello John, how are you?
+ Note over Alice,John: A typical interaction
+
+loop Loop text
+... statements ...
+end
+
+sequenceDiagram
+ Alice->John: Hello John, how are you?
+ loop Every minute
+ John-->Alice: Great!
+ end
+
+alt Describing text
+... statements ...
+else
+... statements ...
+end
+
+opt Describing text
+... statements ...
+end
+
+sequenceDiagram
+ Alice->>Bob: Hello Bob, how are you?
+ alt is sick
+ Bob->>Alice: Not so good :(
+ else is well
+ Bob->>Alice: Feeling fresh like a daisy
+ end
+ opt Extra response
+ Bob->>Alice: Thanks for asking
+ end
+
+par [Action 1]
+... statements ...
+and [Action 2]
+... statements ...
+and [Action N]
+... statements ...
+end
+
+rect rgb(0, 255, 0)
+... content ...
+end
+
+rect rgba(0, 0, 255, .1)
+... content ...
+end
+
+sequenceDiagram
+ Alice->>John: Hello John, how are you?
+ %% this is a comment
+ John-->>Alice: Great!
+
+sequenceDiagram
+ A->>B: I #9829; you!
+ B->>A: I #9829; you #infin; times more!
+
+sequenceDiagram
+ autonumber
+ Alice->>John: Hello John, how are you?
+ loop Healthcheck
+ John->>John: Fight against hypochondria
+ end
+ Note right of John: Rational thoughts!
+ John-->>Alice: Great!
+ John->>Bob: How about you?
+ Bob-->>John: Jolly good!
+
+----------------------------------------------------
+
+[
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->>"],
+ "John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n John",
+ ["arrow", "-->>"],
+ "Alice",
+ ["operator", ":"],
+ " Great!\r\n Alice",
+ ["arrow", "-)"],
+ "John",
+ ["operator", ":"],
+ " See you later!\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ ["keyword", "participant"],
+ " John\r\n ",
+
+ ["keyword", "participant"],
+ " Alice\r\n Alice",
+ ["arrow", "->>"],
+ "John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n John",
+ ["arrow", "-->>"],
+ "Alice",
+ ["operator", ":"],
+ " Great!\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ ["keyword", "participant"],
+ " A as Alice\r\n ",
+
+ ["keyword", "participant"],
+ " J as John\r\n A",
+ ["arrow", "->>"],
+ "J",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n J",
+ ["arrow", "->>"],
+ "A",
+ ["operator", ":"],
+ " Great!\r\n\r\n",
+
+ ["text", "[Actor]"],
+ ["text", "[Arrow]"],
+ ["text", "[Actor]"],
+ ["operator", ":"],
+ "Message text\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->>"],
+ "John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n ",
+
+ ["keyword", "activate"],
+ " John\r\n John",
+ ["arrow", "-->>"],
+ "Alice",
+ ["operator", ":"],
+ " Great!\r\n ",
+
+ ["keyword", "deactivate"],
+ " John\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->>"],
+ "+John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n John",
+ ["arrow", "-->>"],
+ "-Alice",
+ ["operator", ":"],
+ " Great!\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->>"],
+ "+John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n Alice",
+ ["arrow", "->>"],
+ "+John",
+ ["operator", ":"],
+ " John, can you hear me?\r\n John",
+ ["arrow", "-->>"],
+ "-Alice",
+ ["operator", ":"],
+ " Hi Alice, I can hear you!\r\n John",
+ ["arrow", "-->>"],
+ "-Alice",
+ ["operator", ":"],
+ " I feel great!\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ ["keyword", "participant"],
+ " John\r\n ",
+
+ ["keyword", "Note right of"],
+ " John",
+ ["operator", ":"],
+ " Text in note\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->"],
+ "John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n ",
+
+ ["keyword", "Note over"],
+ " Alice,John",
+ ["operator", ":"],
+ " A typical interaction\r\n\r\n",
+
+ ["keyword", "loop"], " Loop text\r\n... statements ...\r\n",
+ ["keyword", "end"],
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->"],
+ "John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n ",
+
+ ["keyword", "loop"],
+ " Every minute\r\n John",
+ ["arrow", "-->"],
+ "Alice",
+ ["operator", ":"],
+ " Great!\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "alt"], " Describing text\r\n... statements ...\r\n",
+ ["keyword", "else"],
+ "\r\n... statements ...\r\n",
+ ["keyword", "end"],
+
+ ["keyword", "opt"], " Describing text\r\n... statements ...\r\n",
+ ["keyword", "end"],
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->>"],
+ "Bob",
+ ["operator", ":"],
+ " Hello Bob, how are you?\r\n ",
+
+ ["keyword", "alt"],
+ " is sick\r\n Bob",
+ ["arrow", "->>"],
+ "Alice",
+ ["operator", ":"],
+ " Not so good ",
+ ["operator", ":"],
+ ["punctuation", "("],
+
+ ["keyword", "else"],
+ " is well\r\n Bob",
+ ["arrow", "->>"],
+ "Alice",
+ ["operator", ":"],
+ " Feeling fresh like a daisy\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "opt"],
+ " Extra response\r\n Bob",
+ ["arrow", "->>"],
+ "Alice",
+ ["operator", ":"],
+ " Thanks for asking\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "par"], ["text", "[Action 1]"],
+ "\r\n... statements ...\r\n",
+ ["keyword", "and"], ["text", "[Action 2]"],
+ "\r\n... statements ...\r\n",
+ ["keyword", "and"], ["text", "[Action N]"],
+ "\r\n... statements ...\r\n",
+ ["keyword", "end"],
+
+ ["keyword", "rect"], " rgb", ["text", "(0, 255, 0)"],
+ "\r\n... content ...\r\n",
+ ["keyword", "end"],
+
+ ["keyword", "rect"], " rgba", ["text", "(0, 0, 255, .1)"],
+ "\r\n... content ...\r\n",
+ ["keyword", "end"],
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n Alice",
+ ["arrow", "->>"],
+ "John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n ",
+
+ ["comment", "%% this is a comment"],
+
+ "\r\n John",
+ ["arrow", "-->>"],
+ "Alice",
+ ["operator", ":"],
+ " Great!\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ "\r\n A",
+ ["arrow", "->>"],
+ "B",
+ ["operator", ":"],
+ " I ",
+ ["entity", "#9829;"],
+ " you!\r\n B",
+ ["arrow", "->>"],
+ "A",
+ ["operator", ":"],
+ " I ",
+ ["entity", "#9829;"],
+ " you ",
+ ["entity", "#infin;"],
+ " times more!\r\n\r\n",
+
+ ["keyword", "sequenceDiagram"],
+
+ ["keyword", "autonumber"],
+
+ "\r\n Alice",
+ ["arrow", "->>"],
+ "John",
+ ["operator", ":"],
+ " Hello John, how are you?\r\n ",
+
+ ["keyword", "loop"],
+ " Healthcheck\r\n John",
+ ["arrow", "->>"],
+ "John",
+ ["operator", ":"],
+ " Fight against hypochondria\r\n ",
+
+ ["keyword", "end"],
+
+ ["keyword", "Note right of"],
+ " John",
+ ["operator", ":"],
+ " Rational thoughts!\r\n John",
+ ["arrow", "-->>"],
+ "Alice",
+ ["operator", ":"],
+ " Great!\r\n John",
+ ["arrow", "->>"],
+ "Bob",
+ ["operator", ":"],
+ " How about you?\r\n Bob",
+ ["arrow", "-->>"],
+ "John",
+ ["operator", ":"],
+ " Jolly good!"
+]
diff --git a/tests/languages/mermaid/full_statediagram.test b/tests/languages/mermaid/full_statediagram.test
new file mode 100644
index 0000000000..a5d1f27bf4
--- /dev/null
+++ b/tests/languages/mermaid/full_statediagram.test
@@ -0,0 +1,430 @@
+stateDiagram-v2
+ [*] --> Still
+ Still --> [*]
+
+ Still --> Moving
+ Moving --> Still
+ Moving --> Crash
+ Crash --> [*]
+
+stateDiagram-v2
+ s1 --> s2
+
+stateDiagram-v2
+ s1 --> s2: A transition
+
+stateDiagram-v2
+ [*] --> s1
+ s1 --> [*]
+
+stateDiagram-v2
+ [*] --> First
+ state First {
+ [*] --> second
+ second --> [*]
+ }
+
+stateDiagram-v2
+ [*] --> First
+
+ state First {
+ [*] --> Second
+
+ state Second {
+ [*] --> second
+ second --> Third
+
+ state Third {
+ [*] --> third
+ third --> [*]
+ }
+ }
+ }
+
+stateDiagram-v2
+ [*] --> First
+ First --> Second
+ First --> Third
+
+ state First {
+ [*] --> fir
+ fir --> [*]
+ }
+ state Second {
+ [*] --> sec
+ sec --> [*]
+ }
+ state Third {
+ [*] --> thi
+ thi --> [*]
+ }
+
+stateDiagram-v2
+ state if_state <>
+ [*] --> IsPositive
+ IsPositive --> if_state
+ if_state --> False: if n < 0
+ if_state --> True : if n >= 0
+
+stateDiagram-v2
+ state fork_state <>
+ [*] --> fork_state
+ fork_state --> State2
+ fork_state --> State3
+
+ state join_state <>
+ State2 --> join_state
+ State3 --> join_state
+ join_state --> State4
+ State4 --> [*]
+
+stateDiagram-v2
+ State1: The state with a note
+ note right of State1
+ Important information! You can write
+ notes.
+ end note
+ State1 --> State2
+ note left of State2 : This is the note to the left.
+
+stateDiagram-v2
+ [*] --> Active
+
+ state Active {
+ [*] --> NumLockOff
+ NumLockOff --> NumLockOn : EvNumLockPressed
+ NumLockOn --> NumLockOff : EvNumLockPressed
+ --
+ [*] --> CapsLockOff
+ CapsLockOff --> CapsLockOn : EvCapsLockPressed
+ CapsLockOn --> CapsLockOff : EvCapsLockPressed
+ --
+ [*] --> ScrollLockOff
+ ScrollLockOff --> ScrollLockOn : EvScrollLockPressed
+ ScrollLockOn --> ScrollLockOff : EvScrollLockPressed
+ }
+
+stateDiagram
+ direction LR
+ [*] --> A
+ A --> B
+ B --> C
+ state B {
+ direction LR
+ a --> b
+ }
+ B --> D
+
+stateDiagram-v2
+ [*] --> Still
+ Still --> [*]
+%% this is a comment
+ Still --> Moving
+ Moving --> Still %% another comment
+ Moving --> Crash
+ Crash --> [*]
+
+----------------------------------------------------
+
+[
+ ["keyword", "stateDiagram-v2"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " Still\r\n Still ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ "\r\n\r\n Still ",
+ ["arrow", "-->"],
+ " Moving\r\n Moving ",
+ ["arrow", "-->"],
+ " Still\r\n Moving ",
+ ["arrow", "-->"],
+ " Crash\r\n Crash ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["keyword", "stateDiagram-v2"],
+ "\r\n s1 ", ["arrow", "-->"], " s2\r\n\r\n",
+
+ ["keyword", "stateDiagram-v2"],
+
+ "\r\n s1 ",
+ ["arrow", "-->"],
+ " s2",
+ ["operator", ":"],
+ " A transition\r\n\r\n",
+
+ ["keyword", "stateDiagram-v2"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " s1\r\n s1 ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["keyword", "stateDiagram-v2"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " First\r\n ",
+
+ ["keyword", "state"],
+ " First ",
+ ["punctuation", "{"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " second\r\n second ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "stateDiagram-v2"],
+ ["text", "[*]"], ["arrow", "-->"], " First\r\n\r\n ",
+
+ ["keyword", "state"], " First ", ["punctuation", "{"],
+ ["text", "[*]"], ["arrow", "-->"], " Second\r\n\r\n ",
+
+ ["keyword", "state"],
+ " Second ",
+ ["punctuation", "{"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " second\r\n second ",
+ ["arrow", "-->"],
+ " Third\r\n\r\n ",
+
+ ["keyword", "state"],
+ " Third ",
+ ["punctuation", "{"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " third\r\n third ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["punctuation", "}"],
+
+ ["punctuation", "}"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "stateDiagram-v2"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " First\r\n First ",
+ ["arrow", "-->"],
+ " Second\r\n First ",
+ ["arrow", "-->"],
+ " Third\r\n\r\n ",
+
+ ["keyword", "state"],
+ " First ",
+ ["punctuation", "{"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " fir\r\n fir ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "state"],
+ " Second ",
+ ["punctuation", "{"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " sec\r\n sec ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "state"],
+ " Third ",
+ ["punctuation", "{"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " thi\r\n thi ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["punctuation", "}"],
+
+ ["keyword", "stateDiagram-v2"],
+
+ ["keyword", "state"],
+ " if_state ",
+ ["annotation", "<>"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " IsPositive\r\n IsPositive ",
+ ["arrow", "-->"],
+ " if_state\r\n if_state ",
+ ["arrow", "-->"],
+ " False",
+ ["operator", ":"],
+ " if n < 0\r\n if_state ",
+ ["arrow", "-->"],
+ " True ",
+ ["operator", ":"],
+ " if n >= 0\r\n\r\n",
+
+ ["keyword", "stateDiagram-v2"],
+
+ ["keyword", "state"],
+ " fork_state ",
+ ["annotation", "<>"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " fork_state\r\n fork_state ",
+ ["arrow", "-->"],
+ " State2\r\n fork_state ",
+ ["arrow", "-->"],
+ " State3\r\n\r\n ",
+
+ ["keyword", "state"],
+ " join_state ",
+ ["annotation", "<>"],
+
+ "\r\n State2 ",
+ ["arrow", "-->"],
+ " join_state\r\n State3 ",
+ ["arrow", "-->"],
+ " join_state\r\n join_state ",
+ ["arrow", "-->"],
+ " State4\r\n State4 ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["keyword", "stateDiagram-v2"],
+
+ "\r\n State1",
+ ["operator", ":"],
+ " The state with a note\r\n ",
+
+ ["keyword", "note right of"],
+ " State1\r\n Important information! You can write\r\n notes.\r\n ",
+
+ ["keyword", "end note"],
+
+ "\r\n State1 ",
+ ["arrow", "-->"],
+ " State2\r\n ",
+
+ ["keyword", "note left of"],
+ " State2 ",
+ ["operator", ":"],
+ " This is the note to the left.\r\n\r\n",
+
+ ["keyword", "stateDiagram-v2"],
+ ["text", "[*]"], ["arrow", "-->"], " Active\r\n\r\n ",
+
+ ["keyword", "state"],
+ " Active ",
+ ["punctuation", "{"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " NumLockOff\r\n NumLockOff ",
+ ["arrow", "-->"],
+ " NumLockOn ",
+ ["operator", ":"],
+ " EvNumLockPressed\r\n NumLockOn ",
+ ["arrow", "-->"],
+ " NumLockOff ",
+ ["operator", ":"],
+ " EvNumLockPressed\r\n ",
+
+ ["arrow", "--"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " CapsLockOff\r\n CapsLockOff ",
+ ["arrow", "-->"],
+ " CapsLockOn ",
+ ["operator", ":"],
+ " EvCapsLockPressed\r\n CapsLockOn ",
+ ["arrow", "-->"],
+ " CapsLockOff ",
+ ["operator", ":"],
+ " EvCapsLockPressed\r\n ",
+
+ ["arrow", "--"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " ScrollLockOff\r\n ScrollLockOff ",
+ ["arrow", "-->"],
+ " ScrollLockOn ",
+ ["operator", ":"],
+ " EvScrollLockPressed\r\n ScrollLockOn ",
+ ["arrow", "-->"],
+ " ScrollLockOff ",
+ ["operator", ":"],
+ " EvScrollLockPressed\r\n ",
+
+ ["punctuation", "}"],
+
+ ["keyword", "stateDiagram"],
+
+ ["keyword", "direction"],
+ " LR\r\n ",
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " A\r\n A ",
+ ["arrow", "-->"],
+ " B\r\n B ",
+ ["arrow", "-->"],
+ " C\r\n ",
+
+ ["keyword", "state"],
+ " B ",
+ ["punctuation", "{"],
+
+ ["keyword", "direction"],
+ " LR\r\n a ",
+ ["arrow", "-->"],
+ " b\r\n ",
+
+ ["punctuation", "}"],
+
+ "\r\n B ",
+ ["arrow", "-->"],
+ " D\r\n\r\n",
+
+ ["keyword", "stateDiagram-v2"],
+
+ ["text", "[*]"],
+ ["arrow", "-->"],
+ " Still\r\n Still ",
+ ["arrow", "-->"],
+ ["text", "[*]"],
+
+ ["comment", "%% this is a comment"],
+
+ "\r\n Still ",
+ ["arrow", "-->"],
+ " Moving\r\n Moving ",
+ ["arrow", "-->"],
+ " Still ",
+ ["comment", "%% another comment"],
+
+ "\r\n Moving ",
+ ["arrow", "-->"],
+ " Crash\r\n Crash ",
+ ["arrow", "-->"],
+ ["text", "[*]"]
+]
diff --git a/tests/languages/mermaid/inter-arrow-label_feature.test b/tests/languages/mermaid/inter-arrow-label_feature.test
new file mode 100644
index 0000000000..8c07daf5a3
--- /dev/null
+++ b/tests/languages/mermaid/inter-arrow-label_feature.test
@@ -0,0 +1,62 @@
+A -.s .- C
+A -. s .- C
+A -. "asdasd" .- C
+A -- "asdasd" --> C
+A -- "asdasd" --> C
+A -- "asdasd" .- C
+A -- "asdasd" === C
+A -- "asdasd" ==> C
+
+----------------------------------------------------
+
+[
+ "A ",
+ ["inter-arrow-label", [
+ ["arrow-head", "-."],
+ ["label", "s"],
+ ["arrow", ".-"]
+ ]],
+ " C\r\nA ",
+ ["inter-arrow-label", [
+ ["arrow-head", "-."],
+ ["label", "s"],
+ ["arrow", ".-"]
+ ]],
+ " C\r\nA ",
+ ["inter-arrow-label", [
+ ["arrow-head", "-."],
+ ["label", "\"asdasd\""],
+ ["arrow", ".-"]
+ ]],
+ " C\r\nA ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "\"asdasd\""],
+ ["arrow", "-->"]
+ ]],
+ " C\r\nA ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "\"asdasd\""],
+ ["arrow", "-->"]
+ ]],
+ " C\r\nA ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "\"asdasd\""],
+ ["arrow", ".-"]
+ ]],
+ " C\r\nA ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "\"asdasd\""],
+ ["arrow", "==="]
+ ]],
+ " C\r\nA ",
+ ["inter-arrow-label", [
+ ["arrow-head", "--"],
+ ["label", "\"asdasd\""],
+ ["arrow", "==>"]
+ ]],
+ " C"
+]
diff --git a/tests/languages/mermaid/operator_feature.test b/tests/languages/mermaid/operator_feature.test
new file mode 100644
index 0000000000..7ee9a5fbe6
--- /dev/null
+++ b/tests/languages/mermaid/operator_feature.test
@@ -0,0 +1,11 @@
+A & B
+
+: :::
+
+----------------------------------------------------
+
+[
+ "A ", ["operator", "&"], " B\r\n\r\n",
+
+ ["operator", ":"], ["operator", ":::"]
+]
diff --git a/tests/languages/shell-session/command_string_feature.test b/tests/languages/shell-session/command_string_feature.test
index 854314b8bb..930d0b62ca 100644
--- a/tests/languages/shell-session/command_string_feature.test
+++ b/tests/languages/shell-session/command_string_feature.test
@@ -21,6 +21,9 @@ $ cat << "EOF" > /etc/ipsec.secrets
# : RSA vpn-server-b.key
EOF
+$ LC_ALL=C tr -cd 'a-zA-Z0-9_-;:!?.@\\*/#%$' < /dev/random | head -c 8
+y_#!$U48
+
----------------------------------------------------
[
@@ -64,10 +67,10 @@ EOF
["builtin", "echo"],
["punctuation", "\\"],
"'a ",
- ["comment", "# "]
+ ["comment", "# '"]
]]
]],
- ["output", "'\r\n\r\n"],
+
["command", [
["shell-symbol", "$"],
["bash", [
@@ -83,7 +86,28 @@ EOF
"\r\n: RSA vpn-server-a.key\r\n# : RSA vpn-server-b.key\r\nEOF"
]]
]]
- ]]
+ ]],
+
+ ["command", [
+ ["shell-symbol", "$"],
+ ["bash", [
+ ["assign-left", [
+ ["environment", "LC_ALL"]
+ ]],
+ ["operator", ["="]],
+ "C ",
+ ["function", "tr"],
+ " -cd ",
+ ["string", "'a-zA-Z0-9_-;:!?.@\\\\*/#%$'"],
+ ["operator", ["<"]],
+ " /dev/random ",
+ ["operator", ["|"]],
+ ["function", "head"],
+ " -c ",
+ ["number", "8"]
+ ]]
+ ]],
+ ["output", "y_#!$U48"]
]
----------------------------------------------------
diff --git a/tests/languages/shell-session/issue3047_1.test b/tests/languages/shell-session/issue3047_1.test
new file mode 100644
index 0000000000..ca9eec6be4
--- /dev/null
+++ b/tests/languages/shell-session/issue3047_1.test
@@ -0,0 +1,96 @@
+$ diskutil list
+/dev/disk0 (internal, physical):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: GUID_partition_scheme *500.3 GB disk0
+ 1: EFI EFI 209.7 MB disk0s1
+ 2: Apple_APFS Container disk1 500.1 GB disk0s2
+
+/dev/disk1 (synthesized):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: APFS Container Scheme - +500.1 GB disk1
+ Physical Store disk0s2
+ 1: APFS Volume Macintosh HD - Data 340.9 GB disk1s1
+ 2: APFS Volume Preboot 85.9 MB disk1s2
+ 3: APFS Volume Recovery 529.0 MB disk1s3
+ 4: APFS Volume VM 3.2 GB disk1s4
+ 5: APFS Volume Macintosh HD 11.3 GB disk1s5
+
+/dev/disk2 (internal, physical):
+ #: TYPE NAME SIZE IDENTIFIER
+ 0: FDisk_partition_scheme *15.9 GB disk2
+ 1: Windows_FAT_32 boot 268.4 MB disk2s1
+ 2: Linux 15.7 GB disk2s2
+
+$ sudo diskutil unmount /dev/diskn
+disk2 was already unmounted or it has a partitioning scheme so use "diskutil unmountDisk" instead
+
+$ sudo diskutil unmountDisk /dev/diskn (if previous step fails)
+Unmount of all volumes on disk2 was successful
+
+$ sudo dd bs=1m if=$HOME/Downloads/tails-amd64-4.18.img of=/dev/rdiskn
+1131+0 records in
+1131+0 records out
+1185939456 bytes transferred in 44.708618 secs (26525970 bytes/sec)
+
+$ sudo diskutil unmountDisk /dev/diskn
+Unmount of all volumes on disk2 was successful
+
+----------------------------------------------------
+
+[
+ ["command", [
+ ["shell-symbol", "$"],
+ ["bash", ["diskutil list"]]
+ ]],
+
+ ["output", "/dev/disk0 (internal, physical):\r\n #: TYPE NAME SIZE IDENTIFIER\r\n 0: GUID_partition_scheme *500.3 GB disk0\r\n 1: EFI EFI 209.7 MB disk0s1\r\n 2: Apple_APFS Container disk1 500.1 GB disk0s2\r\n\r\n/dev/disk1 (synthesized):\r\n #: TYPE NAME SIZE IDENTIFIER\r\n 0: APFS Container Scheme - +500.1 GB disk1\r\n Physical Store disk0s2\r\n 1: APFS Volume Macintosh HD - Data 340.9 GB disk1s1\r\n 2: APFS Volume Preboot 85.9 MB disk1s2\r\n 3: APFS Volume Recovery 529.0 MB disk1s3\r\n 4: APFS Volume VM 3.2 GB disk1s4\r\n 5: APFS Volume Macintosh HD 11.3 GB disk1s5\r\n\r\n/dev/disk2 (internal, physical):\r\n #: TYPE NAME SIZE IDENTIFIER\r\n 0: FDisk_partition_scheme *15.9 GB disk2\r\n 1: Windows_FAT_32 boot 268.4 MB disk2s1\r\n 2: Linux 15.7 GB disk2s2\r\n\r\n"],
+ ["command", [
+ ["shell-symbol", "$"],
+ ["bash", [
+ ["function", "sudo"],
+ " diskutil unmount /dev/diskn"
+ ]]
+ ]],
+
+ ["output", "disk2 was already unmounted or it has a partitioning scheme so use \"diskutil unmountDisk\" instead\r\n\r\n"],
+ ["command", [
+ ["shell-symbol", "$"],
+ ["bash", [
+ ["function", "sudo"],
+ " diskutil unmountDisk /dev/diskn ",
+ ["punctuation", "("],
+ "if previous step fails",
+ ["punctuation", ")"]
+ ]]
+ ]],
+
+ ["output", "Unmount of all volumes on disk2 was successful\r\n\r\n"],
+ ["command", [
+ ["shell-symbol", "$"],
+ ["bash", [
+ ["function", "sudo"],
+ ["function", "dd"],
+ ["assign-left", ["bs"]],
+ ["operator", ["="]],
+ "1m ",
+ ["assign-left", ["if"]],
+ ["operator", ["="]],
+ ["environment", "$HOME"],
+ "/Downloads/tails-amd64-4.18.img ",
+ ["assign-left", ["of"]],
+ ["operator", ["="]],
+ "/dev/rdiskn"
+ ]]
+ ]],
+
+ ["output", "1131+0 records in\r\n1131+0 records out\r\n1185939456 bytes transferred in 44.708618 secs (26525970 bytes/sec)\r\n\r\n"],
+ ["command", [
+ ["shell-symbol", "$"],
+ ["bash", [
+ ["function", "sudo"],
+ " diskutil unmountDisk /dev/diskn"
+ ]]
+ ]],
+
+ ["output", "Unmount of all volumes on disk2 was successful"]
+]
diff --git a/tests/languages/shell-session/issue3047_2.test b/tests/languages/shell-session/issue3047_2.test
new file mode 100644
index 0000000000..40e03e67d9
--- /dev/null
+++ b/tests/languages/shell-session/issue3047_2.test
@@ -0,0 +1,43 @@
+$ gpg --card-status
+Reader ...........: Yubico YubiKey CCID
+Application ID ...: D*******************************
+Application type .: OpenPGP
+Version ..........: 0.0
+Manufacturer .....: Yubico
+Serial number ....: 1*******
+Name of cardholder: John Doe
+Language prefs ...: en
+Salutation .......:
+URL of public key : [not set]
+Login data .......: john@example.net
+Signature PIN ....: not forced
+Key attributes ...: ed25519 cv25519 ed25519
+Max. PIN lengths .: 127 127 127
+PIN retry counter : 3 0 3
+Signature counter : 0
+KDF setting ......: off
+UIF setting ......: Sign=on Decrypt=on Auth=on
+Signature key ....: ACE1 3F15 90C1 A8C9 D942 51E3 02ED C61B 6543 509B
+ created ....: 2021-07-21 18:44:34
+Encryption key....: 0524 00F4 8E1D 085A F3E1 61EC D463 4E0D 6E2D D8BF
+ created ....: 2021-07-21 18:44:52
+Authentication key: A27B 582F 1F62 03BA 549B 3D44 1E7B 69B2 38FF A21B
+ created ....: 2021-07-21 18:45:13
+General key info..: sub ed25519/0x02EDC61B6543509B 2021-07-21 John Doe
+sec# ed25519/0xC2709D13BAB4763C created: 2021-07-21 expires: never
+ssb> ed25519/0x02EDC61B6543509B created: 2021-07-21 expires: 2022-07-21
+ card-no: 0006 1*******
+ssb> cv25519/0xD4634E0D6E2DD8BF created: 2021-07-21 expires: 2022-07-21
+ card-no: 0006 1*******
+ssb> ed25519/0x1E7B69B238FFA21B created: 2021-07-21 expires: 2022-07-21
+ card-no: 0006 1*******
+
+----------------------------------------------------
+
+[
+ ["command", [
+ ["shell-symbol", "$"],
+ ["bash", ["gpg --card-status"]]
+ ]],
+ ["output", "Reader ...........: Yubico YubiKey CCID\r\nApplication ID ...: D*******************************\r\nApplication type .: OpenPGP\r\nVersion ..........: 0.0\r\nManufacturer .....: Yubico\r\nSerial number ....: 1*******\r\nName of cardholder: John Doe\r\nLanguage prefs ...: en\r\nSalutation .......:\r\nURL of public key : [not set]\r\nLogin data .......: john@example.net\r\nSignature PIN ....: not forced\r\nKey attributes ...: ed25519 cv25519 ed25519\r\nMax. PIN lengths .: 127 127 127\r\nPIN retry counter : 3 0 3\r\nSignature counter : 0\r\nKDF setting ......: off\r\nUIF setting ......: Sign=on Decrypt=on Auth=on\r\nSignature key ....: ACE1 3F15 90C1 A8C9 D942 51E3 02ED C61B 6543 509B\r\n created ....: 2021-07-21 18:44:34\r\nEncryption key....: 0524 00F4 8E1D 085A F3E1 61EC D463 4E0D 6E2D D8BF\r\n created ....: 2021-07-21 18:44:52\r\nAuthentication key: A27B 582F 1F62 03BA 549B 3D44 1E7B 69B2 38FF A21B\r\n created ....: 2021-07-21 18:45:13\r\nGeneral key info..: sub ed25519/0x02EDC61B6543509B 2021-07-21 John Doe \r\nsec# ed25519/0xC2709D13BAB4763C created: 2021-07-21 expires: never\r\nssb> ed25519/0x02EDC61B6543509B created: 2021-07-21 expires: 2022-07-21\r\n card-no: 0006 1*******\r\nssb> cv25519/0xD4634E0D6E2DD8BF created: 2021-07-21 expires: 2022-07-21\r\n card-no: 0006 1*******\r\nssb> ed25519/0x1E7B69B238FFA21B created: 2021-07-21 expires: 2022-07-21\r\n card-no: 0006 1*******"]
+]
diff --git a/tests/languages/systemd/boolean_feature.test b/tests/languages/systemd/boolean_feature.test
new file mode 100644
index 0000000000..a260308560
--- /dev/null
+++ b/tests/languages/systemd/boolean_feature.test
@@ -0,0 +1,46 @@
+foo=on
+foo=true
+foo=yes
+foo=off
+foo=false
+foo=no
+
+----------------------------------------------------
+
+[
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["boolean", "on"]
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["boolean", "true"]
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["boolean", "yes"]
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["boolean", "off"]
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["boolean", "false"]
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["boolean", "no"]
+ ]]
+]
diff --git a/tests/languages/systemd/comment_feature.test b/tests/languages/systemd/comment_feature.test
new file mode 100644
index 0000000000..d564a17ae1
--- /dev/null
+++ b/tests/languages/systemd/comment_feature.test
@@ -0,0 +1,9 @@
+# comment
+; comment
+
+----------------------------------------------------
+
+[
+ ["comment", "# comment"],
+ ["comment", "; comment"]
+]
diff --git a/tests/languages/systemd/key_feature.test b/tests/languages/systemd/key_feature.test
new file mode 100644
index 0000000000..cf3ffab4d6
--- /dev/null
+++ b/tests/languages/systemd/key_feature.test
@@ -0,0 +1,9 @@
+foo=
+foo =
+
+----------------------------------------------------
+
+[
+ ["key", "foo"], ["operator", "="],
+ ["key", "foo"], ["operator", "="]
+]
diff --git a/tests/languages/systemd/section_feature.test b/tests/languages/systemd/section_feature.test
new file mode 100644
index 0000000000..9c6a00b59b
--- /dev/null
+++ b/tests/languages/systemd/section_feature.test
@@ -0,0 +1,11 @@
+[Section Foo]
+
+----------------------------------------------------
+
+[
+ ["section", [
+ ["punctuation", "["],
+ ["section-name", "Section Foo"],
+ ["punctuation", "]"]
+ ]]
+]
diff --git a/tests/languages/systemd/value_feature.test b/tests/languages/systemd/value_feature.test
new file mode 100644
index 0000000000..acdac052b1
--- /dev/null
+++ b/tests/languages/systemd/value_feature.test
@@ -0,0 +1,49 @@
+foo= value 2
+
+foo="something" "some thing" "…"
+foo= "something" "some thing" "…"
+foo=value 2 \
+ value 2 continued
+
+foo=value 3\
+# this line is ignored
+; this line is ignored too
+ value 3 continued
+
+----------------------------------------------------
+
+[
+ ["key", "foo"], ["operator", "="], ["value", ["value 2"]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["quoted", "\"something\""],
+ ["quoted", "\"some thing\""],
+ ["quoted", "\"…\""]
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ ["quoted", "\"something\""],
+ ["quoted", "\"some thing\""],
+ ["quoted", "\"…\""]
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ "value 2 ", ["punctuation", "\\"],
+ "\r\n value 2 continued"
+ ]],
+
+ ["key", "foo"],
+ ["operator", "="],
+ ["value", [
+ "value 3", ["punctuation", "\\"],
+ ["comment", "# this line is ignored"],
+ ["comment", "; this line is ignored too"],
+ "\r\n value 3 continued"
+ ]]
+]