powershell.js
1 /*! `powershell` grammar compiled for Highlight.js 11.10.0 */ 2 (function(){ 3 var hljsGrammar = (function () { 4 'use strict'; 5 6 /* 7 Language: PowerShell 8 Description: PowerShell is a task-based command-line shell and scripting language built on .NET. 9 Author: David Mohundro <david@mohundro.com> 10 Contributors: Nicholas Blumhardt <nblumhardt@nblumhardt.com>, Victor Zhou <OiCMudkips@users.noreply.github.com>, Nicolas Le Gall <contact@nlegall.fr> 11 Website: https://docs.microsoft.com/en-us/powershell/ 12 Category: scripting 13 */ 14 15 function powershell(hljs) { 16 const TYPES = [ 17 "string", 18 "char", 19 "byte", 20 "int", 21 "long", 22 "bool", 23 "decimal", 24 "single", 25 "double", 26 "DateTime", 27 "xml", 28 "array", 29 "hashtable", 30 "void" 31 ]; 32 33 // https://docs.microsoft.com/en-us/powershell/scripting/developer/cmdlet/approved-verbs-for-windows-powershell-commands 34 const VALID_VERBS = 35 'Add|Clear|Close|Copy|Enter|Exit|Find|Format|Get|Hide|Join|Lock|' 36 + 'Move|New|Open|Optimize|Pop|Push|Redo|Remove|Rename|Reset|Resize|' 37 + 'Search|Select|Set|Show|Skip|Split|Step|Switch|Undo|Unlock|' 38 + 'Watch|Backup|Checkpoint|Compare|Compress|Convert|ConvertFrom|' 39 + 'ConvertTo|Dismount|Edit|Expand|Export|Group|Import|Initialize|' 40 + 'Limit|Merge|Mount|Out|Publish|Restore|Save|Sync|Unpublish|Update|' 41 + 'Approve|Assert|Build|Complete|Confirm|Deny|Deploy|Disable|Enable|Install|Invoke|' 42 + 'Register|Request|Restart|Resume|Start|Stop|Submit|Suspend|Uninstall|' 43 + 'Unregister|Wait|Debug|Measure|Ping|Repair|Resolve|Test|Trace|Connect|' 44 + 'Disconnect|Read|Receive|Send|Write|Block|Grant|Protect|Revoke|Unblock|' 45 + 'Unprotect|Use|ForEach|Sort|Tee|Where'; 46 47 const COMPARISON_OPERATORS = 48 '-and|-as|-band|-bnot|-bor|-bxor|-casesensitive|-ccontains|-ceq|-cge|-cgt|' 49 + '-cle|-clike|-clt|-cmatch|-cne|-cnotcontains|-cnotlike|-cnotmatch|-contains|' 50 + '-creplace|-csplit|-eq|-exact|-f|-file|-ge|-gt|-icontains|-ieq|-ige|-igt|' 51 + '-ile|-ilike|-ilt|-imatch|-in|-ine|-inotcontains|-inotlike|-inotmatch|' 52 + '-ireplace|-is|-isnot|-isplit|-join|-le|-like|-lt|-match|-ne|-not|' 53 + '-notcontains|-notin|-notlike|-notmatch|-or|-regex|-replace|-shl|-shr|' 54 + '-split|-wildcard|-xor'; 55 56 const KEYWORDS = { 57 $pattern: /-?[A-z\.\-]+\b/, 58 keyword: 59 'if else foreach return do while until elseif begin for trap data dynamicparam ' 60 + 'end break throw param continue finally in switch exit filter try process catch ' 61 + 'hidden static parameter', 62 // "echo" relevance has been set to 0 to avoid auto-detect conflicts with shell transcripts 63 built_in: 64 'ac asnp cat cd CFS chdir clc clear clhy cli clp cls clv cnsn compare copy cp ' 65 + 'cpi cpp curl cvpa dbp del diff dir dnsn ebp echo|0 epal epcsv epsn erase etsn exsn fc fhx ' 66 + 'fl ft fw gal gbp gc gcb gci gcm gcs gdr gerr ghy gi gin gjb gl gm gmo gp gps gpv group ' 67 + 'gsn gsnp gsv gtz gu gv gwmi h history icm iex ihy ii ipal ipcsv ipmo ipsn irm ise iwmi ' 68 + 'iwr kill lp ls man md measure mi mount move mp mv nal ndr ni nmo npssc nsn nv ogv oh ' 69 + 'popd ps pushd pwd r rbp rcjb rcsn rd rdr ren ri rjb rm rmdir rmo rni rnp rp rsn rsnp ' 70 + 'rujb rv rvpa rwmi sajb sal saps sasv sbp sc scb select set shcm si sl sleep sls sort sp ' 71 + 'spjb spps spsv start stz sujb sv swmi tee trcm type wget where wjb write' 72 // TODO: 'validate[A-Z]+' can't work in keywords 73 }; 74 75 const TITLE_NAME_RE = /\w[\w\d]*((-)[\w\d]+)*/; 76 77 const BACKTICK_ESCAPE = { 78 begin: '`[\\s\\S]', 79 relevance: 0 80 }; 81 82 const VAR = { 83 className: 'variable', 84 variants: [ 85 { begin: /\$\B/ }, 86 { 87 className: 'keyword', 88 begin: /\$this/ 89 }, 90 { begin: /\$[\w\d][\w\d_:]*/ } 91 ] 92 }; 93 94 const LITERAL = { 95 className: 'literal', 96 begin: /\$(null|true|false)\b/ 97 }; 98 99 const QUOTE_STRING = { 100 className: "string", 101 variants: [ 102 { 103 begin: /"/, 104 end: /"/ 105 }, 106 { 107 begin: /@"/, 108 end: /^"@/ 109 } 110 ], 111 contains: [ 112 BACKTICK_ESCAPE, 113 VAR, 114 { 115 className: 'variable', 116 begin: /\$[A-z]/, 117 end: /[^A-z]/ 118 } 119 ] 120 }; 121 122 const APOS_STRING = { 123 className: 'string', 124 variants: [ 125 { 126 begin: /'/, 127 end: /'/ 128 }, 129 { 130 begin: /@'/, 131 end: /^'@/ 132 } 133 ] 134 }; 135 136 const PS_HELPTAGS = { 137 className: "doctag", 138 variants: [ 139 /* no paramater help tags */ 140 { begin: /\.(synopsis|description|example|inputs|outputs|notes|link|component|role|functionality)/ }, 141 /* one parameter help tags */ 142 { begin: /\.(parameter|forwardhelptargetname|forwardhelpcategory|remotehelprunspace|externalhelp)\s+\S+/ } 143 ] 144 }; 145 146 const PS_COMMENT = hljs.inherit( 147 hljs.COMMENT(null, null), 148 { 149 variants: [ 150 /* single-line comment */ 151 { 152 begin: /#/, 153 end: /$/ 154 }, 155 /* multi-line comment */ 156 { 157 begin: /<#/, 158 end: /#>/ 159 } 160 ], 161 contains: [ PS_HELPTAGS ] 162 } 163 ); 164 165 const CMDLETS = { 166 className: 'built_in', 167 variants: [ { begin: '('.concat(VALID_VERBS, ')+(-)[\\w\\d]+') } ] 168 }; 169 170 const PS_CLASS = { 171 className: 'class', 172 beginKeywords: 'class enum', 173 end: /\s*[{]/, 174 excludeEnd: true, 175 relevance: 0, 176 contains: [ hljs.TITLE_MODE ] 177 }; 178 179 const PS_FUNCTION = { 180 className: 'function', 181 begin: /function\s+/, 182 end: /\s*\{|$/, 183 excludeEnd: true, 184 returnBegin: true, 185 relevance: 0, 186 contains: [ 187 { 188 begin: "function", 189 relevance: 0, 190 className: "keyword" 191 }, 192 { 193 className: "title", 194 begin: TITLE_NAME_RE, 195 relevance: 0 196 }, 197 { 198 begin: /\(/, 199 end: /\)/, 200 className: "params", 201 relevance: 0, 202 contains: [ VAR ] 203 } 204 // CMDLETS 205 ] 206 }; 207 208 // Using statment, plus type, plus assembly name. 209 const PS_USING = { 210 begin: /using\s/, 211 end: /$/, 212 returnBegin: true, 213 contains: [ 214 QUOTE_STRING, 215 APOS_STRING, 216 { 217 className: 'keyword', 218 begin: /(using|assembly|command|module|namespace|type)/ 219 } 220 ] 221 }; 222 223 // Comperison operators & function named parameters. 224 const PS_ARGUMENTS = { variants: [ 225 // PS literals are pretty verbose so it's a good idea to accent them a bit. 226 { 227 className: 'operator', 228 begin: '('.concat(COMPARISON_OPERATORS, ')\\b') 229 }, 230 { 231 className: 'literal', 232 begin: /(-){1,2}[\w\d-]+/, 233 relevance: 0 234 } 235 ] }; 236 237 const HASH_SIGNS = { 238 className: 'selector-tag', 239 begin: /@\B/, 240 relevance: 0 241 }; 242 243 // It's a very general rule so I'll narrow it a bit with some strict boundaries 244 // to avoid any possible false-positive collisions! 245 const PS_METHODS = { 246 className: 'function', 247 begin: /\[.*\]\s*[\w]+[ ]??\(/, 248 end: /$/, 249 returnBegin: true, 250 relevance: 0, 251 contains: [ 252 { 253 className: 'keyword', 254 begin: '('.concat( 255 KEYWORDS.keyword.toString().replace(/\s/g, '|' 256 ), ')\\b'), 257 endsParent: true, 258 relevance: 0 259 }, 260 hljs.inherit(hljs.TITLE_MODE, { endsParent: true }) 261 ] 262 }; 263 264 const GENTLEMANS_SET = [ 265 // STATIC_MEMBER, 266 PS_METHODS, 267 PS_COMMENT, 268 BACKTICK_ESCAPE, 269 hljs.NUMBER_MODE, 270 QUOTE_STRING, 271 APOS_STRING, 272 // PS_NEW_OBJECT_TYPE, 273 CMDLETS, 274 VAR, 275 LITERAL, 276 HASH_SIGNS 277 ]; 278 279 const PS_TYPE = { 280 begin: /\[/, 281 end: /\]/, 282 excludeBegin: true, 283 excludeEnd: true, 284 relevance: 0, 285 contains: [].concat( 286 'self', 287 GENTLEMANS_SET, 288 { 289 begin: "(" + TYPES.join("|") + ")", 290 className: "built_in", 291 relevance: 0 292 }, 293 { 294 className: 'type', 295 begin: /[\.\w\d]+/, 296 relevance: 0 297 } 298 ) 299 }; 300 301 PS_METHODS.contains.unshift(PS_TYPE); 302 303 return { 304 name: 'PowerShell', 305 aliases: [ 306 "pwsh", 307 "ps", 308 "ps1" 309 ], 310 case_insensitive: true, 311 keywords: KEYWORDS, 312 contains: GENTLEMANS_SET.concat( 313 PS_CLASS, 314 PS_FUNCTION, 315 PS_USING, 316 PS_ARGUMENTS, 317 PS_TYPE 318 ) 319 }; 320 } 321 322 return powershell; 323 324 })(); 325 326 hljs.registerLanguage('powershell', hljsGrammar); 327 })();