shrink syntax highlighting bundle size
This commit is contained in:
parent
f80171f6ed
commit
7dd4d4833a
|
@ -11,8 +11,8 @@ The most popular languages that USACO supports are [C++11](https://en.wikipedia.
|
|||
|
||||
- If you already know one of these languages, just use it.
|
||||
- If you know multiple languages, we recommend you pick C++ over Java, and Java over Python.
|
||||
- For Bronze and Silver, any language will do.
|
||||
- For Gold and Platinum, Python is not recommended, because it is a slow language and lacks an ordered map.
|
||||
- For Bronze, any language will do.
|
||||
- For Silver<Asterisk>However, if Python is the only language you know / you really want to use Python, you can still pass Silver with Python.</Asterisk>, Gold, and Platinum, Python is not recommended, because it is a slow language and lacks an ordered map.
|
||||
- Check "Factors to Consider When Choosing a Language" for more information.
|
||||
|
||||
Keep in mind that it's easy to switch languages down the road. Don't get caught up on which language to choose. Just pick the one you feel most comfortable with!
|
||||
|
|
|
@ -30,8 +30,8 @@ It's okay to skip over these. Some material in these boxes might not be useful f
|
|||
|
||||
Code should compile by itself, example input / output should be provided. Macros should generally be avoided.
|
||||
|
||||
- For Bronze and Silver, we will provide code snippets in C++, Java, and Python.
|
||||
- For Gold, we will provide code snippets in C++ and Java and (sometimes) Python.
|
||||
- For Bronze, we will provide code snippets in C++, Java, and Python.
|
||||
- For Silver and Gold, we will provide code snippets in C++ and Java and (sometimes) Python.
|
||||
- For Platinum, code snippets might only be provided in C++.
|
||||
|
||||
<warning-block>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// File taken from https://github.com/FormidableLabs/prism-react-renderer/issues/54
|
||||
|
||||
import * as React from 'react';
|
||||
import Highlight, { defaultProps } from 'prism-react-renderer';
|
||||
import Highlight from './SyntaxHighlighting/Highlight';
|
||||
import vsDark from 'prism-react-renderer/themes/vsDark';
|
||||
import Prism from './SyntaxHighlighting/prism';
|
||||
|
||||
export default ({ children, className }) => {
|
||||
if (className === undefined) {
|
||||
|
@ -15,8 +16,9 @@ export default ({ children, className }) => {
|
|||
}
|
||||
const language = className.replace(/language-/, '');
|
||||
return (
|
||||
// @ts-ignore
|
||||
<Highlight
|
||||
{...defaultProps}
|
||||
Prism={Prism as any}
|
||||
code={children.trim()}
|
||||
language={language}
|
||||
theme={vsDark}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
// import * as React from 'react';
|
||||
// import renderMathInElement from 'katex/contrib/auto-render/auto-render';
|
||||
//
|
||||
// type KatexRendererProps = {
|
||||
// children?: React.ReactNode;
|
||||
// };
|
||||
//
|
||||
// export function KatexRenderer(props: KatexRendererProps) {
|
||||
// const ref = React.useRef();
|
||||
//
|
||||
// React.useEffect(() => {
|
||||
// renderMathInElement(ref.current, {
|
||||
// delimiters: [
|
||||
// { left: '$$', right: '$$', display: true },
|
||||
// { left: '$', right: '$', display: false },
|
||||
// ],
|
||||
// });
|
||||
// }, [props.children]);
|
||||
//
|
||||
// return <span ref={ref}>{props.children}</span>;
|
||||
// }
|
353
src/components/markdown/SyntaxHighlighting/Highlight.js
Normal file
353
src/components/markdown/SyntaxHighlighting/Highlight.js
Normal file
|
@ -0,0 +1,353 @@
|
|||
/* eslint-disable */
|
||||
|
||||
// taken from https://github.com/FormidableLabs/prism-react-renderer
|
||||
// really dumb issue: when importing from node_modules, gatsby/webpack doesn't tree-shake properly...
|
||||
|
||||
import { Component } from 'react';
|
||||
|
||||
function _defineProperty(obj, key, value) {
|
||||
if (key in obj) {
|
||||
Object.defineProperty(obj, key, {
|
||||
value: value,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
writable: true,
|
||||
});
|
||||
} else {
|
||||
obj[key] = value;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function _extends() {
|
||||
_extends =
|
||||
Object.assign ||
|
||||
function (target) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var source = arguments[i];
|
||||
|
||||
for (var key in source) {
|
||||
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
};
|
||||
|
||||
return _extends.apply(this, arguments);
|
||||
}
|
||||
|
||||
var newlineRe = /\r\n|\r|\n/; // Empty lines need to contain a single empty token, denoted with { empty: true }
|
||||
|
||||
var normalizeEmptyLines = function (line) {
|
||||
if (line.length === 0) {
|
||||
line.push({
|
||||
types: ['plain'],
|
||||
content: '',
|
||||
empty: true,
|
||||
});
|
||||
} else if (line.length === 1 && line[0].content === '') {
|
||||
line[0].empty = true;
|
||||
}
|
||||
};
|
||||
|
||||
var appendTypes = function (types, add) {
|
||||
var typesSize = types.length;
|
||||
|
||||
if (typesSize > 0 && types[typesSize - 1] === add) {
|
||||
return types;
|
||||
}
|
||||
|
||||
return types.concat(add);
|
||||
}; // Takes an array of Prism's tokens and groups them by line, turning plain
|
||||
// strings into tokens as well. Tokens can become recursive in some cases,
|
||||
// which means that their types are concatenated. Plain-string tokens however
|
||||
// are always of type "plain".
|
||||
// This is not recursive to avoid exceeding the call-stack limit, since it's unclear
|
||||
// how nested Prism's tokens can become
|
||||
|
||||
var normalizeTokens = function (tokens) {
|
||||
var typeArrStack = [[]];
|
||||
var tokenArrStack = [tokens];
|
||||
var tokenArrIndexStack = [0];
|
||||
var tokenArrSizeStack = [tokens.length];
|
||||
var i = 0;
|
||||
var stackIndex = 0;
|
||||
var currentLine = [];
|
||||
var acc = [currentLine];
|
||||
|
||||
while (stackIndex > -1) {
|
||||
while (
|
||||
(i = tokenArrIndexStack[stackIndex]++) < tokenArrSizeStack[stackIndex]
|
||||
) {
|
||||
var content = void 0;
|
||||
var types = typeArrStack[stackIndex];
|
||||
var tokenArr = tokenArrStack[stackIndex];
|
||||
var token = tokenArr[i]; // Determine content and append type to types if necessary
|
||||
|
||||
if (typeof token === 'string') {
|
||||
types = stackIndex > 0 ? types : ['plain'];
|
||||
content = token;
|
||||
} else {
|
||||
types = appendTypes(types, token.type);
|
||||
|
||||
if (token.alias) {
|
||||
types = appendTypes(types, token.alias);
|
||||
}
|
||||
|
||||
content = token.content;
|
||||
} // If token.content is an array, increase the stack depth and repeat this while-loop
|
||||
|
||||
if (typeof content !== 'string') {
|
||||
stackIndex++;
|
||||
typeArrStack.push(types);
|
||||
tokenArrStack.push(content);
|
||||
tokenArrIndexStack.push(0);
|
||||
tokenArrSizeStack.push(content.length);
|
||||
continue;
|
||||
} // Split by newlines
|
||||
|
||||
var splitByNewlines = content.split(newlineRe);
|
||||
var newlineCount = splitByNewlines.length;
|
||||
currentLine.push({
|
||||
types: types,
|
||||
content: splitByNewlines[0],
|
||||
}); // Create a new line for each string on a new line
|
||||
|
||||
for (var i$1 = 1; i$1 < newlineCount; i$1++) {
|
||||
normalizeEmptyLines(currentLine);
|
||||
acc.push((currentLine = []));
|
||||
currentLine.push({
|
||||
types: types,
|
||||
content: splitByNewlines[i$1],
|
||||
});
|
||||
}
|
||||
} // Decreate the stack depth
|
||||
|
||||
stackIndex--;
|
||||
typeArrStack.pop();
|
||||
tokenArrStack.pop();
|
||||
tokenArrIndexStack.pop();
|
||||
tokenArrSizeStack.pop();
|
||||
}
|
||||
|
||||
normalizeEmptyLines(currentLine);
|
||||
return acc;
|
||||
};
|
||||
|
||||
var themeToDict = function (theme, language) {
|
||||
var plain = theme.plain; // $FlowFixMe
|
||||
|
||||
var base = Object.create(null);
|
||||
var themeDict = theme.styles.reduce(function (acc, themeEntry) {
|
||||
var languages = themeEntry.languages;
|
||||
var style = themeEntry.style;
|
||||
|
||||
if (languages && !languages.includes(language)) {
|
||||
return acc;
|
||||
}
|
||||
|
||||
themeEntry.types.forEach(function (type) {
|
||||
// $FlowFixMe
|
||||
var accStyle = _extends({}, acc[type], style);
|
||||
|
||||
acc[type] = accStyle;
|
||||
});
|
||||
return acc;
|
||||
}, base); // $FlowFixMe
|
||||
|
||||
themeDict.root = plain; // $FlowFixMe
|
||||
|
||||
themeDict.plain = _extends({}, plain, {
|
||||
backgroundColor: null,
|
||||
});
|
||||
return themeDict;
|
||||
};
|
||||
|
||||
function objectWithoutProperties(obj, exclude) {
|
||||
var target = {};
|
||||
|
||||
for (var k in obj)
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(obj, k) &&
|
||||
exclude.indexOf(k) === -1
|
||||
)
|
||||
target[k] = obj[k];
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
var Highlight =
|
||||
/*@__PURE__*/
|
||||
(function (Component) {
|
||||
function Highlight() {
|
||||
var this$1 = this;
|
||||
var args = [],
|
||||
len = arguments.length;
|
||||
|
||||
while (len--) args[len] = arguments[len];
|
||||
|
||||
Component.apply(this, args);
|
||||
|
||||
_defineProperty(this, 'getThemeDict', function (props) {
|
||||
if (
|
||||
this$1.themeDict !== undefined &&
|
||||
props.theme === this$1.prevTheme &&
|
||||
props.language === this$1.prevLanguage
|
||||
) {
|
||||
return this$1.themeDict;
|
||||
}
|
||||
|
||||
this$1.prevTheme = props.theme;
|
||||
this$1.prevLanguage = props.language;
|
||||
var themeDict = props.theme
|
||||
? themeToDict(props.theme, props.language)
|
||||
: undefined;
|
||||
return (this$1.themeDict = themeDict);
|
||||
});
|
||||
|
||||
_defineProperty(this, 'getLineProps', function (ref) {
|
||||
var key = ref.key;
|
||||
var className = ref.className;
|
||||
var style = ref.style;
|
||||
var rest$1 = objectWithoutProperties(ref, [
|
||||
'key',
|
||||
'className',
|
||||
'style',
|
||||
'line',
|
||||
]);
|
||||
var rest = rest$1;
|
||||
|
||||
var output = _extends({}, rest, {
|
||||
className: 'token-line',
|
||||
style: undefined,
|
||||
key: undefined,
|
||||
});
|
||||
|
||||
var themeDict = this$1.getThemeDict(this$1.props);
|
||||
|
||||
if (themeDict !== undefined) {
|
||||
output.style = themeDict.plain;
|
||||
}
|
||||
|
||||
if (style !== undefined) {
|
||||
output.style =
|
||||
output.style !== undefined
|
||||
? _extends({}, output.style, style)
|
||||
: style;
|
||||
}
|
||||
|
||||
if (key !== undefined) {
|
||||
output.key = key;
|
||||
}
|
||||
|
||||
if (className) {
|
||||
output.className += ' ' + className;
|
||||
}
|
||||
|
||||
return output;
|
||||
});
|
||||
|
||||
_defineProperty(this, 'getStyleForToken', function (ref) {
|
||||
var types = ref.types;
|
||||
var empty = ref.empty;
|
||||
var typesSize = types.length;
|
||||
var themeDict = this$1.getThemeDict(this$1.props);
|
||||
|
||||
if (themeDict === undefined) {
|
||||
return undefined;
|
||||
} else if (typesSize === 1 && types[0] === 'plain') {
|
||||
return empty
|
||||
? {
|
||||
display: 'inline-block',
|
||||
}
|
||||
: undefined;
|
||||
} else if (typesSize === 1 && !empty) {
|
||||
return themeDict[types[0]];
|
||||
}
|
||||
|
||||
var baseStyle = empty
|
||||
? {
|
||||
display: 'inline-block',
|
||||
}
|
||||
: {}; // $FlowFixMe
|
||||
|
||||
var typeStyles = types.map(function (type) {
|
||||
return themeDict[type];
|
||||
});
|
||||
return Object.assign.apply(Object, [baseStyle].concat(typeStyles));
|
||||
});
|
||||
|
||||
_defineProperty(this, 'getTokenProps', function (ref) {
|
||||
var key = ref.key;
|
||||
var className = ref.className;
|
||||
var style = ref.style;
|
||||
var token = ref.token;
|
||||
var rest$1 = objectWithoutProperties(ref, [
|
||||
'key',
|
||||
'className',
|
||||
'style',
|
||||
'token',
|
||||
]);
|
||||
var rest = rest$1;
|
||||
|
||||
var output = _extends({}, rest, {
|
||||
className: 'token ' + token.types.join(' '),
|
||||
children: token.content,
|
||||
style: this$1.getStyleForToken(token),
|
||||
key: undefined,
|
||||
});
|
||||
|
||||
if (style !== undefined) {
|
||||
output.style =
|
||||
output.style !== undefined
|
||||
? _extends({}, output.style, style)
|
||||
: style;
|
||||
}
|
||||
|
||||
if (key !== undefined) {
|
||||
output.key = key;
|
||||
}
|
||||
|
||||
if (className) {
|
||||
output.className += ' ' + className;
|
||||
}
|
||||
|
||||
return output;
|
||||
});
|
||||
}
|
||||
|
||||
if (Component) Highlight.__proto__ = Component;
|
||||
Highlight.prototype = Object.create(Component && Component.prototype);
|
||||
Highlight.prototype.constructor = Highlight;
|
||||
|
||||
Highlight.prototype.render = function render() {
|
||||
var ref = this.props;
|
||||
var Prism = ref.Prism;
|
||||
var language = ref.language;
|
||||
var code = ref.code;
|
||||
var children = ref.children;
|
||||
var themeDict = this.getThemeDict(this.props);
|
||||
var grammar = Prism.languages[language];
|
||||
var mixedTokens =
|
||||
grammar !== undefined
|
||||
? Prism.tokenize(code, grammar, language)
|
||||
: [code];
|
||||
var tokens = normalizeTokens(mixedTokens);
|
||||
return children({
|
||||
tokens: tokens,
|
||||
className: 'prism-code language-' + language,
|
||||
style: themeDict !== undefined ? themeDict.root : {},
|
||||
getLineProps: this.getLineProps,
|
||||
getTokenProps: this.getTokenProps,
|
||||
});
|
||||
};
|
||||
|
||||
return Highlight;
|
||||
})(Component);
|
||||
|
||||
export default Highlight;
|
||||
// export { defaultProps };
|
645
src/components/markdown/SyntaxHighlighting/prism.js
Normal file
645
src/components/markdown/SyntaxHighlighting/prism.js
Normal file
|
@ -0,0 +1,645 @@
|
|||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* me (thecodingwizard):
|
||||
* - added C++, Java, Python syntax highlighting manually
|
||||
* - oops this is really dumb but I couldn't get tree-shaking to work properly when importing from node_modules >:-(
|
||||
*/
|
||||
|
||||
var Prism = (function () {
|
||||
// Private helper vars
|
||||
var lang = /\blang(?:uage)?-([\w-]+)\b/i;
|
||||
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, '&')
|
||||
.replace(/</g, '<')
|
||||
.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, '"') +
|
||||
'"'
|
||||
);
|
||||
})
|
||||
.join(' ');
|
||||
|
||||
return (
|
||||
'<' +
|
||||
env.tag +
|
||||
' class="' +
|
||||
env.classes.join(' ') +
|
||||
'"' +
|
||||
(attributes ? ' ' + attributes : '') +
|
||||
'>' +
|
||||
env.content +
|
||||
'</' +
|
||||
env.tag +
|
||||
'>'
|
||||
);
|
||||
};
|
||||
|
||||
return _;
|
||||
})();
|
||||
|
||||
/* "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-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-python" */
|
||||
|
||||
Prism.languages.python = {
|
||||
comment: {
|
||||
pattern: /(^|[^\\])#.*/,
|
||||
lookbehind: true,
|
||||
},
|
||||
'string-interpolation': {
|
||||
pattern: /(?:f|rf|fr)(?:("""|''')[\s\S]+?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,
|
||||
greedy: true,
|
||||
inside: {
|
||||
interpolation: {
|
||||
// "{" <expression> <optional "!s", "!r", or "!a"> <optional ":" format specifier> "}"
|
||||
pattern: /((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,
|
||||
lookbehind: true,
|
||||
inside: {
|
||||
'format-spec': {
|
||||
pattern: /(:)[^:(){}]+(?=}$)/,
|
||||
lookbehind: true,
|
||||
},
|
||||
'conversion-option': {
|
||||
pattern: /![sra](?=[:}]$)/,
|
||||
alias: 'punctuation',
|
||||
},
|
||||
rest: null,
|
||||
},
|
||||
},
|
||||
string: /[\s\S]+/,
|
||||
},
|
||||
},
|
||||
'triple-quoted-string': {
|
||||
pattern: /(?:[rub]|rb|br)?("""|''')[\s\S]+?\1/i,
|
||||
greedy: true,
|
||||
alias: 'string',
|
||||
},
|
||||
string: {
|
||||
pattern: /(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,
|
||||
greedy: true,
|
||||
},
|
||||
function: {
|
||||
pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,
|
||||
lookbehind: true,
|
||||
},
|
||||
'class-name': {
|
||||
pattern: /(\bclass\s+)\w+/i,
|
||||
lookbehind: true,
|
||||
},
|
||||
decorator: {
|
||||
pattern: /(^\s*)@\w+(?:\.\w+)*/i,
|
||||
lookbehind: true,
|
||||
alias: ['annotation', 'punctuation'],
|
||||
inside: {
|
||||
punctuation: /\./,
|
||||
},
|
||||
},
|
||||
keyword: /\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
|
||||
builtin: /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,
|
||||
boolean: /\b(?:True|False|None)\b/,
|
||||
number: /(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,
|
||||
operator: /[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
|
||||
punctuation: /[{}[\];(),.:]/,
|
||||
};
|
||||
Prism.languages.python['string-interpolation'].inside[
|
||||
'interpolation'
|
||||
].inside.rest = Prism.languages.python;
|
||||
Prism.languages.py = Prism.languages.python;
|
||||
|
||||
export default Prism;
|
Reference in a new issue