latex.js
1 /*! `latex` grammar compiled for Highlight.js 11.10.0 */ 2 (function(){ 3 var hljsGrammar = (function () { 4 'use strict'; 5 6 /* 7 Language: LaTeX 8 Author: Benedikt Wilde <bwilde@posteo.de> 9 Website: https://www.latex-project.org 10 Category: markup 11 */ 12 13 /** @type LanguageFn */ 14 function latex(hljs) { 15 const regex = hljs.regex; 16 const KNOWN_CONTROL_WORDS = regex.either(...[ 17 '(?:NeedsTeXFormat|RequirePackage|GetIdInfo)', 18 'Provides(?:Expl)?(?:Package|Class|File)', 19 '(?:DeclareOption|ProcessOptions)', 20 '(?:documentclass|usepackage|input|include)', 21 'makeat(?:letter|other)', 22 'ExplSyntax(?:On|Off)', 23 '(?:new|renew|provide)?command', 24 '(?:re)newenvironment', 25 '(?:New|Renew|Provide|Declare)(?:Expandable)?DocumentCommand', 26 '(?:New|Renew|Provide|Declare)DocumentEnvironment', 27 '(?:(?:e|g|x)?def|let)', 28 '(?:begin|end)', 29 '(?:part|chapter|(?:sub){0,2}section|(?:sub)?paragraph)', 30 'caption', 31 '(?:label|(?:eq|page|name)?ref|(?:paren|foot|super)?cite)', 32 '(?:alpha|beta|[Gg]amma|[Dd]elta|(?:var)?epsilon|zeta|eta|[Tt]heta|vartheta)', 33 '(?:iota|(?:var)?kappa|[Ll]ambda|mu|nu|[Xx]i|[Pp]i|varpi|(?:var)rho)', 34 '(?:[Ss]igma|varsigma|tau|[Uu]psilon|[Pp]hi|varphi|chi|[Pp]si|[Oo]mega)', 35 '(?:frac|sum|prod|lim|infty|times|sqrt|leq|geq|left|right|middle|[bB]igg?)', 36 '(?:[lr]angle|q?quad|[lcvdi]?dots|d?dot|hat|tilde|bar)' 37 ].map(word => word + '(?![a-zA-Z@:_])')); 38 const L3_REGEX = new RegExp([ 39 // A function \module_function_name:signature or \__module_function_name:signature, 40 // where both module and function_name need at least two characters and 41 // function_name may contain single underscores. 42 '(?:__)?[a-zA-Z]{2,}_[a-zA-Z](?:_?[a-zA-Z])+:[a-zA-Z]*', 43 // A variable \scope_module_and_name_type or \scope__module_ane_name_type, 44 // where scope is one of l, g or c, type needs at least two characters 45 // and module_and_name may contain single underscores. 46 '[lgc]__?[a-zA-Z](?:_?[a-zA-Z])*_[a-zA-Z]{2,}', 47 // A quark \q_the_name or \q__the_name or 48 // scan mark \s_the_name or \s__vthe_name, 49 // where variable_name needs at least two characters and 50 // may contain single underscores. 51 '[qs]__?[a-zA-Z](?:_?[a-zA-Z])+', 52 // Other LaTeX3 macro names that are not covered by the three rules above. 53 'use(?:_i)?:[a-zA-Z]*', 54 '(?:else|fi|or):', 55 '(?:if|cs|exp):w', 56 '(?:hbox|vbox):n', 57 '::[a-zA-Z]_unbraced', 58 '::[a-zA-Z:]' 59 ].map(pattern => pattern + '(?![a-zA-Z:_])').join('|')); 60 const L2_VARIANTS = [ 61 { begin: /[a-zA-Z@]+/ }, // control word 62 { begin: /[^a-zA-Z@]?/ } // control symbol 63 ]; 64 const DOUBLE_CARET_VARIANTS = [ 65 { begin: /\^{6}[0-9a-f]{6}/ }, 66 { begin: /\^{5}[0-9a-f]{5}/ }, 67 { begin: /\^{4}[0-9a-f]{4}/ }, 68 { begin: /\^{3}[0-9a-f]{3}/ }, 69 { begin: /\^{2}[0-9a-f]{2}/ }, 70 { begin: /\^{2}[\u0000-\u007f]/ } 71 ]; 72 const CONTROL_SEQUENCE = { 73 className: 'keyword', 74 begin: /\\/, 75 relevance: 0, 76 contains: [ 77 { 78 endsParent: true, 79 begin: KNOWN_CONTROL_WORDS 80 }, 81 { 82 endsParent: true, 83 begin: L3_REGEX 84 }, 85 { 86 endsParent: true, 87 variants: DOUBLE_CARET_VARIANTS 88 }, 89 { 90 endsParent: true, 91 relevance: 0, 92 variants: L2_VARIANTS 93 } 94 ] 95 }; 96 const MACRO_PARAM = { 97 className: 'params', 98 relevance: 0, 99 begin: /#+\d?/ 100 }; 101 const DOUBLE_CARET_CHAR = { 102 // relevance: 1 103 variants: DOUBLE_CARET_VARIANTS }; 104 const SPECIAL_CATCODE = { 105 className: 'built_in', 106 relevance: 0, 107 begin: /[$&^_]/ 108 }; 109 const MAGIC_COMMENT = { 110 className: 'meta', 111 begin: /% ?!(T[eE]X|tex|BIB|bib)/, 112 end: '$', 113 relevance: 10 114 }; 115 const COMMENT = hljs.COMMENT( 116 '%', 117 '$', 118 { relevance: 0 } 119 ); 120 const EVERYTHING_BUT_VERBATIM = [ 121 CONTROL_SEQUENCE, 122 MACRO_PARAM, 123 DOUBLE_CARET_CHAR, 124 SPECIAL_CATCODE, 125 MAGIC_COMMENT, 126 COMMENT 127 ]; 128 const BRACE_GROUP_NO_VERBATIM = { 129 begin: /\{/, 130 end: /\}/, 131 relevance: 0, 132 contains: [ 133 'self', 134 ...EVERYTHING_BUT_VERBATIM 135 ] 136 }; 137 const ARGUMENT_BRACES = hljs.inherit( 138 BRACE_GROUP_NO_VERBATIM, 139 { 140 relevance: 0, 141 endsParent: true, 142 contains: [ 143 BRACE_GROUP_NO_VERBATIM, 144 ...EVERYTHING_BUT_VERBATIM 145 ] 146 } 147 ); 148 const ARGUMENT_BRACKETS = { 149 begin: /\[/, 150 end: /\]/, 151 endsParent: true, 152 relevance: 0, 153 contains: [ 154 BRACE_GROUP_NO_VERBATIM, 155 ...EVERYTHING_BUT_VERBATIM 156 ] 157 }; 158 const SPACE_GOBBLER = { 159 begin: /\s+/, 160 relevance: 0 161 }; 162 const ARGUMENT_M = [ ARGUMENT_BRACES ]; 163 const ARGUMENT_O = [ ARGUMENT_BRACKETS ]; 164 const ARGUMENT_AND_THEN = function(arg, starts_mode) { 165 return { 166 contains: [ SPACE_GOBBLER ], 167 starts: { 168 relevance: 0, 169 contains: arg, 170 starts: starts_mode 171 } 172 }; 173 }; 174 const CSNAME = function(csname, starts_mode) { 175 return { 176 begin: '\\\\' + csname + '(?![a-zA-Z@:_])', 177 keywords: { 178 $pattern: /\\[a-zA-Z]+/, 179 keyword: '\\' + csname 180 }, 181 relevance: 0, 182 contains: [ SPACE_GOBBLER ], 183 starts: starts_mode 184 }; 185 }; 186 const BEGIN_ENV = function(envname, starts_mode) { 187 return hljs.inherit( 188 { 189 begin: '\\\\begin(?=[ \t]*(\\r?\\n[ \t]*)?\\{' + envname + '\\})', 190 keywords: { 191 $pattern: /\\[a-zA-Z]+/, 192 keyword: '\\begin' 193 }, 194 relevance: 0, 195 }, 196 ARGUMENT_AND_THEN(ARGUMENT_M, starts_mode) 197 ); 198 }; 199 const VERBATIM_DELIMITED_EQUAL = (innerName = "string") => { 200 return hljs.END_SAME_AS_BEGIN({ 201 className: innerName, 202 begin: /(.|\r?\n)/, 203 end: /(.|\r?\n)/, 204 excludeBegin: true, 205 excludeEnd: true, 206 endsParent: true 207 }); 208 }; 209 const VERBATIM_DELIMITED_ENV = function(envname) { 210 return { 211 className: 'string', 212 end: '(?=\\\\end\\{' + envname + '\\})' 213 }; 214 }; 215 216 const VERBATIM_DELIMITED_BRACES = (innerName = "string") => { 217 return { 218 relevance: 0, 219 begin: /\{/, 220 starts: { 221 endsParent: true, 222 contains: [ 223 { 224 className: innerName, 225 end: /(?=\})/, 226 endsParent: true, 227 contains: [ 228 { 229 begin: /\{/, 230 end: /\}/, 231 relevance: 0, 232 contains: [ "self" ] 233 } 234 ], 235 } 236 ] 237 } 238 }; 239 }; 240 const VERBATIM = [ 241 ...[ 242 'verb', 243 'lstinline' 244 ].map(csname => CSNAME(csname, { contains: [ VERBATIM_DELIMITED_EQUAL() ] })), 245 CSNAME('mint', ARGUMENT_AND_THEN(ARGUMENT_M, { contains: [ VERBATIM_DELIMITED_EQUAL() ] })), 246 CSNAME('mintinline', ARGUMENT_AND_THEN(ARGUMENT_M, { contains: [ 247 VERBATIM_DELIMITED_BRACES(), 248 VERBATIM_DELIMITED_EQUAL() 249 ] })), 250 CSNAME('url', { contains: [ 251 VERBATIM_DELIMITED_BRACES("link"), 252 VERBATIM_DELIMITED_BRACES("link") 253 ] }), 254 CSNAME('hyperref', { contains: [ VERBATIM_DELIMITED_BRACES("link") ] }), 255 CSNAME('href', ARGUMENT_AND_THEN(ARGUMENT_O, { contains: [ VERBATIM_DELIMITED_BRACES("link") ] })), 256 ...[].concat(...[ 257 '', 258 '\\*' 259 ].map(suffix => [ 260 BEGIN_ENV('verbatim' + suffix, VERBATIM_DELIMITED_ENV('verbatim' + suffix)), 261 BEGIN_ENV('filecontents' + suffix, ARGUMENT_AND_THEN(ARGUMENT_M, VERBATIM_DELIMITED_ENV('filecontents' + suffix))), 262 ...[ 263 '', 264 'B', 265 'L' 266 ].map(prefix => 267 BEGIN_ENV(prefix + 'Verbatim' + suffix, ARGUMENT_AND_THEN(ARGUMENT_O, VERBATIM_DELIMITED_ENV(prefix + 'Verbatim' + suffix))) 268 ) 269 ])), 270 BEGIN_ENV('minted', ARGUMENT_AND_THEN(ARGUMENT_O, ARGUMENT_AND_THEN(ARGUMENT_M, VERBATIM_DELIMITED_ENV('minted')))), 271 ]; 272 273 return { 274 name: 'LaTeX', 275 aliases: [ 'tex' ], 276 contains: [ 277 ...VERBATIM, 278 ...EVERYTHING_BUT_VERBATIM 279 ] 280 }; 281 } 282 283 return latex; 284 285 })(); 286 287 hljs.registerLanguage('latex', hljsGrammar); 288 })();