From 423ed3f671bc5a267e8ddb6e28cf36f89f0253a1 Mon Sep 17 00:00:00 2001 From: Michael Catanzaro Date: Mon, 8 Feb 2021 09:36:26 -0600 Subject: Update to highlight.js 10.6.0 --- third-party/highlightjs/highlight.js | 729 ++++++++++++++++++++++++++++++----- 1 file changed, 625 insertions(+), 104 deletions(-) diff --git a/third-party/highlightjs/highlight.js b/third-party/highlightjs/highlight.js index de28408ef..7ba6c4f29 100644 --- a/third-party/highlightjs/highlight.js +++ b/third-party/highlightjs/highlight.js @@ -1,5 +1,5 @@ /* - Highlight.js 10.5.0 (af20048d) + Highlight.js 10.6.0 (eb122d3b) License: BSD-3-Clause Copyright (c) 2006-2020, Ivan Sagalaev */ @@ -446,6 +446,7 @@ var hljs = (function () { } // Common regexps + const MATCH_NOTHING_RE = /\b\B/; const IDENT_RE = '[a-zA-Z]\\w*'; const UNDERSCORE_IDENT_RE = '[a-zA-Z_]\\w*'; const NUMBER_RE = '\\b\\d+(\\.\\d+)?'; @@ -614,6 +615,7 @@ var hljs = (function () { var MODES = /*#__PURE__*/Object.freeze({ __proto__: null, + MATCH_NOTHING_RE: MATCH_NOTHING_RE, IDENT_RE: IDENT_RE, UNDERSCORE_IDENT_RE: UNDERSCORE_IDENT_RE, NUMBER_RE: NUMBER_RE, @@ -689,6 +691,11 @@ var hljs = (function () { mode.__beforeBegin = skipIfhasPrecedingDot; mode.keywords = mode.keywords || mode.beginKeywords; delete mode.beginKeywords; + + // prevents double relevance, the keywords themselves provide + // relevance, the mode doesn't need to double it + // eslint-disable-next-line no-undefined + if (mode.relevance === undefined) mode.relevance = 0; } /** @@ -737,21 +744,31 @@ var hljs = (function () { 'value' // common variable name ]; + const DEFAULT_KEYWORD_CLASSNAME = "keyword"; + /** * Given raw keywords from a language definition, compile them. * - * @param {string | Record} rawKeywords + * @param {string | Record | Array} rawKeywords * @param {boolean} caseInsensitive */ - function compileKeywords(rawKeywords, caseInsensitive) { + function compileKeywords(rawKeywords, caseInsensitive, className = DEFAULT_KEYWORD_CLASSNAME) { /** @type KeywordDict */ const compiledKeywords = {}; - if (typeof rawKeywords === 'string') { // string - splitAndCompile('keyword', rawKeywords); + // input can be a string of keywords, an array of keywords, or a object with + // named keys representing className (which can then point to a string or array) + if (typeof rawKeywords === 'string') { + compileList(className, rawKeywords.split(" ")); + } else if (Array.isArray(rawKeywords)) { + compileList(className, rawKeywords); } else { Object.keys(rawKeywords).forEach(function(className) { - splitAndCompile(className, rawKeywords[className]); + // collapse all our objects back into the parent object + Object.assign( + compiledKeywords, + compileKeywords(rawKeywords[className], caseInsensitive, className) + ); }); } return compiledKeywords; @@ -764,13 +781,13 @@ var hljs = (function () { * Ex: "for if when while|5" * * @param {string} className - * @param {string} keywordList + * @param {Array} keywordList */ - function splitAndCompile(className, keywordList) { + function compileList(className, keywordList) { if (caseInsensitive) { - keywordList = keywordList.toLowerCase(); + keywordList = keywordList.map(x => x.toLowerCase()); } - keywordList.split(' ').forEach(function(keyword) { + keywordList.forEach(function(keyword) { const pair = keyword.split('|'); compiledKeywords[pair[0]] = [className, scoreForKeyword(pair[0], pair[1])]; }); @@ -1217,7 +1234,7 @@ var hljs = (function () { return mode; } - var version = "10.5.0"; + var version = "10.6.0"; // @ts-nocheck @@ -1579,9 +1596,9 @@ var hljs = (function () { // a before plugin can usurp the result completely by providing it's own // in which case we don't even need to call highlight - const result = context.result ? - context.result : - _highlight(context.language, context.code, ignoreIllegals, continuation); + const result = context.result + ? context.result + : _highlight(context.language, context.code, ignoreIllegals, continuation); result.code = context.code; // the plugin can change anything in result to suite it @@ -1969,7 +1986,9 @@ var hljs = (function () { result = emitter.toHTML(); return { - relevance: relevance, + // avoid possible breakage with v10 clients expecting + // this to always be an integer + relevance: Math.floor(relevance), value: result, language: languageName, illegal: false, @@ -2200,18 +2219,47 @@ var hljs = (function () { * * @type {Function & {called?: boolean}} */ + // TODO: remove v12, deprecated const initHighlighting = () => { if (initHighlighting.called) return; initHighlighting.called = true; + deprecated("10.6.0", "initHighlighting() is deprecated. Use highlightAll() instead."); + const blocks = document.querySelectorAll('pre code'); blocks.forEach(highlightBlock); }; // Higlights all when DOMContentLoaded fires + // TODO: remove v12, deprecated function initHighlightingOnLoad() { - // @ts-ignore - window.addEventListener('DOMContentLoaded', initHighlighting, false); + deprecated("10.6.0", "initHighlightingOnLoad() is deprecated. Use highlightAll() instead."); + wantsHighlight = true; + } + + let wantsHighlight = false; + let domLoaded = false; + + /** + * auto-highlights all pre>code elements on the page + */ + function highlightAll() { + // if we are called too early in the loading process + if (!domLoaded) { wantsHighlight = true; return; } + + const blocks = document.querySelectorAll('pre code'); + blocks.forEach(highlightBlock); + } + + function boot() { + domLoaded = true; + // if a highlight was requested before DOM was loaded, do now + if (wantsHighlight) highlightAll(); + } + + // make sure we are in the browser environment + if (typeof window !== 'undefined' && window.addEventListener) { + window.addEventListener('DOMContentLoaded', boot, false); } /** @@ -2339,6 +2387,7 @@ var hljs = (function () { Object.assign(hljs, { highlight, highlightAuto, + highlightAll, fixMarkup: deprecateFixMarkup, highlightBlock, configure, @@ -2389,6 +2438,466 @@ if (typeof exports === 'object' && typeof module !== 'undefined') { module.expor hljs.registerLanguage('css', function () { 'use strict'; + const MODES = (hljs) => { + return { + IMPORTANT: { + className: 'meta', + begin: '!important' + }, + HEXCOLOR: { + className: 'number', + begin: '#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})' + }, + ATTRIBUTE_SELECTOR_MODE: { + className: 'selector-attr', + begin: /\[/, + end: /\]/, + illegal: '$', + contains: [ + hljs.APOS_STRING_MODE, + hljs.QUOTE_STRING_MODE + ] + } + }; + }; + + const TAGS = [ + 'a', + 'abbr', + 'address', + 'article', + 'aside', + 'audio', + 'b', + 'blockquote', + 'body', + 'button', + 'canvas', + 'caption', + 'cite', + 'code', + 'dd', + 'del', + 'details', + 'dfn', + 'div', + 'dl', + 'dt', + 'em', + 'fieldset', + 'figcaption', + 'figure', + 'footer', + 'form', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'header', + 'hgroup', + 'html', + 'i', + 'iframe', + 'img', + 'input', + 'ins', + 'kbd', + 'label', + 'legend', + 'li', + 'main', + 'mark', + 'menu', + 'nav', + 'object', + 'ol', + 'p', + 'q', + 'quote', + 'samp', + 'section', + 'span', + 'strong', + 'summary', + 'sup', + 'table', + 'tbody', + 'td', + 'textarea', + 'tfoot', + 'th', + 'thead', + 'time', + 'tr', + 'ul', + 'var', + 'video' + ]; + + const MEDIA_FEATURES = [ + 'any-hover', + 'any-pointer', + 'aspect-ratio', + 'color', + 'color-gamut', + 'color-index', + 'device-aspect-ratio', + 'device-height', + 'device-width', + 'display-mode', + 'forced-colors', + 'grid', + 'height', + 'hover', + 'inverted-colors', + 'monochrome', + 'orientation', + 'overflow-block', + 'overflow-inline', + 'pointer', + 'prefers-color-scheme', + 'prefers-contrast', + 'prefers-reduced-motion', + 'prefers-reduced-transparency', + 'resolution', + 'scan', + 'scripting', + 'update', + 'width', + // TODO: find a better solution? + 'min-width', + 'max-width', + 'min-height', + 'max-height' + ]; + + // https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes + const PSEUDO_CLASSES = [ + 'active', + 'any-link', + 'blank', + 'checked', + 'current', + 'default', + 'defined', + 'dir', // dir() + 'disabled', + 'drop', + 'empty', + 'enabled', + 'first', + 'first-child', + 'first-of-type', + 'fullscreen', + 'future', + 'focus', + 'focus-visible', + 'focus-within', + 'has', // has() + 'host', // host or host() + 'host-context', // host-context() + 'hover', + 'indeterminate', + 'in-range', + 'invalid', + 'is', // is() + 'lang', // lang() + 'last-child', + 'last-of-type', + 'left', + 'link', + 'local-link', + 'not', // not() + 'nth-child', // nth-child() + 'nth-col', // nth-col() + 'nth-last-child', // nth-last-child() + 'nth-last-col', // nth-last-col() + 'nth-last-of-type', //nth-last-of-type() + 'nth-of-type', //nth-of-type() + 'only-child', + 'only-of-type', + 'optional', + 'out-of-range', + 'past', + 'placeholder-shown', + 'read-only', + 'read-write', + 'required', + 'right', + 'root', + 'scope', + 'target', + 'target-within', + 'user-invalid', + 'valid', + 'visited', + 'where' // where() + ]; + + // https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements + const PSEUDO_ELEMENTS = [ + 'after', + 'backdrop', + 'before', + 'cue', + 'cue-region', + 'first-letter', + 'first-line', + 'grammar-error', + 'marker', + 'part', + 'placeholder', + 'selection', + 'slotted', + 'spelling-error' + ]; + + const ATTRIBUTES = [ + 'align-content', + 'align-items', + 'align-self', + 'animation', + 'animation-delay', + 'animation-direction', + 'animation-duration', + 'animation-fill-mode', + 'animation-iteration-count', + 'animation-name', + 'animation-play-state', + 'animation-timing-function', + 'auto', + 'backface-visibility', + 'background', + 'background-attachment', + 'background-clip', + 'background-color', + 'background-image', + 'background-origin', + 'background-position', + 'background-repeat', + 'background-size', + 'border', + 'border-bottom', + 'border-bottom-color', + 'border-bottom-left-radius', + 'border-bottom-right-radius', + 'border-bottom-style', + 'border-bottom-width', + 'border-collapse', + 'border-color', + 'border-image', + 'border-image-outset', + 'border-image-repeat', + 'border-image-slice', + 'border-image-source', + 'border-image-width', + 'border-left', + 'border-left-color', + 'border-left-style', + 'border-left-width', + 'border-radius', + 'border-right', + 'border-right-color', + 'border-right-style', + 'border-right-width', + 'border-spacing', + 'border-style', + 'border-top', + 'border-top-color', + 'border-top-left-radius', + 'border-top-right-radius', + 'border-top-style', + 'border-top-width', + 'border-width', + 'bottom', + 'box-decoration-break', + 'box-shadow', + 'box-sizing', + 'break-after', + 'break-before', + 'break-inside', + 'caption-side', + 'clear', + 'clip', + 'clip-path', + 'color', + 'column-count', + 'column-fill', + 'column-gap', + 'column-rule', + 'column-rule-color', + 'column-rule-style', + 'column-rule-width', + 'column-span', + 'column-width', + 'columns', + 'content', + 'counter-increment', + 'counter-reset', + 'cursor', + 'direction', + 'display', + 'empty-cells', + 'filter', + 'flex', + 'flex-basis', + 'flex-direction', + 'flex-flow', + 'flex-grow', + 'flex-shrink', + 'flex-wrap', + 'float', + 'font', + 'font-display', + 'font-family', + 'font-feature-settings', + 'font-kerning', + 'font-language-override', + 'font-size', + 'font-size-adjust', + 'font-stretch', + 'font-style', + 'font-variant', + 'font-variant-ligatures', + 'font-variation-settings', + 'font-weight', + 'height', + 'hyphens', + 'icon', + 'image-orientation', + 'image-rendering', + 'image-resolution', + 'ime-mode', + 'inherit', + 'initial', + 'justify-content', + 'left', + 'letter-spacing', + 'line-height', + 'list-style', + 'list-style-image', + 'list-style-position', + 'list-style-type', + 'margin', + 'margin-bottom', + 'margin-left', + 'margin-right', + 'margin-top', + 'marks', + 'mask', + 'max-height', + 'max-width', + 'min-height', + 'min-width', + 'nav-down', + 'nav-index', + 'nav-left', + 'nav-right', + 'nav-up', + 'none', + 'normal', + 'object-fit', + 'object-position', + 'opacity', + 'order', + 'orphans', + 'outline', + 'outline-color', + 'outline-offset', + 'outline-style', + 'outline-width', + 'overflow', + 'overflow-wrap', + 'overflow-x', + 'overflow-y', + 'padding', + 'padding-bottom', + 'padding-left', + 'padding-right', + 'padding-top', + 'page-break-after', + 'page-break-before', + 'page-break-inside', + 'perspective', + 'perspective-origin', + 'pointer-events', + 'position', + 'quotes', + 'resize', + 'right', + 'src', // @font-face + 'tab-size', + 'table-layout', + 'text-align', + 'text-align-last', + 'text-decoration', + 'text-decoration-color', + 'text-decoration-line', + 'text-decoration-style', + 'text-indent', + 'text-overflow', + 'text-rendering', + 'text-shadow', + 'text-transform', + 'text-underline-position', + 'top', + 'transform', + 'transform-origin', + 'transform-style', + 'transition', + 'transition-delay', + 'transition-duration', + 'transition-property', + 'transition-timing-function', + 'unicode-bidi', + 'vertical-align', + 'visibility', + 'white-space', + 'widows', + 'width', + 'word-break', + 'word-spacing', + 'word-wrap', + 'z-index' + // reverse makes sure longer attributes `font-weight` are matched fully + // instead of getting false positives on say `font` + ].reverse(); + + /** + * @param {string} value + * @returns {RegExp} + * */ + + /** + * @param {RegExp | string } re + * @returns {string} + */ + function source(re) { + if (!re) return null; + if (typeof re === "string") return re; + + return re.source; + } + + /** + * @param {RegExp | string } re + * @returns {string} + */ + function lookahead(re) { + return concat('(?=', re, ')'); + } + + /** + * @param {...(RegExp | string) } args + * @returns {string} + */ + function concat(...args) { + const joined = args.map((x) => source(x)).join(""); + return joined; + } + /* Language: CSS Category: common, css @@ -2397,127 +2906,139 @@ hljs.registerLanguage('css', function () { /** @type LanguageFn */ function css(hljs) { - var FUNCTION_LIKE = { - begin: /[\w-]+\(/, returnBegin: true, - contains: [ - { - className: 'built_in', - begin: /[\w-]+/ - }, - { - begin: /\(/, end: /\)/, - contains: [ - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE, - hljs.CSS_NUMBER_MODE, - ] - } - ] - }; - var ATTRIBUTE = { - className: 'attribute', - begin: /\S/, end: ':', excludeEnd: true, - starts: { - endsWithParent: true, excludeEnd: true, - contains: [ - FUNCTION_LIKE, - hljs.CSS_NUMBER_MODE, - hljs.QUOTE_STRING_MODE, - hljs.APOS_STRING_MODE, - hljs.C_BLOCK_COMMENT_MODE, - { - className: 'number', begin: '#[0-9A-Fa-f]+' - }, - { - className: 'meta', begin: '!important' - } - ] - } + const modes = MODES(hljs); + const FUNCTION_DISPATCH = { + className: "built_in", + begin: /[\w-]+(?=\()/ }; - var AT_IDENTIFIER = '@[a-z-]+'; // @font-face - var AT_MODIFIERS = "and or not only"; - var AT_PROPERTY_RE = /@-?\w[\w]*(-\w+)*/; // @-webkit-keyframes - var IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*'; - var RULE = { - begin: /([*]\s?)?(?:[A-Z_.\-\\]+|--[a-zA-Z0-9_-]+)\s*(\/\*\*\/)?:/, returnBegin: true, end: ';', endsWithParent: true, - contains: [ - ATTRIBUTE - ] + const VENDOR_PREFIX = { + begin: /-(webkit|moz|ms|o)-(?=[a-z])/ }; + const AT_MODIFIERS = "and or not only"; + const AT_PROPERTY_RE = /@-?\w[\w]*(-\w+)*/; // @-webkit-keyframes + const IDENT_RE = '[a-zA-Z-][a-zA-Z0-9_-]*'; + const STRINGS = [ + hljs.APOS_STRING_MODE, + hljs.QUOTE_STRING_MODE + ]; return { name: 'CSS', case_insensitive: true, illegal: /[=|'\$]/, + keywords: { + keyframePosition: "from to" + }, + classNameAliases: { + // for visual continuity with `tag {}` and because we + // don't have a great class for this? + keyframePosition: "selector-tag" + }, contains: [ hljs.C_BLOCK_COMMENT_MODE, + VENDOR_PREFIX, + // to recognize keyframe 40% etc which are outside the scope of our + // attribute value mode + hljs.CSS_NUMBER_MODE, { - className: 'selector-id', begin: /#[A-Za-z0-9_-]+/ + className: 'selector-id', + begin: /#[A-Za-z0-9_-]+/, + relevance: 0 }, { - className: 'selector-class', begin: '\\.' + IDENT_RE + className: 'selector-class', + begin: '\\.' + IDENT_RE, + relevance: 0 }, + modes.ATTRIBUTE_SELECTOR_MODE, { - className: 'selector-attr', - begin: /\[/, end: /\]/, - illegal: '$', - contains: [ - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE, + className: 'selector-pseudo', + variants: [ + { + begin: ':(' + PSEUDO_CLASSES.join('|') + ')' + }, + { + begin: '::(' + PSEUDO_ELEMENTS.join('|') + ')' + } ] }, + // we may actually need this (12/2020) + // { // pseudo-selector params + // begin: /\(/, + // end: /\)/, + // contains: [ hljs.CSS_NUMBER_MODE ] + // }, { - className: 'selector-pseudo', - begin: /:(:)?[a-zA-Z0-9_+()"'.-]+/ + className: 'attribute', + begin: '\\b(' + ATTRIBUTES.join('|') + ')\\b' }, - // matching these here allows us to treat them more like regular CSS - // rules so everything between the {} gets regular rule highlighting, - // which is what we want for page and font-face + // attribute values { - begin: '@(page|font-face)', - lexemes: AT_IDENTIFIER, - keywords: '@page @font-face' + begin: ':', + end: '[;}]', + contains: [ + modes.HEXCOLOR, + modes.IMPORTANT, + hljs.CSS_NUMBER_MODE, + ...STRINGS, + // needed to highlight these as strings and to avoid issues with + // illegal characters that might be inside urls that would tigger the + // languages illegal stack + { + begin: /(url|data-uri)\(/, + end: /\)/, + relevance: 0, // from keywords + keywords: { + built_in: "url data-uri" + }, + contains: [ + { + className: "string", + // any character other than `)` as in `url()` will be the start + // of a string, which ends with `)` (from the parent mode) + begin: /[^)]/, + endsWithParent: true, + excludeEnd: true + } + ] + }, + FUNCTION_DISPATCH + ] }, { - begin: '@', end: '[{;]', // at_rule eating first "{" is a good thing - // because it doesn’t let it to be parsed as - // a rule set but instead drops parser into - // the default mode which is how it should be. + begin: lookahead(/@/), + end: '[{;]', + relevance: 0, illegal: /:/, // break on Less variables @var: ... - returnBegin: true, contains: [ { className: 'keyword', begin: AT_PROPERTY_RE }, { - begin: /\s/, endsWithParent: true, excludeEnd: true, + begin: /\s/, + endsWithParent: true, + excludeEnd: true, relevance: 0, - keywords: AT_MODIFIERS, + keywords: { + $pattern: /[a-z-]+/, + keyword: AT_MODIFIERS, + attribute: MEDIA_FEATURES.join(" ") + }, contains: [ { - begin: /[a-z-]+:/, - className:"attribute" + begin: /[a-z-]+(?=:)/, + className: "attribute" }, - hljs.APOS_STRING_MODE, - hljs.QUOTE_STRING_MODE, + ...STRINGS, hljs.CSS_NUMBER_MODE ] } ] }, { - className: 'selector-tag', begin: IDENT_RE, - relevance: 0 - }, - { - begin: /\{/, end: /\}/, - illegal: /\S/, - contains: [ - hljs.C_BLOCK_COMMENT_MODE, - { begin: /;/ }, // empty ; rule - RULE, - ] + className: 'selector-tag', + begin: '\\b(' + TAGS.join('|') + ')\\b' } ] }; @@ -2760,9 +3281,9 @@ hljs.registerLanguage('javascript', function () { }; const KEYWORDS$1 = { $pattern: IDENT_RE, - keyword: KEYWORDS.join(" "), - literal: LITERALS.join(" "), - built_in: BUILT_INS.join(" ") + keyword: KEYWORDS, + literal: LITERALS, + built_in: BUILT_INS }; // https://tc39.es/ecma262/#sec-literals-numeric-literals @@ -3204,7 +3725,7 @@ hljs.registerLanguage('xml', function () { /** @type LanguageFn */ function xml(hljs) { // Element names can contain letters, digits, hyphens, underscores, and periods - const TAG_NAME_RE = concat(/[A-Z_]/, optional(/[A-Z0-9_.-]+:/), /[A-Z0-9_.-]*/); + const TAG_NAME_RE = concat(/[A-Z_]/, optional(/[A-Z0-9_.-]*:/), /[A-Z0-9_.-]*/); const XML_IDENT_RE = /[A-Za-z0-9._:-]+/; const XML_ENTITIES = { className: 'symbol', -- cgit v1.2.1