UNPKG

prism-react-renderer

Version:

Renders highlighted Prism output using React

1,427 lines (1,280 loc) 109 kB
/** * Prism: Lightweight, robust, elegant syntax highlighting * MIT license http://www.opensource.org/licenses/mit-license.php/ * @author Lea Verou http://lea.verou.me */ /** * prism-react-renderer: * This file has been modified to remove: * - globals and window dependency * - worker support * - highlightAll and other element dependent methods * - _.hooks helpers * - UMD/node-specific hacks * It has also been run through prettier */ var Prism = function () { var uniqueId = 0; var _ = { util: { encode: function (tokens) { if (tokens instanceof Token) { return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias); } else if (_.util.type(tokens) === "Array") { return tokens.map(_.util.encode); } else { return tokens.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/\u00a0/g, " "); } }, type: function (o) { return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1]; }, objId: function (obj) { if (!obj["__id"]) { Object.defineProperty(obj, "__id", { value: ++uniqueId }); } return obj["__id"]; }, // Deep clone a language definition (e.g. to extend it) clone: function (o, visited) { var type = _.util.type(o); visited = visited || {}; switch (type) { case "Object": if (visited[_.util.objId(o)]) { return visited[_.util.objId(o)]; } var clone = {}; visited[_.util.objId(o)] = clone; for (var key in o) { if (o.hasOwnProperty(key)) { clone[key] = _.util.clone(o[key], visited); } } return clone; case "Array": if (visited[_.util.objId(o)]) { return visited[_.util.objId(o)]; } var clone = []; visited[_.util.objId(o)] = clone; o.forEach(function (v, i) { clone[i] = _.util.clone(v, visited); }); return clone; } return o; } }, languages: { extend: function (id, redef) { var lang = _.util.clone(_.languages[id]); for (var key in redef) { lang[key] = redef[key]; } return lang; }, /** * Insert a token before another token in a language literal * As this needs to recreate the object (we cannot actually insert before keys in object literals), * we cannot just provide an object, we need anobject and a key. * @param inside The key (or language id) of the parent * @param before The key to insert before. If not provided, the function appends instead. * @param insert Object with the key/value pairs to insert * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted. */ insertBefore: function (inside, before, insert, root) { root = root || _.languages; var grammar = root[inside]; if (arguments.length == 2) { insert = arguments[1]; for (var newToken in insert) { if (insert.hasOwnProperty(newToken)) { grammar[newToken] = insert[newToken]; } } return grammar; } var ret = {}; for (var token in grammar) { if (grammar.hasOwnProperty(token)) { if (token == before) { for (var newToken in insert) { if (insert.hasOwnProperty(newToken)) { ret[newToken] = insert[newToken]; } } } ret[token] = grammar[token]; } } // Update references in other language definitions _.languages.DFS(_.languages, function (key, value) { if (value === root[inside] && key != inside) { this[key] = ret; } }); return root[inside] = ret; }, // Traverse a language definition with Depth First Search DFS: function (o, callback, type, visited) { visited = visited || {}; for (var i in o) { if (o.hasOwnProperty(i)) { callback.call(o, i, o[i], type || i); if (_.util.type(o[i]) === "Object" && !visited[_.util.objId(o[i])]) { visited[_.util.objId(o[i])] = true; _.languages.DFS(o[i], callback, null, visited); } else if (_.util.type(o[i]) === "Array" && !visited[_.util.objId(o[i])]) { visited[_.util.objId(o[i])] = true; _.languages.DFS(o[i], callback, i, visited); } } } } }, plugins: {}, highlight: function (text, grammar, language) { var env = { code: text, grammar: grammar, language: language }; env.tokens = _.tokenize(env.code, env.grammar); return Token.stringify(_.util.encode(env.tokens), env.language); }, matchGrammar: function (text, strarr, grammar, index, startPos, oneshot, target) { var Token = _.Token; for (var token in grammar) { if (!grammar.hasOwnProperty(token) || !grammar[token]) { continue; } if (token == target) { return; } var patterns = grammar[token]; patterns = _.util.type(patterns) === "Array" ? patterns : [patterns]; for (var j = 0; j < patterns.length; ++j) { var pattern = patterns[j], inside = pattern.inside, lookbehind = !!pattern.lookbehind, greedy = !!pattern.greedy, lookbehindLength = 0, alias = pattern.alias; if (greedy && !pattern.pattern.global) { // Without the global flag, lastIndex won't work var flags = pattern.pattern.toString().match(/[imuy]*$/)[0]; pattern.pattern = RegExp(pattern.pattern.source, flags + "g"); } pattern = pattern.pattern || pattern; // Don’t cache length as it changes during the loop for (var i = index, pos = startPos; i < strarr.length; pos += strarr[i].length, ++i) { var str = strarr[i]; if (strarr.length > text.length) { // Something went terribly wrong, ABORT, ABORT! return; } if (str instanceof Token) { continue; } if (greedy && i != strarr.length - 1) { pattern.lastIndex = pos; var match = pattern.exec(text); if (!match) { break; } var from = match.index + (lookbehind ? match[1].length : 0), to = match.index + match[0].length, k = i, p = pos; for (var len = strarr.length; k < len && (p < to || !strarr[k].type && !strarr[k - 1].greedy); ++k) { p += strarr[k].length; // Move the index i to the element in strarr that is closest to from if (from >= p) { ++i; pos = p; } } // If strarr[i] is a Token, then the match starts inside another Token, which is invalid if (strarr[i] instanceof Token) { continue; } // Number of tokens to delete and replace with the new match delNum = k - i; str = text.slice(pos, p); match.index -= pos; } else { pattern.lastIndex = 0; var match = pattern.exec(str), delNum = 1; } if (!match) { if (oneshot) { break; } continue; } if (lookbehind) { lookbehindLength = match[1] ? match[1].length : 0; } var from = match.index + lookbehindLength, match = match[0].slice(lookbehindLength), to = from + match.length, before = str.slice(0, from), after = str.slice(to); var args = [i, delNum]; if (before) { ++i; pos += before.length; args.push(before); } var wrapped = new Token(token, inside ? _.tokenize(match, inside) : match, alias, match, greedy); args.push(wrapped); if (after) { args.push(after); } Array.prototype.splice.apply(strarr, args); if (delNum != 1) { _.matchGrammar(text, strarr, grammar, i, pos, true, token); } if (oneshot) { break; } } } } }, hooks: { add: function () {} }, tokenize: function (text, grammar, language) { var strarr = [text]; var rest = grammar.rest; if (rest) { for (var token in rest) { grammar[token] = rest[token]; } delete grammar.rest; } _.matchGrammar(text, strarr, grammar, 0, 0, false); return strarr; } }; var Token = _.Token = function (type, content, alias, matchedStr, greedy) { this.type = type; this.content = content; this.alias = alias; // Copy of the full string this token was created from this.length = (matchedStr || "").length | 0; this.greedy = !!greedy; }; Token.stringify = function (o, language, parent) { if (typeof o == "string") { return o; } if (_.util.type(o) === "Array") { return o.map(function (element) { return Token.stringify(element, language, o); }).join(""); } var env = { type: o.type, content: Token.stringify(o.content, language, parent), tag: "span", classes: ["token", o.type], attributes: {}, language: language, parent: parent }; if (o.alias) { var aliases = _.util.type(o.alias) === "Array" ? o.alias : [o.alias]; Array.prototype.push.apply(env.classes, aliases); } var attributes = Object.keys(env.attributes).map(function (name) { return name + '="' + (env.attributes[name] || "").replace(/"/g, "&quot;") + '"'; }).join(" "); return "<" + env.tag + ' class="' + env.classes.join(" ") + '"' + (attributes ? " " + attributes : "") + ">" + env.content + "</" + env.tag + ">"; }; return _; }(); /* This content is auto-generated to include some prismjs language components: */ /* "prismjs/components/prism-markup" */ Prism.languages.markup = { 'comment': /<!--[\s\S]*?-->/, 'prolog': /<\?[\s\S]+?\?>/, 'doctype': /<!DOCTYPE[\s\S]+?>/i, 'cdata': /<!\[CDATA\[[\s\S]*?]]>/i, 'tag': { pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/i, greedy: true, inside: { 'tag': { pattern: /^<\/?[^\s>\/]+/i, inside: { 'punctuation': /^<\/?/, 'namespace': /^[^\s>\/:]+:/ } }, 'attr-value': { pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/i, inside: { 'punctuation': [/^=/, { pattern: /^(\s*)["']|["']$/, lookbehind: true }] } }, 'punctuation': /\/?>/, 'attr-name': { pattern: /[^\s>\/]+/, inside: { 'namespace': /^[^\s>\/:]+:/ } } } }, 'entity': /&#?[\da-z]{1,8};/i }; Prism.languages.markup['tag'].inside['attr-value'].inside['entity'] = Prism.languages.markup['entity']; // Plugin to make entity title show the real entity, idea by Roman Komarov Prism.hooks.add('wrap', function (env) { if (env.type === 'entity') { env.attributes['title'] = env.content.replace(/&amp;/, '&'); } }); Object.defineProperty(Prism.languages.markup.tag, 'addInlined', { /** * Adds an inlined language to markup. * * An example of an inlined language is CSS with `<style>` tags. * * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as * case insensitive. * @param {string} lang The language key. * @example * addInlined('style', 'css'); */ value: function addInlined(tagName, lang) { var includedCdataInside = {}; includedCdataInside['language-' + lang] = { pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i, lookbehind: true, inside: Prism.languages[lang] }; includedCdataInside['cdata'] = /^<!\[CDATA\[|\]\]>$/i; var inside = { 'included-cdata': { pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i, inside: includedCdataInside } }; inside['language-' + lang] = { pattern: /[\s\S]+/, inside: Prism.languages[lang] }; var def = {}; def[tagName] = { pattern: RegExp(/(<__[\s\S]*?>)(?:<!\[CDATA\[[\s\S]*?\]\]>\s*|[\s\S])*?(?=<\/__>)/.source.replace(/__/g, tagName), 'i'), lookbehind: true, greedy: true, inside: inside }; Prism.languages.insertBefore('markup', 'cdata', def); } }); Prism.languages.xml = Prism.languages.extend('markup', {}); Prism.languages.html = Prism.languages.markup; Prism.languages.mathml = Prism.languages.markup; Prism.languages.svg = Prism.languages.markup; /* "prismjs/components/prism-bash" */ (function (Prism) { // $ set | grep '^[A-Z][^[:space:]]*=' | cut -d= -f1 | tr '\n' '|' // + LC_ALL, RANDOM, REPLY, SECONDS. // + make sure PS1..4 are here as they are not always set, // - some useless things. var envVars = '\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b'; var insideString = { 'environment': { pattern: RegExp("\\$" + envVars), alias: 'constant' }, 'variable': [// [0]: Arithmetic Environment { pattern: /\$?\(\([\s\S]+?\)\)/, greedy: true, inside: { // If there is a $ sign at the beginning highlight $(( and )) as variable 'variable': [{ pattern: /(^\$\(\([\s\S]+)\)\)/, lookbehind: true }, /^\$\(\(/], 'number': /\b0x[\dA-Fa-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:[Ee]-?\d+)?/, // Operators according to https://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic 'operator': /--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/, // If there is no $ sign at the beginning highlight (( and )) as punctuation 'punctuation': /\(\(?|\)\)?|,|;/ } }, // [1]: Command Substitution { pattern: /\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/, greedy: true, inside: { 'variable': /^\$\(|^`|\)$|`$/ } }, // [2]: Brace expansion { pattern: /\$\{[^}]+\}/, greedy: true, inside: { 'operator': /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/, 'punctuation': /[\[\]]/, 'environment': { pattern: RegExp("(\\{)" + envVars), lookbehind: true, alias: 'constant' } } }, /\$(?:\w+|[#?*!@$])/], // Escape sequences from echo and printf's manuals, and escaped quotes. 'entity': /\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/ }; Prism.languages.bash = { 'shebang': { pattern: /^#!\s*\/.*/, alias: 'important' }, 'comment': { pattern: /(^|[^"{\\$])#.*/, lookbehind: true }, 'function-name': [// a) function foo { // b) foo() { // c) function foo() { // but not “foo {” { // a) and c) pattern: /(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/, lookbehind: true, alias: 'function' }, { // b) pattern: /\b\w+(?=\s*\(\s*\)\s*\{)/, alias: 'function' }], // Highlight variable names as variables in for and select beginnings. 'for-or-select': { pattern: /(\b(?:for|select)\s+)\w+(?=\s+in\s)/, alias: 'variable', lookbehind: true }, // Highlight variable names as variables in the left-hand part // of assignments (“=” and “+=”). 'assign-left': { pattern: /(^|[\s;|&]|[<>]\()\w+(?=\+?=)/, inside: { 'environment': { pattern: RegExp("(^|[\\s;|&]|[<>]\\()" + envVars), lookbehind: true, alias: 'constant' } }, alias: 'variable', lookbehind: true }, 'string': [// Support for Here-documents https://en.wikipedia.org/wiki/Here_document { pattern: /((?:^|[^<])<<-?\s*)(\w+?)\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\2/, lookbehind: true, greedy: true, inside: insideString }, // Here-document with quotes around the tag // → No expansion (so no “inside”). { pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s*(?:\r?\n|\r)(?:[\s\S])*?(?:\r?\n|\r)\3/, lookbehind: true, greedy: true }, // “Normal” string { pattern: /(["'])(?:\\[\s\S]|\$\([^)]+\)|`[^`]+`|(?!\1)[^\\])*\1/, greedy: true, inside: insideString }], 'environment': { pattern: RegExp("\\$?" + envVars), alias: 'constant' }, 'variable': insideString.variable, 'function': { pattern: /(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/, lookbehind: true }, 'keyword': { pattern: /(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/, lookbehind: true }, // https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html 'builtin': { pattern: /(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/, lookbehind: true, // Alias added to make those easier to distinguish from strings. alias: 'class-name' }, 'boolean': { pattern: /(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/, lookbehind: true }, 'file-descriptor': { pattern: /\B&\d\b/, alias: 'important' }, 'operator': { // Lots of redirections here, but not just that. pattern: /\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/, inside: { 'file-descriptor': { pattern: /^\d/, alias: 'important' } } }, 'punctuation': /\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/, 'number': { pattern: /(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/, lookbehind: true } }; /* Patterns in command substitution. */ var toBeCopied = ['comment', 'function-name', 'for-or-select', 'assign-left', 'string', 'environment', 'function', 'keyword', 'builtin', 'boolean', 'file-descriptor', 'operator', 'punctuation', 'number']; var inside = insideString.variable[1].inside; for (var i = 0; i < toBeCopied.length; i++) { inside[toBeCopied[i]] = Prism.languages.bash[toBeCopied[i]]; } Prism.languages.shell = Prism.languages.bash; })(Prism); /* "prismjs/components/prism-clike" */ Prism.languages.clike = { 'comment': [{ pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/, lookbehind: true }, { pattern: /(^|[^\\:])\/\/.*/, lookbehind: true, greedy: true }], 'string': { pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, greedy: true }, 'class-name': { pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i, lookbehind: true, inside: { punctuation: /[.\\]/ } }, 'keyword': /\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/, 'boolean': /\b(?:true|false)\b/, 'function': /\w+(?=\()/, 'number': /\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i, 'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/, 'punctuation': /[{}[\];(),.:]/ }; /* "prismjs/components/prism-c" */ Prism.languages.c = Prism.languages.extend('clike', { 'class-name': { pattern: /(\b(?:enum|struct)\s+)\w+/, lookbehind: true }, 'keyword': /\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/, 'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/, 'number': /(?:\b0x(?:[\da-f]+\.?[\da-f]*|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i }); Prism.languages.insertBefore('c', 'string', { 'macro': { // allow for multiline macro definitions // spaces after the # character compile fine with gcc pattern: /(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im, lookbehind: true, alias: 'property', inside: { // highlight the path of the include statement as a string 'string': { pattern: /(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/, lookbehind: true }, // highlight macro directives as keywords 'directive': { pattern: /(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/, lookbehind: true, alias: 'keyword' } } }, // highlight predefined macros as constants 'constant': /\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/ }); delete Prism.languages.c['boolean']; /* "prismjs/components/prism-cpp" */ Prism.languages.cpp = Prism.languages.extend('c', { 'class-name': { pattern: /(\b(?:class|enum|struct)\s+)\w+/, lookbehind: true }, 'keyword': /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/, 'number': { pattern: /(?:\b0b[01']+|\b0x(?:[\da-f']+\.?[\da-f']*|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+\.?[\d']*|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]*/i, greedy: true }, 'operator': />>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/, 'boolean': /\b(?:true|false)\b/ }); Prism.languages.insertBefore('cpp', 'string', { 'raw-string': { pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/, alias: 'string', greedy: true } }); /* "prismjs/components/prism-css" */ (function (Prism) { var string = /("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/; Prism.languages.css = { 'comment': /\/\*[\s\S]*?\*\//, 'atrule': { pattern: /@[\w-]+[\s\S]*?(?:;|(?=\s*\{))/, inside: { 'rule': /@[\w-]+/ // See rest below } }, 'url': { pattern: RegExp('url\\((?:' + string.source + '|[^\n\r()]*)\\)', 'i'), inside: { 'function': /^url/i, 'punctuation': /^\(|\)$/ } }, 'selector': RegExp('[^{}\\s](?:[^{};"\']|' + string.source + ')*?(?=\\s*\\{)'), 'string': { pattern: string, greedy: true }, 'property': /[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i, 'important': /!important\b/i, 'function': /[-a-z0-9]+(?=\()/i, 'punctuation': /[(){};:,]/ }; Prism.languages.css['atrule'].inside.rest = Prism.languages.css; var markup = Prism.languages.markup; if (markup) { markup.tag.addInlined('style', 'css'); Prism.languages.insertBefore('inside', 'attr-value', { 'style-attr': { pattern: /\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i, inside: { 'attr-name': { pattern: /^\s*style/i, inside: markup.tag.inside }, 'punctuation': /^\s*=\s*['"]|['"]\s*$/, 'attr-value': { pattern: /.+/i, inside: Prism.languages.css } }, alias: 'language-css' } }, markup.tag); } })(Prism); /* "prismjs/components/prism-css-extras" */ Prism.languages.css.selector = { pattern: Prism.languages.css.selector, inside: { 'pseudo-element': /:(?:after|before|first-letter|first-line|selection)|::[-\w]+/, 'pseudo-class': /:[-\w]+/, 'class': /\.[-:.\w]+/, 'id': /#[-:.\w]+/, 'attribute': { pattern: /\[(?:[^[\]"']|("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1)*\]/, greedy: true, inside: { 'punctuation': /^\[|\]$/, 'case-sensitivity': { pattern: /(\s)[si]$/i, lookbehind: true, alias: 'keyword' }, 'namespace': { pattern: /^(\s*)[-*\w\xA0-\uFFFF]*\|(?!=)/, lookbehind: true, inside: { 'punctuation': /\|$/ } }, 'attribute': { pattern: /^(\s*)[-\w\xA0-\uFFFF]+/, lookbehind: true }, 'value': [/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/, { pattern: /(=\s*)[-\w\xA0-\uFFFF]+(?=\s*$)/, lookbehind: true }], 'operator': /[|~*^$]?=/ } }, 'n-th': [{ pattern: /(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/, lookbehind: true, inside: { 'number': /[\dn]+/, 'operator': /[+-]/ } }, { pattern: /(\(\s*)(?:even|odd)(?=\s*\))/i, lookbehind: true }], 'punctuation': /[()]/ } }; Prism.languages.insertBefore('css', 'property', { 'variable': { pattern: /(^|[^-\w\xA0-\uFFFF])--[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*/i, lookbehind: true } }); Prism.languages.insertBefore('css', 'function', { 'operator': { pattern: /(\s)[+\-*\/](?=\s)/, lookbehind: true }, 'hexcode': /#[\da-f]{3,8}/i, 'entity': /\\[\da-f]{1,8}/i, 'unit': { pattern: /(\d)(?:%|[a-z]+)/, lookbehind: true }, 'number': /-?[\d.]+/ }); /* "prismjs/components/prism-javascript" */ Prism.languages.javascript = Prism.languages.extend('clike', { 'class-name': [Prism.languages.clike['class-name'], { pattern: /(^|[^$\w\xA0-\uFFFF])[_$A-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\.(?:prototype|constructor))/, lookbehind: true }], 'keyword': [{ pattern: /((?:^|})\s*)(?:catch|finally)\b/, lookbehind: true }, { pattern: /(^|[^.])\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/, lookbehind: true }], 'number': /\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/, // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444) 'function': /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/, 'operator': /-[-=]?|\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/ }); Prism.languages.javascript['class-name'][0].pattern = /(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/; Prism.languages.insertBefore('javascript', 'keyword', { 'regex': { pattern: /((?:^|[^$\w\xA0-\uFFFF."'\])\s])\s*)\/(\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=\s*($|[\r\n,.;})\]]))/, lookbehind: true, greedy: true }, // This must be declared before keyword because we use "function" inside the look-forward 'function-variable': { pattern: /#?[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|[_$a-zA-Z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)\s*=>))/, alias: 'function' }, 'parameter': [{ pattern: /(function(?:\s+[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*)?\s*\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\))/, lookbehind: true, inside: Prism.languages.javascript }, { pattern: /[_$a-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*(?=\s*=>)/i, inside: Prism.languages.javascript }, { pattern: /(\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*=>)/, lookbehind: true, inside: Prism.languages.javascript }, { pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:[_$A-Za-z\xA0-\uFFFF][$\w\xA0-\uFFFF]*\s*)\(\s*)(?!\s)(?:[^()]|\([^()]*\))+?(?=\s*\)\s*\{)/, lookbehind: true, inside: Prism.languages.javascript }], 'constant': /\b[A-Z](?:[A-Z_]|\dx?)*\b/ }); Prism.languages.insertBefore('javascript', 'string', { 'template-string': { pattern: /`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/, greedy: true, inside: { 'template-punctuation': { pattern: /^`|`$/, alias: 'string' }, 'interpolation': { pattern: /((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/, lookbehind: true, inside: { 'interpolation-punctuation': { pattern: /^\${|}$/, alias: 'punctuation' }, rest: Prism.languages.javascript } }, 'string': /[\s\S]+/ } } }); if (Prism.languages.markup) { Prism.languages.markup.tag.addInlined('script', 'javascript'); } Prism.languages.js = Prism.languages.javascript; /* "prismjs/components/prism-jsx" */ (function (Prism) { var javascript = Prism.util.clone(Prism.languages.javascript); Prism.languages.jsx = Prism.languages.extend('markup', javascript); Prism.languages.jsx.tag.pattern = /<\/?(?:[\w.:-]+\s*(?:\s+(?:[\w.:-]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s{'">=]+|\{(?:\{(?:\{[^}]*\}|[^{}])*\}|[^{}])+\}))?|\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}))*\s*\/?)?>/i; Prism.languages.jsx.tag.inside['tag'].pattern = /^<\/?[^\s>\/]*/i; Prism.languages.jsx.tag.inside['attr-value'].pattern = /=(?!\{)(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">]+)/i; Prism.languages.jsx.tag.inside['tag'].inside['class-name'] = /^[A-Z]\w*(?:\.[A-Z]\w*)*$/; Prism.languages.insertBefore('inside', 'attr-name', { 'spread': { pattern: /\{\.{3}[a-z_$][\w$]*(?:\.[a-z_$][\w$]*)*\}/, inside: { 'punctuation': /\.{3}|[{}.]/, 'attr-value': /\w+/ } } }, Prism.languages.jsx.tag); Prism.languages.insertBefore('inside', 'attr-value', { 'script': { // Allow for two levels of nesting pattern: /=(\{(?:\{(?:\{[^}]*\}|[^}])*\}|[^}])+\})/i, inside: { 'script-punctuation': { pattern: /^=(?={)/, alias: 'punctuation' }, rest: Prism.languages.jsx }, 'alias': 'language-javascript' } }, Prism.languages.jsx.tag); // The following will handle plain text inside tags var stringifyToken = function (token) { if (!token) { return ''; } if (typeof token === 'string') { return token; } if (typeof token.content === 'string') { return token.content; } return token.content.map(stringifyToken).join(''); }; var walkTokens = function (tokens) { var openedTags = []; for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; var notTagNorBrace = false; if (typeof token !== 'string') { if (token.type === 'tag' && token.content[0] && token.content[0].type === 'tag') { // We found a tag, now find its kind if (token.content[0].content[0].content === '</') { // Closing tag if (openedTags.length > 0 && openedTags[openedTags.length - 1].tagName === stringifyToken(token.content[0].content[1])) { // Pop matching opening tag openedTags.pop(); } } else { if (token.content[token.content.length - 1].content === '/>') ; else { // Opening tag openedTags.push({ tagName: stringifyToken(token.content[0].content[1]), openedBraces: 0 }); } } } else if (openedTags.length > 0 && token.type === 'punctuation' && token.content === '{') { // Here we might have entered a JSX context inside a tag openedTags[openedTags.length - 1].openedBraces++; } else if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces > 0 && token.type === 'punctuation' && token.content === '}') { // Here we might have left a JSX context inside a tag openedTags[openedTags.length - 1].openedBraces--; } else { notTagNorBrace = true; } } if (notTagNorBrace || typeof token === 'string') { if (openedTags.length > 0 && openedTags[openedTags.length - 1].openedBraces === 0) { // Here we are inside a tag, and not inside a JSX context. // That's plain text: drop any tokens matched. var plainText = stringifyToken(token); // And merge text with adjacent text if (i < tokens.length - 1 && (typeof tokens[i + 1] === 'string' || tokens[i + 1].type === 'plain-text')) { plainText += stringifyToken(tokens[i + 1]); tokens.splice(i + 1, 1); } if (i > 0 && (typeof tokens[i - 1] === 'string' || tokens[i - 1].type === 'plain-text')) { plainText = stringifyToken(tokens[i - 1]) + plainText; tokens.splice(i - 1, 1); i--; } tokens[i] = new Prism.Token('plain-text', plainText, null, plainText); } } if (token.content && typeof token.content !== 'string') { walkTokens(token.content); } } }; Prism.hooks.add('after-tokenize', function (env) { if (env.language !== 'jsx' && env.language !== 'tsx') { return; } walkTokens(env.tokens); }); })(Prism); /* "prismjs/components/prism-javadoclike" */ (function (Prism) { var javaDocLike = Prism.languages.javadoclike = { 'parameter': { pattern: /(^\s*(?:\/{3}|\*|\/\*\*)\s*@(?:param|arg|arguments)\s+)\w+/m, lookbehind: true }, 'keyword': { // keywords are the first word in a line preceded be an `@` or surrounded by curly braces. // @word, {@word} pattern: /(^\s*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m, lookbehind: true }, 'punctuation': /[{}]/ }; /** * Adds doc comment support to the given language and calls a given callback on each doc comment pattern. * * @param {string} lang the language add doc comment support to. * @param {(pattern: {inside: {rest: undefined}}) => void} callback the function called with each doc comment pattern as argument. */ function docCommentSupport(lang, callback) { var tokenName = 'doc-comment'; var grammar = Prism.languages[lang]; if (!grammar) { return; } var token = grammar[tokenName]; if (!token) { // add doc comment: /** */ var definition = {}; definition[tokenName] = { pattern: /(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/, alias: 'comment' }; grammar = Prism.languages.insertBefore(lang, 'comment', definition); token = grammar[tokenName]; } if (token instanceof RegExp) { // convert regex to object token = grammar[tokenName] = { pattern: token }; } if (Array.isArray(token)) { for (var i = 0, l = token.length; i < l; i++) { if (token[i] instanceof RegExp) { token[i] = { pattern: token[i] }; } callback(token[i]); } } else { callback(token); } } /** * Adds doc-comment support to the given languages for the given documentation language. * * @param {string[]|string} languages * @param {Object} docLanguage */ function addSupport(languages, docLanguage) { if (typeof languages === 'string') { languages = [languages]; } languages.forEach(function (lang) { docCommentSupport(lang, function (pattern) { if (!pattern.inside) { pattern.inside = {}; } pattern.inside.rest = docLanguage; }); }); } Object.defineProperty(javaDocLike, 'addSupport', { value: addSupport }); javaDocLike.addSupport(['java', 'javascript', 'php'], javaDocLike); })(Prism); /* "prismjs/components/prism-java" */ (function (Prism) { var keywords = /\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while|var|null|exports|module|open|opens|provides|requires|to|transitive|uses|with)\b/; // based on the java naming conventions var className = /\b[A-Z](?:\w*[a-z]\w*)?\b/; Prism.languages.java = Prism.languages.extend('clike', { 'class-name': [className, // variables and parameters // this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods) /\b[A-Z]\w*(?=\s+\w+\s*[;,=())])/], 'keyword': keywords, 'function': [Prism.languages.clike.function, { pattern: /(\:\:)[a-z_]\w*/, lookbehind: true }], 'number': /\b0b[01][01_]*L?\b|\b0x[\da-f_]*\.?[\da-f_p+-]+\b|(?:\b\d[\d_]*\.?[\d_]*|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i, 'operator': { pattern: /(^|[^.])(?:<<=?|>>>?=?|->|([-+&|])\2|[?:~]|[-+*/%&|^!=<>]=?)/m, lookbehind: true } }); Prism.languages.insertBefore('java', 'class-name', { 'annotation': { alias: 'punctuation', pattern: /(^|[^.])@\w+/, lookbehind: true }, 'namespace': { pattern: /(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)[a-z]\w*(\.[a-z]\w*)+/, lookbehind: true, inside: { 'punctuation': /\./ } }, 'generics': { pattern: /<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/, inside: { 'class-name': className, 'keyword': keywords, 'punctuation': /[<>(),.:]/, 'operator': /[?&|]/ } } }); })(Prism); /* "prismjs/components/prism-markup-templating" */ (function (Prism) { /** * Returns the placeholder for the given language id and index. * * @param {string} language * @param {string|number} index * @returns {string} */ function getPlaceholder(language, index) { return '___' + language.toUpperCase() + index + '___'; } Object.defineProperties(Prism.languages['markup-templating'] = {}, { buildPlaceholders: { /** * Tokenize all inline templating expressions matching `placeholderPattern`. * * If `replaceFilter` is provided, only matches of `placeholderPattern` for which `replaceFilter` returns * `true` will be replaced. * * @param {object} env The environment of the `before-tokenize` hook. * @param {string} language The language id. * @param {RegExp} placeholderPattern The matches of this pattern will be replaced by placeholders. * @param {(match: string) => boolean} [replaceFilter] */ value: function (env, language, placeholderPattern, replaceFilter) { if (env.language !== language) { return; } var tokenStack = env.tokenStack = []; env.code = env.code.replace(placeholderPattern, function (match) { if (typeof replaceFilter === 'function' && !replaceFilter(match)) { return match; } var i = tokenStack.length; var placeholder; // Check for existing strings while (env.code.indexOf(placeholder = getPlaceholder(language, i)) !== -1) { ++i; } // Create a sparse array tokenStack[i] = match; return placeholder; }); // Switch the grammar to markup env.grammar = Prism.languages.markup; } }, tokenizePlaceholders: { /** * Replace placeholders with proper tokens after tokenizing. * * @param {object} env The environment of the `after-tokenize` hook. * @param {string} language The language id. */ value: function (env, language) { if (env.language !== language || !env.tokenStack) { return; } // Switch the grammar back env.grammar = Prism.languages[language]; var j = 0; var keys = Object.keys(env.tokenStack); function walkTokens(tokens) { for (var i = 0; i < tokens.length; i++) { // all placeholders are replaced already if (j >= keys.length) { break; } var token = tokens[i]; if (typeof token === 'string' || token.content && typeof token.content === 'string') { var k = keys[j]; var t = env.tokenStack[k]; var s = typeof token === 'string' ? token : token.content; var placeholder = getPlaceholder(language, k); var index = s.indexOf(placeholder); if (index > -1) { ++j; var before = s.substring(0, index); var middle = new Prism.Token(language, Prism.tokenize(t, env.grammar), 'language-' + language, t); var after = s.substring(index + placeholder.length); var replacement = []; if (before) { replacement.push.apply(replacement, walkTokens([before])); } replacement.push(middle); if (after) { replacement.push.apply(replacement, walkTokens([after])); } if (typeof token === 'string') { tokens.splice.apply(tokens, [i, 1].concat(replacement)); } else { token.content = replacement; } } } else if (token.content /* && typeof token.content !== 'string' */ ) { walkTokens(token.content); } } return tokens; } walkTokens(env.tokens); } } }); })(Prism); /* "prismjs/components/prism-php" */ /** * Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/ * Modified by Miles Johnson: http://milesj.me * * Supports the following: * - Extends clike syntax * - Support for PHP 5.3+ (namespaces, traits, generators, etc) * - Smarter constant and function matching * * Adds the following new token classes: * constant, delimiter, variable, function, package */ (function (Prism) { Prism.languages.php = Prism.languages.extend('clike', { 'keyword': /\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|new|or|parent|print|private|protected|public|require|require_once|return|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i, 'boolean': { pattern: /\b(?:false|true)\b/i, alias: 'constant' }, 'constant': [/\b[A-Z_][A-Z0-9_]*\b/, /\b(?:null)\b/i], 'comment': { pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/, lookbehind: true } }); Prism.languages.insertBefore('php', 'string', { 'shell-comment': { pattern: /(^|[^\\])#.*/, lookbehind: true, alias: 'comment' } }); Prism.languages.insertBefore('php', 'comment', { 'delimiter': { pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i, alias: 'important' } }); Prism.languages.insertBefore('php', 'keyword', { 'variable': /\$+(?:\w+\b|(?={))/i, 'package': { pattern: /(\\|namespace\s+|use\s+)[\w\\]+/, lookbehind: true, inside: { punctuation: /\\/ } } }); // Must be defined after the function pattern Prism.languages.insertBefore('php', 'operator', { 'property': { pattern: /(->)[\w]+/, lookbehind: true } }); var string_interpolation = { pattern: /{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[.+?]|->\w+)*)/, lookbehind: true, inside: { rest: Prism.languages.php } }; Prism.languages.insertBefore('php', 'string', { 'nowdoc-string': { pattern: /<<<'([^']+)'(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;/, greedy: true, alias: 'string', inside: { 'delimiter': { pattern: /^<<<'[^']+'|[a-z_]\w*;$/i, alias: 'symbol', inside: { 'punctuation': /^<<<'?|[';]$/ } } } }, 'heredoc-string': { pattern: /<<<(?:"([^"]+)"(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\1;|([a-z_]\w*)(?:\r\n?|\n)(?:.*(?:\r\n?|\n))*?\2;)/i, greedy: true, alias: 'string', inside: { 'delimiter': { pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i, alias: 'symbol', inside: { 'punctuation': /^<<<"?|[";]$/ } }, 'interpolation': string_interpolation // See below } }, 'single-quoted-string': { pattern: /'(?:\\[\s\S]|[^\\'])*'/, greedy: true, alias: 'string' }, 'double-quoted-string': { pattern: /"(?:\\[\s\S]|[^\\"])*"/, greedy: true, alias: 'string', inside: { 'interpolation': string_interpolation // See below } } }); // The different types of PHP strings "replace" the C-like standard string delete Prism.languages.php['string']; Prism.hooks.add('before-tokenize', function (env) { if (!/<\?/.test(env.code)) { return; } var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#)(?:[^?\n\r]|\?(?!>))*|\/\*[\s\S]*?(?:\*\/|$))*?(?:\?>|$)/ig; Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern); }); Prism.hooks.add('after-tokenize', function (env) { Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php'); }); })(Prism); /* "prismjs/components/pr