diff --git a/cloudlab-manual.scrbl b/cloudlab-manual.scrbl index b9cdc0e4ebf7a29f8baa0d127d44fcf282859d4e..5023975306975d0c3561da6a6f0d5e8faddaf375 100644 --- a/cloudlab-manual.scrbl +++ b/cloudlab-manual.scrbl @@ -2,7 +2,7 @@ @(require racket/date) @(require "defs.rkt") -@title[#:version apt-version +@title[#:version apt-version #:style main-style #:date (date->string (current-date))]{The CloudLab Manual} @author[ diff --git a/defs.rkt b/defs.rkt index e6fe99949eb05ddf829b6d17448d709a003bbb29..4ac39bc70603b932017a899cd0874224d7fcb87e 100644 --- a/defs.rkt +++ b/defs.rkt @@ -3,6 +3,7 @@ (require scribble/core) (require scribble/decode) (require scribble/manual) +(require scribble/private/defaults) (require scribble/html-properties) (require scribble/latex-properties) (require racket/class) @@ -14,6 +15,11 @@ (provide (all-defined-out)) +(define main-style + (make-style "main" + (list (js-style-addition "highlight.pack.js") + (make-css-addition "highlight-default.css")))) + ; Check to see if we are building Apt or CloudLab documentation (define tb-mode (if (vector-member "clab" (current-command-line-arguments)) diff --git a/geni-lib.scrbl b/geni-lib.scrbl index c7343bfd6198d77dab5dbbff0c41c1751bcb0026..f683cd66b5f52a8d840bdd0f194ccac25cfef7fb 100644 --- a/geni-lib.scrbl +++ b/geni-lib.scrbl @@ -2,7 +2,7 @@ @(require "defs.rkt") -@title[#:tag "geni-lib" #:version apt-version]{Describing a profile with python and @tt{geni-lib}} +@title[#:tag "geni-lib" #:style main-style #:version apt-version]{Describing a profile with python and @tt{geni-lib}} @tt{geni-lib} is a tool that allows users to generate @seclink["rspecs"]{RSpec} files from Python code. @(tb) offers the ability to use @tt{geni-lib} diff --git a/highlight-default.css b/highlight-default.css new file mode 100644 index 0000000000000000000000000000000000000000..b0ac8b8aac9b37ecc5e0c0ab9157bdb73a9e5d4c --- /dev/null +++ b/highlight-default.css @@ -0,0 +1,155 @@ +/* + +Original style from softwaremaniacs.org (c) Ivan Sagalaev + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: #f0f0f0; + -webkit-text-size-adjust: none; +} + +.hljs, +.hljs-subst, +.hljs-tag .hljs-title, +.nginx .hljs-title { + color: black; +} + +.hljs-string, +.hljs-title, +.hljs-constant, +.hljs-parent, +.hljs-tag .hljs-value, +.hljs-rule .hljs-value, +.hljs-preprocessor, +.hljs-pragma, +.hljs-name, +.haml .hljs-symbol, +.ruby .hljs-symbol, +.ruby .hljs-symbol .hljs-string, +.hljs-template_tag, +.django .hljs-variable, +.smalltalk .hljs-class, +.hljs-addition, +.hljs-flow, +.hljs-stream, +.bash .hljs-variable, +.pf .hljs-variable, +.apache .hljs-tag, +.apache .hljs-cbracket, +.tex .hljs-command, +.tex .hljs-special, +.erlang_repl .hljs-function_or_atom, +.asciidoc .hljs-header, +.markdown .hljs-header, +.coffeescript .hljs-attribute, +.tp .hljs-variable { + color: #800; +} + +.smartquote, +.hljs-comment, +.hljs-annotation, +.diff .hljs-header, +.hljs-chunk, +.asciidoc .hljs-blockquote, +.markdown .hljs-blockquote { + color: #888; +} + +.hljs-number, +.hljs-date, +.hljs-regexp, +.hljs-literal, +.hljs-hexcolor, +.smalltalk .hljs-symbol, +.smalltalk .hljs-char, +.go .hljs-constant, +.hljs-change, +.lasso .hljs-variable, +.makefile .hljs-variable, +.asciidoc .hljs-bullet, +.markdown .hljs-bullet, +.asciidoc .hljs-link_url, +.markdown .hljs-link_url { + color: #080; +} + +.hljs-label, +.ruby .hljs-string, +.hljs-decorator, +.hljs-filter .hljs-argument, +.hljs-localvars, +.hljs-array, +.hljs-attr_selector, +.hljs-important, +.hljs-pseudo, +.hljs-pi, +.haml .hljs-bullet, +.hljs-doctype, +.hljs-deletion, +.hljs-envvar, +.hljs-shebang, +.apache .hljs-sqbracket, +.nginx .hljs-built_in, +.tex .hljs-formula, +.erlang_repl .hljs-reserved, +.hljs-prompt, +.asciidoc .hljs-link_label, +.markdown .hljs-link_label, +.vhdl .hljs-attribute, +.clojure .hljs-attribute, +.asciidoc .hljs-attribute, +.lasso .hljs-attribute, +.coffeescript .hljs-property, +.hljs-phony { + color: #88f; +} + +.hljs-keyword, +.hljs-id, +.hljs-title, +.hljs-built_in, +.css .hljs-tag, +.hljs-doctag, +.smalltalk .hljs-class, +.hljs-winutils, +.bash .hljs-variable, +.pf .hljs-variable, +.apache .hljs-tag, +.hljs-type, +.hljs-typename, +.tex .hljs-command, +.asciidoc .hljs-strong, +.markdown .hljs-strong, +.hljs-request, +.hljs-status, +.tp .hljs-data, +.tp .hljs-io { + font-weight: bold; +} + +.asciidoc .hljs-emphasis, +.markdown .hljs-emphasis, +.tp .hljs-units { + font-style: italic; +} + +.nginx .hljs-built_in { + font-weight: normal; +} + +.coffeescript .javascript, +.javascript .xml, +.lasso .markup, +.tex .hljs-formula, +.xml .javascript, +.xml .vbscript, +.xml .css, +.xml .hljs-cdata { + opacity: 0.5; +} diff --git a/highlight.pack.js b/highlight.pack.js new file mode 100644 index 0000000000000000000000000000000000000000..2565ce6040423eb79657a25a49a01f6f2d821e8d --- /dev/null +++ b/highlight.pack.js @@ -0,0 +1,854 @@ +/*! highlight.js v8.9.1 | BSD3 License | git.io/hljslicense */ +(function(factory) { + + // Setup highlight.js for different environments. First is Node.js or + // CommonJS. + if(typeof exports !== 'undefined') { + factory(exports); + } else { + // Export hljs globally even when using AMD for cases when this script + // is loaded with others that may still expect a global hljs. + window.hljs = factory({}); + + // Finally register the global hljs with AMD. + if(typeof define === 'function' && define.amd) { + define('hljs', [], function() { + return window.hljs; + }); + } + } + +}(function(hljs) { + + /* Utility functions */ + + function escape(value) { + return value.replace(/&/gm, '&').replace(//gm, '>'); + } + + function tag(node) { + return node.nodeName.toLowerCase(); + } + + function testRe(re, lexeme) { + var match = re && re.exec(lexeme); + return match && match.index == 0; + } + + function isNotHighlighted(language) { + return (/^(no-?highlight|plain|text)$/i).test(language); + } + + function blockLanguage(block) { + var i, match, length, + classes = block.className + ' '; + + classes += block.parentNode ? block.parentNode.className : ''; + + // language-* takes precedence over non-prefixed class names + match = (/\blang(?:uage)?-([\w-]+)\b/i).exec(classes); + if (match) { + return getLanguage(match[1]) ? match[1] : 'no-highlight'; + } + + classes = classes.split(/\s+/); + for (i = 0, length = classes.length; i < length; i++) { + if (getLanguage(classes[i]) || isNotHighlighted(classes[i])) { + return classes[i]; + } + } + } + + function inherit(parent, obj) { + var result = {}, key; + for (key in parent) + result[key] = parent[key]; + if (obj) + for (key in obj) + result[key] = obj[key]; + return result; + } + + /* Stream merging */ + + function nodeStream(node) { + var result = []; + (function _nodeStream(node, offset) { + for (var child = node.firstChild; child; child = child.nextSibling) { + if (child.nodeType == 3) + offset += child.nodeValue.length; + else if (child.nodeType == 1) { + result.push({ + event: 'start', + offset: offset, + node: child + }); + offset = _nodeStream(child, offset); + // Prevent void elements from having an end tag that would actually + // double them in the output. There are more void elements in HTML + // but we list only those realistically expected in code display. + if (!tag(child).match(/br|hr|img|input/)) { + result.push({ + event: 'stop', + offset: offset, + node: child + }); + } + } + } + return offset; + })(node, 0); + return result; + } + + function mergeStreams(original, highlighted, value) { + var processed = 0; + var result = ''; + var nodeStack = []; + + function selectStream() { + if (!original.length || !highlighted.length) { + return original.length ? original : highlighted; + } + if (original[0].offset != highlighted[0].offset) { + return (original[0].offset < highlighted[0].offset) ? original : highlighted; + } + + /* + To avoid starting the stream just before it should stop the order is + ensured that original always starts first and closes last: + + if (event1 == 'start' && event2 == 'start') + return original; + if (event1 == 'start' && event2 == 'stop') + return highlighted; + if (event1 == 'stop' && event2 == 'start') + return original; + if (event1 == 'stop' && event2 == 'stop') + return highlighted; + + ... which is collapsed to: + */ + return highlighted[0].event == 'start' ? original : highlighted; + } + + function open(node) { + function attr_str(a) {return ' ' + a.nodeName + '="' + escape(a.value) + '"';} + result += '<' + tag(node) + Array.prototype.map.call(node.attributes, attr_str).join('') + '>'; + } + + function close(node) { + result += ''; + } + + function render(event) { + (event.event == 'start' ? open : close)(event.node); + } + + while (original.length || highlighted.length) { + var stream = selectStream(); + result += escape(value.substr(processed, stream[0].offset - processed)); + processed = stream[0].offset; + if (stream == original) { + /* + On any opening or closing tag of the original markup we first close + the entire highlighted node stack, then render the original tag along + with all the following original tags at the same offset and then + reopen all the tags on the highlighted stack. + */ + nodeStack.reverse().forEach(close); + do { + render(stream.splice(0, 1)[0]); + stream = selectStream(); + } while (stream == original && stream.length && stream[0].offset == processed); + nodeStack.reverse().forEach(open); + } else { + if (stream[0].event == 'start') { + nodeStack.push(stream[0].node); + } else { + nodeStack.pop(); + } + render(stream.splice(0, 1)[0]); + } + } + return result + escape(value.substr(processed)); + } + + /* Initialization */ + + function compileLanguage(language) { + + function reStr(re) { + return (re && re.source) || re; + } + + function langRe(value, global) { + return new RegExp( + reStr(value), + 'm' + (language.case_insensitive ? 'i' : '') + (global ? 'g' : '') + ); + } + + function compileMode(mode, parent) { + if (mode.compiled) + return; + mode.compiled = true; + + mode.keywords = mode.keywords || mode.beginKeywords; + if (mode.keywords) { + var compiled_keywords = {}; + + var flatten = function(className, str) { + if (language.case_insensitive) { + str = str.toLowerCase(); + } + str.split(' ').forEach(function(kw) { + var pair = kw.split('|'); + compiled_keywords[pair[0]] = [className, pair[1] ? Number(pair[1]) : 1]; + }); + }; + + if (typeof mode.keywords == 'string') { // string + flatten('keyword', mode.keywords); + } else { + Object.keys(mode.keywords).forEach(function (className) { + flatten(className, mode.keywords[className]); + }); + } + mode.keywords = compiled_keywords; + } + mode.lexemesRe = langRe(mode.lexemes || /\b\w+\b/, true); + + if (parent) { + if (mode.beginKeywords) { + mode.begin = '\\b(' + mode.beginKeywords.split(' ').join('|') + ')\\b'; + } + if (!mode.begin) + mode.begin = /\B|\b/; + mode.beginRe = langRe(mode.begin); + if (!mode.end && !mode.endsWithParent) + mode.end = /\B|\b/; + if (mode.end) + mode.endRe = langRe(mode.end); + mode.terminator_end = reStr(mode.end) || ''; + if (mode.endsWithParent && parent.terminator_end) + mode.terminator_end += (mode.end ? '|' : '') + parent.terminator_end; + } + if (mode.illegal) + mode.illegalRe = langRe(mode.illegal); + if (mode.relevance === undefined) + mode.relevance = 1; + if (!mode.contains) { + mode.contains = []; + } + var expanded_contains = []; + mode.contains.forEach(function(c) { + if (c.variants) { + c.variants.forEach(function(v) {expanded_contains.push(inherit(c, v));}); + } else { + expanded_contains.push(c == 'self' ? mode : c); + } + }); + mode.contains = expanded_contains; + mode.contains.forEach(function(c) {compileMode(c, mode);}); + + if (mode.starts) { + compileMode(mode.starts, parent); + } + + var terminators = + mode.contains.map(function(c) { + return c.beginKeywords ? '\\.?(' + c.begin + ')\\.?' : c.begin; + }) + .concat([mode.terminator_end, mode.illegal]) + .map(reStr) + .filter(Boolean); + mode.terminators = terminators.length ? langRe(terminators.join('|'), true) : {exec: function(/*s*/) {return null;}}; + } + + compileMode(language); + } + + /* + Core highlighting function. Accepts a language name, or an alias, and a + string with the code to highlight. Returns an object with the following + properties: + + - relevance (int) + - value (an HTML string with highlighting markup) + + */ + function highlight(name, value, ignore_illegals, continuation) { + + function subMode(lexeme, mode) { + for (var i = 0; i < mode.contains.length; i++) { + if (testRe(mode.contains[i].beginRe, lexeme)) { + return mode.contains[i]; + } + } + } + + function endOfMode(mode, lexeme) { + if (testRe(mode.endRe, lexeme)) { + while (mode.endsParent && mode.parent) { + mode = mode.parent; + } + return mode; + } + if (mode.endsWithParent) { + return endOfMode(mode.parent, lexeme); + } + } + + function isIllegal(lexeme, mode) { + return !ignore_illegals && testRe(mode.illegalRe, lexeme); + } + + function keywordMatch(mode, match) { + var match_str = language.case_insensitive ? match[0].toLowerCase() : match[0]; + return mode.keywords.hasOwnProperty(match_str) && mode.keywords[match_str]; + } + + function buildSpan(classname, insideSpan, leaveOpen, noPrefix) { + var classPrefix = noPrefix ? '' : options.classPrefix, + openSpan = ''; + + return openSpan + insideSpan + closeSpan; + } + + function processKeywords() { + if (!top.keywords) + return escape(mode_buffer); + var result = ''; + var last_index = 0; + top.lexemesRe.lastIndex = 0; + var match = top.lexemesRe.exec(mode_buffer); + while (match) { + result += escape(mode_buffer.substr(last_index, match.index - last_index)); + var keyword_match = keywordMatch(top, match); + if (keyword_match) { + relevance += keyword_match[1]; + result += buildSpan(keyword_match[0], escape(match[0])); + } else { + result += escape(match[0]); + } + last_index = top.lexemesRe.lastIndex; + match = top.lexemesRe.exec(mode_buffer); + } + return result + escape(mode_buffer.substr(last_index)); + } + + function processSubLanguage() { + var explicit = typeof top.subLanguage == 'string'; + if (explicit && !languages[top.subLanguage]) { + return escape(mode_buffer); + } + + var result = explicit ? + highlight(top.subLanguage, mode_buffer, true, continuations[top.subLanguage]) : + highlightAuto(mode_buffer, top.subLanguage.length ? top.subLanguage : undefined); + + // Counting embedded language score towards the host language may be disabled + // with zeroing the containing mode relevance. Usecase in point is Markdown that + // allows XML everywhere and makes every XML snippet to have a much larger Markdown + // score. + if (top.relevance > 0) { + relevance += result.relevance; + } + if (explicit) { + continuations[top.subLanguage] = result.top; + } + return buildSpan(result.language, result.value, false, true); + } + + function processBuffer() { + return top.subLanguage !== undefined ? processSubLanguage() : processKeywords(); + } + + function startNewMode(mode, lexeme) { + var markup = mode.className? buildSpan(mode.className, '', true): ''; + if (mode.returnBegin) { + result += markup; + mode_buffer = ''; + } else if (mode.excludeBegin) { + result += escape(lexeme) + markup; + mode_buffer = ''; + } else { + result += markup; + mode_buffer = lexeme; + } + top = Object.create(mode, {parent: {value: top}}); + } + + function processLexeme(buffer, lexeme) { + + mode_buffer += buffer; + if (lexeme === undefined) { + result += processBuffer(); + return 0; + } + + var new_mode = subMode(lexeme, top); + if (new_mode) { + result += processBuffer(); + startNewMode(new_mode, lexeme); + return new_mode.returnBegin ? 0 : lexeme.length; + } + + var end_mode = endOfMode(top, lexeme); + if (end_mode) { + var origin = top; + if (!(origin.returnEnd || origin.excludeEnd)) { + mode_buffer += lexeme; + } + result += processBuffer(); + do { + if (top.className) { + result += ''; + } + relevance += top.relevance; + top = top.parent; + } while (top != end_mode.parent); + if (origin.excludeEnd) { + result += escape(lexeme); + } + mode_buffer = ''; + if (end_mode.starts) { + startNewMode(end_mode.starts, ''); + } + return origin.returnEnd ? 0 : lexeme.length; + } + + if (isIllegal(lexeme, top)) + throw new Error('Illegal lexeme "' + lexeme + '" for mode "' + (top.className || '') + '"'); + + /* + Parser should not reach this point as all types of lexemes should be caught + earlier, but if it does due to some bug make sure it advances at least one + character forward to prevent infinite looping. + */ + mode_buffer += lexeme; + return lexeme.length || 1; + } + + var language = getLanguage(name); + if (!language) { + throw new Error('Unknown language: "' + name + '"'); + } + + compileLanguage(language); + var top = continuation || language; + var continuations = {}; // keep continuations for sub-languages + var result = '', current; + for(current = top; current != language; current = current.parent) { + if (current.className) { + result = buildSpan(current.className, '', true) + result; + } + } + var mode_buffer = ''; + var relevance = 0; + try { + var match, count, index = 0; + while (true) { + top.terminators.lastIndex = index; + match = top.terminators.exec(value); + if (!match) + break; + count = processLexeme(value.substr(index, match.index - index), match[0]); + index = match.index + count; + } + processLexeme(value.substr(index)); + for(current = top; current.parent; current = current.parent) { // close dangling modes + if (current.className) { + result += ''; + } + } + return { + relevance: relevance, + value: result, + language: name, + top: top + }; + } catch (e) { + if (e.message.indexOf('Illegal') != -1) { + return { + relevance: 0, + value: escape(value) + }; + } else { + throw e; + } + } + } + + /* + Highlighting with language detection. Accepts a string with the code to + highlight. Returns an object with the following properties: + + - language (detected language) + - relevance (int) + - value (an HTML string with highlighting markup) + - second_best (object with the same structure for second-best heuristically + detected language, may be absent) + + */ + function highlightAuto(text, languageSubset) { + languageSubset = languageSubset || options.languages || Object.keys(languages); + var result = { + relevance: 0, + value: escape(text) + }; + var second_best = result; + languageSubset.forEach(function(name) { + if (!getLanguage(name)) { + return; + } + var current = highlight(name, text, false); + current.language = name; + if (current.relevance > second_best.relevance) { + second_best = current; + } + if (current.relevance > result.relevance) { + second_best = result; + result = current; + } + }); + if (second_best.language) { + result.second_best = second_best; + } + return result; + } + + /* + Post-processing of the highlighted markup: + + - replace TABs with something more useful + - replace real line-breaks with '
' for non-pre containers + + */ + function fixMarkup(value) { + if (options.tabReplace) { + value = value.replace(/^((<[^>]+>|\t)+)/gm, function(match, p1 /*..., offset, s*/) { + return p1.replace(/\t/g, options.tabReplace); + }); + } + if (options.useBR) { + value = value.replace(/\n/g, '
'); + } + return value; + } + + function buildClassName(prevClassName, currentLang, resultLang) { + var language = currentLang ? aliases[currentLang] : resultLang, + result = [prevClassName.trim()]; + + if (!prevClassName.match(/\bhljs\b/)) { + result.push('hljs'); + } + + if (prevClassName.indexOf(language) === -1) { + result.push(language); + } + + return result.join(' ').trim(); + } + + /* + Applies highlighting to a DOM node containing code. Accepts a DOM node and + two optional parameters for fixMarkup. + */ + function highlightBlock(block) { + var language = blockLanguage(block); + if (isNotHighlighted(language)) + return; + + var node; + if (options.useBR) { + node = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + node.innerHTML = block.innerHTML.replace(/\n/g, '').replace(//g, '\n'); + } else { + node = block; + } + var text = node.textContent; + var result = language ? highlight(language, text, true) : highlightAuto(text); + + var originalStream = nodeStream(node); + if (originalStream.length) { + var resultNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); + resultNode.innerHTML = result.value; + result.value = mergeStreams(originalStream, nodeStream(resultNode), text); + } + result.value = fixMarkup(result.value); + + block.innerHTML = result.value; + block.className = buildClassName(block.className, language, result.language); + block.result = { + language: result.language, + re: result.relevance + }; + if (result.second_best) { + block.second_best = { + language: result.second_best.language, + re: result.second_best.relevance + }; + } + } + + var options = { + classPrefix: 'hljs-', + tabReplace: null, + useBR: false, + languages: undefined + }; + + /* + Updates highlight.js global options with values passed in the form of an object + */ + function configure(user_options) { + options = inherit(options, user_options); + } + + /* + Applies highlighting to all
..
blocks on a page. + */ + function initHighlighting() { + if (initHighlighting.called) + return; + initHighlighting.called = true; + + var blocks = document.querySelectorAll('.code-sample'); + Array.prototype.forEach.call(blocks, highlightBlock); + } + + /* + Attaches highlighting to the page load event. + */ + function initHighlightingOnLoad() { + addEventListener('DOMContentLoaded', initHighlighting, false); + addEventListener('load', initHighlighting, false); + } + + var languages = {}; + var aliases = {}; + + function registerLanguage(name, language) { + var lang = languages[name] = language(hljs); + if (lang.aliases) { + lang.aliases.forEach(function(alias) {aliases[alias] = name;}); + } + } + + function listLanguages() { + return Object.keys(languages); + } + + function getLanguage(name) { + name = (name || '').toLowerCase(); + return languages[name] || languages[aliases[name]]; + } + + /* Interface definition */ + + hljs.highlight = highlight; + hljs.highlightAuto = highlightAuto; + hljs.fixMarkup = fixMarkup; + hljs.highlightBlock = highlightBlock; + hljs.configure = configure; + hljs.initHighlighting = initHighlighting; + hljs.initHighlightingOnLoad = initHighlightingOnLoad; + hljs.registerLanguage = registerLanguage; + hljs.listLanguages = listLanguages; + hljs.getLanguage = getLanguage; + hljs.inherit = inherit; + + // Common regexps + hljs.IDENT_RE = '[a-zA-Z]\\w*'; + hljs.UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*'; + hljs.NUMBER_RE = '\\b\\d+(\\.\\d+)?'; + hljs.C_NUMBER_RE = '(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)'; // 0x..., 0..., decimal, float + hljs.BINARY_NUMBER_RE = '\\b(0b[01]+)'; // 0b... + hljs.RE_STARTERS_RE = '!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~'; + + // Common modes + hljs.BACKSLASH_ESCAPE = { + begin: '\\\\[\\s\\S]', relevance: 0 + }; + hljs.APOS_STRING_MODE = { + className: 'string', + begin: '\'', end: '\'', + illegal: '\\n', + contains: [hljs.BACKSLASH_ESCAPE] + }; + hljs.QUOTE_STRING_MODE = { + className: 'string', + begin: '"', end: '"', + illegal: '\\n', + contains: [hljs.BACKSLASH_ESCAPE] + }; + hljs.PHRASAL_WORDS_MODE = { + begin: /\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\b/ + }; + hljs.COMMENT = function (begin, end, inherits) { + var mode = hljs.inherit( + { + className: 'comment', + begin: begin, end: end, + contains: [] + }, + inherits || {} + ); + mode.contains.push(hljs.PHRASAL_WORDS_MODE); + mode.contains.push({ + className: 'doctag', + begin: "(?:TODO|FIXME|NOTE|BUG|XXX):", + relevance: 0 + }); + return mode; + }; + hljs.C_LINE_COMMENT_MODE = hljs.COMMENT('//', '$'); + hljs.C_BLOCK_COMMENT_MODE = hljs.COMMENT('/\\*', '\\*/'); + hljs.HASH_COMMENT_MODE = hljs.COMMENT('#', '$'); + hljs.NUMBER_MODE = { + className: 'number', + begin: hljs.NUMBER_RE, + relevance: 0 + }; + hljs.C_NUMBER_MODE = { + className: 'number', + begin: hljs.C_NUMBER_RE, + relevance: 0 + }; + hljs.BINARY_NUMBER_MODE = { + className: 'number', + begin: hljs.BINARY_NUMBER_RE, + relevance: 0 + }; + hljs.CSS_NUMBER_MODE = { + className: 'number', + begin: hljs.NUMBER_RE + '(' + + '%|em|ex|ch|rem' + + '|vw|vh|vmin|vmax' + + '|cm|mm|in|pt|pc|px' + + '|deg|grad|rad|turn' + + '|s|ms' + + '|Hz|kHz' + + '|dpi|dpcm|dppx' + + ')?', + relevance: 0 + }; + hljs.REGEXP_MODE = { + className: 'regexp', + begin: /\//, end: /\/[gimuy]*/, + illegal: /\n/, + contains: [ + hljs.BACKSLASH_ESCAPE, + { + begin: /\[/, end: /\]/, + relevance: 0, + contains: [hljs.BACKSLASH_ESCAPE] + } + ] + }; + hljs.TITLE_MODE = { + className: 'title', + begin: hljs.IDENT_RE, + relevance: 0 + }; + hljs.UNDERSCORE_TITLE_MODE = { + className: 'title', + begin: hljs.UNDERSCORE_IDENT_RE, + relevance: 0 + }; + +hljs.registerLanguage('python', function(hljs) { + var PROMPT = { + className: 'prompt', begin: /^(>>>|\.\.\.) / + }; + var STRING = { + className: 'string', + contains: [hljs.BACKSLASH_ESCAPE], + variants: [ + { + begin: /(u|b)?r?'''/, end: /'''/, + contains: [PROMPT], + relevance: 10 + }, + { + begin: /(u|b)?r?"""/, end: /"""/, + contains: [PROMPT], + relevance: 10 + }, + { + begin: /(u|r|ur)'/, end: /'/, + relevance: 10 + }, + { + begin: /(u|r|ur)"/, end: /"/, + relevance: 10 + }, + { + begin: /(b|br)'/, end: /'/ + }, + { + begin: /(b|br)"/, end: /"/ + }, + hljs.APOS_STRING_MODE, + hljs.QUOTE_STRING_MODE + ] + }; + var NUMBER = { + className: 'number', relevance: 0, + variants: [ + {begin: hljs.BINARY_NUMBER_RE + '[lLjJ]?'}, + {begin: '\\b(0o[0-7]+)[lLjJ]?'}, + {begin: hljs.C_NUMBER_RE + '[lLjJ]?'} + ] + }; + var PARAMS = { + className: 'params', + begin: /\(/, end: /\)/, + contains: ['self', PROMPT, NUMBER, STRING] + }; + return { + aliases: ['py', 'gyp'], + keywords: { + keyword: + 'and elif is global as in if from raise for except finally print import pass return ' + + 'exec else break not with class assert yield try while continue del or def lambda ' + + 'async await nonlocal|10 None True False', + built_in: + 'Ellipsis NotImplemented' + }, + illegal: /(<\/|->|\?)/, + contains: [ + PROMPT, + NUMBER, + STRING, + hljs.HASH_COMMENT_MODE, + { + variants: [ + {className: 'function', beginKeywords: 'def', relevance: 10}, + {className: 'class', beginKeywords: 'class'} + ], + end: /:/, + illegal: /[${=;\n,]/, + contains: [hljs.UNDERSCORE_TITLE_MODE, PARAMS] + }, + { + className: 'decorator', + begin: /^[\t ]*@/, end: /$/ + }, + { + begin: /\b(print|exec)\(/ // don’t highlight keywords-turned-functions in Python 3 + } + ] + }; +}); + + return hljs; +})); + +hljs.initHighlightingOnLoad();